Implemented just enough of tcpip32.dll and dependencies to run FINGER.EXE.

Finger (etc) also rely on MPTN\DLL\tnls32.dll, which I pulled out a copy of
OS/2 Warp 4.52, which loads and limps along enough to not be a problem.
Reimplementing that library is going to be a pain, so that's a job for another
day. Inexplicably, tnls32 references pmgpi.dll's GpiQueryTextBox(), so I put a
stub for that in, too, but we're nowhere near really implementing GPI yet.

This is enough to run "finger.exe icculus@icculus.org" and see my .plan file,
which I consider a victory. A few more TCP/IP command line tools aren't far
behind.
This commit is contained in:
Ryan C. Gordon committed 2017-12-21 17:53:05 -05:00
1 parent fabd3be3e6
commit b72ccd6e5a
8 files changed
+395 -1

No files matched your search

+1 -1
View File
@@ -64,7 +64,7 @@ elseif(CURSES_HAVE_CURSES_H)
add_definitions(-DHAVE_CURSES_H)
endif()
foreach(_I doscalls;msg;nls;quecalls;viocalls;kbdcalls;sesmgr)
foreach(_I doscalls;msg;nls;quecalls;viocalls;kbdcalls;sesmgr;som;pmwin;pmshapi;pmgpi;tcpip32)
add_library(${_I} SHARED "native/${_I}.c")
set_target_properties(${_I} PROPERTIES COMPILE_FLAGS "-m32")
set_target_properties(${_I} PROPERTIES LINK_FLAGS "-m32 -ggdb3")
+2
View File
@@ -15,6 +15,8 @@
#include "msg.h"
#include "nls.h"
#include "sesmgr.h"
#include "pmgpi.h"
#include "tcpip32.h"
#endif
+1
View File
@@ -41,6 +41,7 @@ void OS2EXPORT lxNativeModuleDeinit(void);
static const LxExport lx_native_exports[] = {
#define LX_NATIVE_EXPORT(fn, ord) { ord, #fn, fn, NULL }
#define LX_NATIVE_EXPORT_DIFFERENT_NAME(fn, fnname, ord) { ord, fnname, fn, NULL }
#define LX_NATIVE_MODULE_INIT_END() \
}; \
+3
View File
@@ -37,6 +37,8 @@ typedef uint32_t APIRET;
typedef uint16_t APIRET16;
typedef uint32_t APIRET32;
typedef uint32_t BOOL;
typedef void VOID;
typedef VOID *PVOID;
typedef PVOID *PPVOID;
@@ -64,6 +66,7 @@ typedef HANDLE HDIR, *PHDIR;
typedef HANDLE HEV, *PHEV;
typedef HANDLE HMTX, *PHMTX;
typedef HANDLE HQUEUE, *PHQUEUE;
typedef HANDLE HPS, *PHPS;
typedef HANDLE PID, *PPID;
typedef HANDLE TID, *PTID;
typedef SHANDLE HVIO, *PHVIO;
+16
View File
@@ -0,0 +1,16 @@
#include "os2native.h"
#include "pmgpi.h"
BOOL GpiQueryTextBox(HPS hps, LONG lCount1, PCH pchString, LONG lCount2, PPOINTL aptlPoints)
{
TRACE_NATIVE("GpiQueryTextBox(%u, %d, '%s', %d, %p)", (unsigned int) hps, (int) lCount1, pchString, (int) lCount2, aptlPoints);
FIXME("write me");
return 0;
} // GpiQueryTextBox
LX_NATIVE_MODULE_INIT()
LX_NATIVE_EXPORT(GpiQueryTextBox, 489)
LX_NATIVE_MODULE_INIT_END()
// end of pmgpi.c ...
+25
View File
@@ -0,0 +1,25 @@
#ifndef _INCL_PMGPI_H_
#define _INCL_PMGPI_H_
#include "os2types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
int32_t x;
int32_t y;
} POINTL, *PPOINTL;
OS2EXPORT BOOL OS2API GpiQueryTextBox(HPS hps, LONG lCount1, PCH pchString, LONG lCount2, PPOINTL aptlPoints);
#ifdef __cplusplus
}
#endif
#endif
// end of pmgpi.h ...
+238
View File
@@ -0,0 +1,238 @@
#include "os2native.h"
#include "tcpip32.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
int OS2_sock_init(void)
{
TRACE_NATIVE("sock_init()");
return 1; // always succeeds.
} // OS2_sock_init
static int mapOS2MsgFlags(const int os2flags)
{
int bsdflags = 0;
#define MAPSOCKFLAGS(f) if (os2flags & OS2_##f) { bsdflags |= f; }
MAPSOCKFLAGS(MSG_OOB);
MAPSOCKFLAGS(MSG_PEEK);
MAPSOCKFLAGS(MSG_DONTROUTE);
MAPSOCKFLAGS(MSG_EOR);
MAPSOCKFLAGS(MSG_TRUNC);
MAPSOCKFLAGS(MSG_CTRUNC);
MAPSOCKFLAGS(MSG_WAITALL);
MAPSOCKFLAGS(MSG_DONTWAIT);
#undef MAPSOCKFLAGS
// !!! FIXME: no such flag on Linux
//MAPSOCKFLAGS(MSG_FULLREAD);
return bsdflags;
} // mapOS2MsgFlags
int OS2_recv(int sock, void *buf, size_t len, int os2flags)
{
TRACE_NATIVE("recv(%d, %p, %d, %d)", sock, buf, (int) len, os2flags);
FIXME("this should fail if not a socket"); // otherwise you might be a file descriptor...
return recv(sock, buf, len, mapOS2MsgFlags(os2flags));
} // OS2_recv
int OS2_connect(int sock, const struct OS2_sockaddr *os2addr, int addrlen)
{
TRACE_NATIVE("connect(%d, %p, %d)", sock, os2addr, addrlen);
FIXME("this should fail if not a socket"); // otherwise you might be a file descriptor...
if (os2addr->sa_family != OS2_AF_INET) {
FIXME("currently demands IPv4 socket");
return -1;
}
struct sockaddr_in bsdaddr;
memset(&bsdaddr, '\0', sizeof (bsdaddr));
bsdaddr.sin_family = AF_INET;
bsdaddr.sin_port = ((const OS2_sockaddr_in *) os2addr)->sin_port;
bsdaddr.sin_addr.s_addr = ((const OS2_sockaddr_in *) os2addr)->sin_addr.s_addr;
return connect(sock, &bsdaddr, (socklen_t) sizeof (bsdaddr));
} // OS2_connect
int OS2_shutdown(int sock, int kind)
{
TRACE_NATIVE("shutdown(%d, %d)", sock, kind);
FIXME("this should fail if not a socket"); // otherwise you might be a file descriptor...
return shutdown(sock, kind);
} // OS2_shutdown
int OS2_socket(int os2family, int os2socktype, int protocol)
{
TRACE_NATIVE("socket(%d, %d, %d)", os2family, os2socktype, protocol);
if (os2family != OS2_AF_INET) {
FIXME("currently demands IPv4 socket");
return -1;
}
if (protocol != 0) {
FIXME("Only protocol 0 supported at the moment");
return -1;
}
int bsdsocktype;
if (os2socktype == OS2_SOCK_STREAM) {
bsdsocktype = SOCK_STREAM;
} else if (os2socktype == OS2_SOCK_DGRAM) {
bsdsocktype = SOCK_DGRAM;
} else {
FIXME("Only SOCK_STREAM and SOCK_DGRAM supported at the moment");
return -1;
}
return socket(AF_INET, bsdsocktype, 0);
} // OS2_socket
ssize_t OS2_send(int sock, const void *buf, size_t len, int os2flags)
{
TRACE_NATIVE("send(%d, %p, %d, %d)", sock, buf, (int) len, os2flags);
FIXME("this should fail if not a socket"); // otherwise you might be a file descriptor...
return send(sock, buf, len, mapOS2MsgFlags(os2flags));
} // OS2_send
int OS2_soclose(int sock)
{
TRACE_NATIVE("soclose(%d)", sock);
FIXME("this should fail if not a socket"); // otherwise you might close a file descriptor...
return close(sock);
} // OS2_soclose
int OS2_sock_errno(void)
{
TRACE_NATIVE("sock_errno()");
FIXME("this should cache errno when an OS/2 socket function fails");
return errno;
} // OS2_sock_errno
unsigned long OS2_inet_addr(const char *name)
{
TRACE_NATIVE("inet_addr('%s')", name);
return inet_addr(name);
} // OS2_inet_addr
struct OS2_hostent *OS2_gethostbyname(const char *name)
{
TRACE_NATIVE("gethostbyname('%s')", name);
struct hostent *hent = gethostbyname(name);
return (OS2_hostent *) hent; // these happen to match up between Linux and OS/2.
} // OS2_gethostbyname
unsigned short OS2_htons(unsigned short val)
{
TRACE_NATIVE("htons(%u)", (unsigned int) val);
return htons(val);
} // OS2_htons
char *OS2_inet_ntoa(struct OS2_in_addr os2inaddr)
{
TRACE_NATIVE("inet_ntoa(%u)", (unsigned int) os2inaddr.s_addr);
struct in_addr bsdaddr;
bsdaddr.s_addr = os2inaddr.s_addr;
return inet_ntoa(bsdaddr);
} // OS2_inet_ntoa
struct OS2_servent *OS2_getservbyname(const char *name, const char *proto)
{
TRACE_NATIVE("getservbyname('%s', '%s')", name, proto);
struct servent *sent = getservbyname(name, proto);
return (OS2_servent *) sent; // these happen to match up between Linux and OS/2.
} // OS2_getservbyname
static void mapOS2FdSet(const OS2_fd_set *os2set, fd_set *bsdset)
{
FD_ZERO(bsdset);
const int total = os2set->fd_count;
for (int i = 0; i < total; i++) {
FD_SET(os2set->fd_array[i], bsdset);
}
} // mapOS2FdSet
int OS2_select(int ndfs, OS2_fd_set *os2readfds, OS2_fd_set *os2writefds, OS2_fd_set *os2errorfds, OS2_timeval *os2timeout)
{
TRACE_NATIVE("select(%d, %p, %p, %p, %p)", ndfs, os2readfds, os2writefds, os2errorfds, os2timeout);
#define MAPFDS(t) \
fd_set bsd##t##fds; \
fd_set *t##fds = NULL; \
if (os2##t##fds) { \
t##fds = &bsd##t##fds; \
mapOS2FdSet(os2##t##fds, t##fds); \
}
MAPFDS(read);
MAPFDS(write);
MAPFDS(error);
#undef MAPFDS
struct timeval bsdtv;
struct timeval *pbsdtv = NULL;
if (os2timeout) {
pbsdtv = &bsdtv;
bsdtv.tv_sec = os2timeout->tv_sec;
bsdtv.tv_usec = os2timeout->tv_usec;
}
const int rc = select(ndfs, readfds, writefds, errorfds, pbsdtv);
FIXME("fill in OS/2 fds");
return rc;
} // OS2_select
int OS2_os2_select(int *socks, int noreads, int nowrites, int noexcept, long timeout)
{
TRACE_NATIVE("os2_select(%p, %d, %d, %d, %d)", socks, noreads, nowrites, noexcept, (int) timeout);
const int nfds = noreads + nowrites + noexcept;
struct pollfd *fds = (struct pollfd *) alloca(sizeof (struct pollfd) * nfds);
struct pollfd *origfds = fds;
for (int i = 0; i < noreads; i++) {
fds->fd = *(socks++);
fds->events = POLLIN;
fds++;
}
for (int i = 0; i < nowrites; i++) {
fds->fd = *(socks++);
fds->events = POLLOUT;
fds++;
}
for (int i = 0; i < noexcept; i++) {
fds->fd = *(socks++);
fds->events = POLLERR;
fds++;
}
return poll(origfds, nfds, timeout * 1000);
} // OS2_os2_select
LX_NATIVE_MODULE_INIT()
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_connect, "connect", 3),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_recv, "recv", 10),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_os2_select, "os2_select", 12),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_send, "send", 13),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_socket, "socket", 16),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_soclose, "soclose", 17),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_sock_errno, "sock_errno", 20),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_shutdown, "shutdown", 25),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_sock_init, "sock_init", 26),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_select, "select", 32),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_inet_addr, "inet_addr", 105),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_inet_ntoa, "inet_ntoa", 110),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_gethostbyname, "gethostbyname", 111),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_getservbyname, "getservbyname",124),
LX_NATIVE_EXPORT_DIFFERENT_NAME(OS2_htons, "htons", 205)
LX_NATIVE_MODULE_INIT_END()
// end of tcpip32.c ...
+109
View File
@@ -0,0 +1,109 @@
#ifndef _INCL_TCPIP32_H_
#define _INCL_TCPIP32_H_
#include "os2types.h"
#ifdef __cplusplus
extern "C" {
#endif
// These are (mostly) the same symbols as BSD sockets, so to prevent conflicts
// with the _actual_ C runtime on the host, we name them OS2_*. The LX
// loader exports them with the correct names. If you're recompiling an
// OS/2 app and using this for API support, just use real BSD sockets
// instead.
// !!! FIXME: lots of "int" and such in here that should probably be int32, etc.
#define OS2_MSG_OOB 0x1
#define OS2_MSG_PEEK 0x2
#define OS2_MSG_DONTROUTE 0x4
#define OS2_MSG_FULLREAD 0x8
#define OS2_MSG_EOR 0x10
#define OS2_MSG_TRUNC 0x20
#define OS2_MSG_CTRUNC 0x40
#define OS2_MSG_WAITALL 0x80
#define OS2_MSG_DONTWAIT 0x100
#define OS2_AF_INET 2
#define OS2_SOCK_STREAM 1
#define OS2_SOCK_DGRAM 2
#pragma pack(push, 1)
typedef struct OS2_sockaddr
{
uint8 sa_len;
uint8 sa_family;
char sa_data[14];
} OS2_sockaddr;
typedef struct OS2_in_addr
{
uint32 s_addr;
} OS2_in_addr;
typedef struct OS2_sockaddr_in
{
uint8 sin_len;
uint8 sin_family;
uint16 sin_port;
struct OS2_in_addr sin_addr;
char sin_zero[8];
} OS2_sockaddr_in;
typedef struct OS2_hostent
{
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
} OS2_hostent;
typedef struct OS2_servent
{
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
} OS2_servent;
#define OS2_FD_SETSIZE 64
typedef struct OS2_fd_set
{
uint16 fd_count;
uint16 padding;
int fd_array[OS2_FD_SETSIZE];
} OS2_fd_set;
typedef struct OS2_timeval
{
sint32 tv_sec;
sint32 tv_usec;
} OS2_timeval;
#pragma pack(pop)
OS2EXPORT int OS2API OS2_sock_init(void);
OS2EXPORT int OS2API OS2_recv(int sock, void *buf, size_t len, int os2flags);
OS2EXPORT int OS2API OS2_connect(int sock, const OS2_sockaddr *os2addr, int addrlen);
OS2EXPORT int OS2API OS2_shutdown(int sock, int kind);
OS2EXPORT int OS2API OS2_socket(int family, int os2socktype, int protocol);
OS2EXPORT ssize_t OS2API OS2_send(int sock, const void *buf, size_t len, int os2flags);
OS2EXPORT int OS2API OS2_soclose(int sock);
OS2EXPORT int OS2API OS2_sock_errno(void);
OS2EXPORT unsigned long OS2API OS2_inet_addr(const char *name);
OS2EXPORT OS2_hostent * OS2API OS2_gethostbyname(const char *name);
OS2EXPORT unsigned short OS2API OS2_htons(unsigned short val);
OS2EXPORT char * OS2API OS2_inet_ntoa(OS2_in_addr os2inaddr);
OS2EXPORT OS2_servent * OS2API OS2_getservbyname(const char *name, const char *proto);
OS2EXPORT int OS2API OS2_select(int sock, OS2_fd_set *readfds, OS2_fd_set *writefds, OS2_fd_set *errorfds, OS2_timeval *timeout);
OS2EXPORT int OS2API OS2_os2_select(int *socks, int noreads, int nowrites, int noexcept, long timeout);
#ifdef __cplusplus
}
#endif
#endif
// end of tcpip32.h ...