Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
8 changed files
with
395 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ... | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ... | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ... | ||
|
Oops, something went wrong.