Skip to content

Commit

Permalink
Implemented just enough of tcpip32.dll and dependencies to run FINGER…
Browse files Browse the repository at this point in the history
….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.
  • Loading branch information
icculus committed Dec 21, 2017
1 parent fabd3be commit b72ccd6
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -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")
Expand Down
2 changes: 2 additions & 0 deletions native/os2.h
Expand Up @@ -15,6 +15,8 @@
#include "msg.h"
#include "nls.h"
#include "sesmgr.h"
#include "pmgpi.h"
#include "tcpip32.h"

#endif

Expand Down
1 change: 1 addition & 0 deletions native/os2native.h
Expand Up @@ -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() \
}; \
Expand Down
3 changes: 3 additions & 0 deletions native/os2types.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions native/pmgpi.c
@@ -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 changes: 25 additions & 0 deletions native/pmgpi.h
@@ -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 changes: 238 additions & 0 deletions native/tcpip32.c
@@ -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 ...

0 comments on commit b72ccd6

Please sign in to comment.