quakeforge-old/standalone/mplpc.c
1999-12-25 05:22:39 +00:00

1001 lines
21 KiB
C

/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <go32.h>
#include "mpdosock.h"
//#include "types.h"
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
//#include "lpc.h"
typedef struct {
short version; // version of LPC requested
short sizeOfArgs; // size of arguments
short service; // service # requested
char Data[1]; // data
} LPCData;
typedef struct {
short version; // LPC version
short sizeOfReturn; // return data size
short error; // any error codes
short noRet; // number of returns
char Data[1]; // data
} LPCReturn;
//#include "services.h"
#define MAXSOCKETS 20
// services
#define LPC_SOCKBIND 4
#define LPC_SOCKGETHOSTBYNAME 5
#define LPC_SOCKGETHOSTNAME 6
#define LPC_SOCKGETHOSTBYADDR 7
#define LPC_SOCKCLOSE 8
#define LPC_SOCKSOCKET 9
#define LPC_SOCKRECVFROM 10
#define LPC_SOCKSENDTO 11
#define LPC_SOCKIOCTL 12
#define LPC_SOCKGETSOCKNAME 13
#define LPC_SOCKFLUSH 14
#define LPC_SOCKSETOPT 15
#define LPC_SOCKGETLASTERROR 16
#define LPC_SOCKINETADDR 17
// htons, ntohs, htonl, ntohl implemented locally
// errors
#define LPC_UNRECOGNIZED_SERVICE -1
#define LPC_NOERROR 0
// structures for support
typedef struct {
SOCKET s;
int namelen;
char name[1];
} BindArgs;
typedef struct {
SOCKET s;
long cmd;
char data[1];
} IoctlArgs;
typedef struct {
int retVal;
int namelen;
char name[1];
} GetSockNameRet;
typedef GetSockNameRet GetHostNameRet;
typedef struct {
int retVal;
int h_addr_0; // that's the only important value
} GetHostByNameRet;
typedef struct {
int len;
int type;
char addr[1];
} GetHostByAddrArgs;
typedef struct {
int retVal;
char h_name[1]; // h_name is the only important value
} GetHostByAddrRet;
typedef struct {
SOCKET s;
int flags;
} RecvFromArgs;
typedef struct {
int retVal;
int errCode;
int len; // message len
struct sockaddr sockaddr;
int sockaddrlen;
char Data[1];
} RecvFromRet;
typedef struct {
SOCKET s;
int flags;
int len;
struct sockaddr sockaddr;
int sockaddrlen;
char Data[1];
} SendToArgs;
typedef struct {
int retVal;
int errCode;
} SendToRet;
typedef struct {
int bufflen;
SOCKET s;
int len;
int sockaddrlen;
struct sockaddr address;
char data[1];
} SocketChannelData;
typedef struct {
int af;
int type;
int protocol;
} SocketArgs;
typedef struct {
SOCKET s;
int len;
int flags;
int addrlen;
struct sockaddr addr;
char data[1];
} WinSockData;
typedef struct {
SOCKET s;
int level;
int optname;
int optlen;
char optval[1];
} SetSockOptArgs;
typedef struct {
SOCKET sock[MAXSOCKETS];
} SocketMap;
//#include "rtq.h"
#define RTQ_NODE struct rtq_node
RTQ_NODE
{
RTQ_NODE *self; // Ring zero address of this node
RTQ_NODE *left; // Ring zero address of preceding node
RTQ_NODE *right; // Ring zero address of succeding node
BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface)
BYTE * rtqInsert; // Ring 3 insertion position
WORD rtqLen; // Length of buffer, excluding preface
WORD rtqUpCtr; // Up Counter of bytes used so far
WORD rtqQCtr; // number of nodes attached
WORD padding; // DWORD alignment
};
#define RTQ_PARAM_MOVENODE struct rtq_param_movenode
RTQ_PARAM_MOVENODE
{
WORD rtqFromDQ;
WORD rtqToDQ;
};
RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From
//#include "mplib.h"
// give up time slice
void Yield(void);
void MGenWakeupDll(void);
// post a message to win32 side
void PostWindowsMessage(void);
// get # of items on qNo
int MGenGetQueueCtr(int qNo);
// move first node from qFrom to qTo
RTQ_NODE *MGenMoveTo(int qFrom, int qTo);
// get first node from q
RTQ_NODE *MGenGetNode(int q);
// get master node, returning size of RTQ_NODE for size verification
RTQ_NODE *MGenGetMasterNode(unsigned *size);
// move all nodes from qFrom to qTo
RTQ_NODE *MGenFlushNodes(int qFrom, int qTo);
// count number of nodes in queues designated by bitmask
// lowerOrderBits == 0..31, upperOrderBits == 32-63
int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits);
// perform consistency check on chunnel address space
int MGenSanityCheck(void);
#include <stdio.h>
#include <sys/farptr.h>
extern short flat_selector;
#define SOCKET_MAP_QUEUE 41
#define IDLE_QUEUE 44
#define REC_QUEUE 45
#define SEND_QUEUE 46
// queue sizes
#define FREEQBASE 58
#define FREEQ64 58
#define FREEQ128 59
#define FREEQ256 60
#define FREEQ512 61
#define FREEQ1024 62
#define FREEQ2048 63
#define NFREEQ 6
#define QLIMIT 10
#define PRIVATEQ 50
#define FARPKL(x) (_farnspeekl((unsigned long) x))
#define FARPKB(x) (_farnspeekb((unsigned long) x))
#define FARPKS(x) (_farnspeekw((unsigned long) x))
#define FARPOKL(x, y) (_farnspokel((unsigned long) x, (unsigned long) y))
#define FARPOKB(x, y) (_farnspokeb((unsigned long) x, (unsigned char) y))
int Qsizes[] = { 64, 128, 256, 512, 1024, 2048 };
int SocketError = 0;
SocketMap *SockMap;
#define HOSTENT_ALIAS_LIMIT 5
#define HOSTENT_STRLEN_LIMIT 50
#define HOSTENT_ADDR_LIST_LIMIT 5
struct hostent HostEnt;
char HostEnt_hname[HOSTENT_STRLEN_LIMIT];
char *HostEnt_h_aliases[HOSTENT_ALIAS_LIMIT];
char HostEnt_names[HOSTENT_ALIAS_LIMIT][HOSTENT_STRLEN_LIMIT];
struct in_addr* HostEnt_addr_list[HOSTENT_ADDR_LIST_LIMIT];
struct in_addr HostEnt_addrs[HOSTENT_ADDR_LIST_LIMIT];
void
fmemcpyto(void *to, const void *from, int length)
{
movedata(_my_ds(), (unsigned)from, flat_selector, (unsigned)to, length);
}
void
fmemcpyfrom(void *to, const void *from, int length)
{
movedata(flat_selector, (unsigned)from, _my_ds(), (unsigned)to, length);
}
void
fstrcpyto(char *to, const char *from)
{
while (*from) {
FARPOKB(to, *from);
to++; from++;
}
FARPOKB(to, 0);
}
void
fstrncpyto(char *to, const char *from, int len)
{
while (*from && len) {
FARPOKB(to, *from);
to++; from++; len--;
}
FARPOKB(to, 0);
}
void
fstrcpyfrom(char *to, const char *from)
{
while (FARPKB(from)) {
*to = FARPKB(from);
from++; to++;
}
*to = 0;
}
void
fstrncpyfrom(char *to, const char *from, int len)
{
while (FARPKB(from) && len) {
*to = FARPKB(from);
from++; to++; len--;
}
*to = 0;
}
void
GetSocketMap(void)
{
RTQ_NODE *n = MGenGetNode(SOCKET_MAP_QUEUE);
SockMap = (SocketMap *) FARPKL(&n->rtqDatum);
}
void *
GetFreeBufferToQueue(int q, int bufSize)
{
int i;
for (i = 0; i < NFREEQ; i++) {
if (Qsizes[i] >= bufSize && MGenGetQueueCtr(i+FREEQBASE)) {
RTQ_NODE *n = MGenMoveTo(i+FREEQBASE, q);
if (!n)
continue;
FARPOKL(&n->rtqUpCtr, bufSize);
return (void *) FARPKL(&n->rtqDatum);
}
}
return 0;
}
void
FreeBufferFromQueue(int q)
{
int i;
RTQ_NODE *n = MGenGetNode(q);
for (i = 0; i < NFREEQ; i++) {
if (Qsizes[i] == FARPKS(&n->rtqLen)) {
MGenMoveTo(q, i+FREEQBASE);
return;
}
}
}
void
SetLPCData(LPCData *lpc)
{
FARPOKL(&(lpc->version), 1);
FARPOKL(&(lpc->sizeOfArgs), 0);
FARPOKL(&(lpc->service), 0);
}
int
bind(SOCKET s, const struct sockaddr *name, int namelen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
BindArgs *bargs;
int retVal;
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKBIND);
bargs = (BindArgs *) p->Data;
FARPOKL(&bargs->s, s);
FARPOKL(&bargs->namelen, namelen);
fmemcpyto(bargs->name, name, namelen);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
int
closesocket(SOCKET s)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKCLOSE);
FARPOKL(p->Data, s);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
void
ZapHostEnt()
{
// do nothing
}
void
ReconstructHostEnt(struct hostent *s, void *flattened)
{
struct hostent *old = (struct hostent *) flattened;
int i;
char **ptr;
s->h_name = HostEnt_hname;
fstrncpyfrom(s->h_name, (char *) FARPKL(&old->h_name), HOSTENT_STRLEN_LIMIT-1);
s->h_name[HOSTENT_STRLEN_LIMIT-1] = 0;
s->h_aliases = HostEnt_h_aliases;
ptr = (char **) FARPKL(&old->h_aliases);
for (i = 0; i < (HOSTENT_ALIAS_LIMIT-1) && FARPKL(ptr); i++, ptr++) {
s->h_aliases[i] = HostEnt_names[i];
// fstrncpyfrom(s->h_aliases[i], (void *) FARPKL(ptr), HOSTENT_STRLEN_LIMIT-1);
s->h_aliases[i][HOSTENT_STRLEN_LIMIT-1] = 0;
}
s->h_aliases[i] = 0;
s->h_addrtype = FARPKS(&old->h_addrtype);
s->h_length = FARPKS(&old->h_length);
if (FARPKS(&old->h_length) != sizeof(struct in_addr)) {
printf("Error!\n");
exit(0);
}
s->h_addr_list = (char **) HostEnt_addr_list;
ptr = (char **) FARPKL(&old->h_addr_list);
for (i = 0; i < (HOSTENT_ADDR_LIST_LIMIT - 1) && FARPKL(ptr); i++, ptr++) {
s->h_addr_list[i] = (char *) &(HostEnt_addrs[i]);
fmemcpyfrom(s->h_addr_list[i], (void *) FARPKL(ptr), s->h_length);
}
s->h_addr_list[i] = 0;
}
int
getsockname(SOCKET s, struct sockaddr *name, int *namelen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
GetSockNameRet *ret;
int retVal;
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETSOCKNAME);
FARPOKL(p->Data, s);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
ret = (GetSockNameRet *) r->Data;
retVal = FARPKL(&ret->retVal);
fmemcpyfrom(name, ret->name, FARPKL(&ret->namelen));
*namelen = FARPKL(&ret->namelen);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
int
gethostname(char *name, int namelen)
{
RTQ_NODE *n;
LPCData *p;
LPCReturn *r;
GetHostNameRet *ret;
int retVal;
char *s;
_farsetsel(flat_selector);
SocketError = 0;
n = (RTQ_NODE *) MGenGetNode(IDLE_QUEUE);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service,LPC_SOCKGETHOSTNAME);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = (RTQ_NODE *) (MGenGetNode(REC_QUEUE))) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
ret = (GetHostNameRet *) r->Data;
retVal = FARPKL(&ret->retVal);
s = ret->name;
fstrncpyfrom(name, s, namelen);
#if 0
len = strlen(ret->name);
if (len > namelen)
memcpy(name, ret->name, ret->namelen);
else
strcpy(name, ret->name);
#endif
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
struct hostent *
gethostbyname(const char *name)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
struct hostent *retVal;
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETHOSTBYNAME);
fstrcpyto(p->Data, name);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = (struct hostent *) r->Data;
if (FARPKL(&retVal->h_name) == 0) {
retVal = 0;
} else {
ZapHostEnt();
ReconstructHostEnt(&HostEnt, (void *) retVal);
retVal = &HostEnt;
}
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
struct hostent *
gethostbyaddr(const char *addr, int len, int type)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
GetHostByAddrArgs *args;
struct hostent *retVal;
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETHOSTBYADDR);
args = (GetHostByAddrArgs *) p->Data;
FARPOKL(&args->len, len);
FARPOKL(&args->type, type);
fmemcpyto(args->addr, addr, len);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = (struct hostent *) r->Data;
if (FARPKL(&retVal->h_name) == 0) {
retVal = 0;
} else {
ZapHostEnt();
ReconstructHostEnt(&HostEnt, (void *) retVal);
retVal = &HostEnt;
}
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
SOCKET
socket(int af, int type, int protocol)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
SocketArgs *args;
int retVal;
_farsetsel(flat_selector);
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKSOCKET);
args = (SocketArgs *) p->Data;
FARPOKL(&args->af, af);
FARPOKL(&args->type, type);
FARPOKL(&args->protocol, protocol);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
void
sockets_flush(void)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
SocketError = 0;
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKFLUSH);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
}
int
recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from,
int *fromlen)
{
int i;
RTQ_NODE *n;
WinSockData *data;
int bytesRead;
SocketError = 0;
_farsetsel(flat_selector);
if (!SockMap)
GetSocketMap();
for (i = 0; i < MAXSOCKETS; i++) {
if (FARPKL(&(SockMap->sock[i])) == s)
break;
}
if (i == MAXSOCKETS)
return SOCKET_ERROR;
// pick up node
n = MGenGetNode(i);
if (n == 0) {
SocketError = WSAEWOULDBLOCK;
return -1;
}
data = (WinSockData *) FARPKL(&n->rtqDatum);
bytesRead = FARPKL(&data->len);
if (from) {
fmemcpyfrom(from, &data->addr, sizeof(struct sockaddr));
}
if (fromlen) {
*fromlen = FARPKL(&data->addrlen);
}
fmemcpyfrom(buf, data->data, len > bytesRead ? bytesRead : len);
if ((flags & MSG_PEEK) == 0) {
FreeBufferFromQueue(i);
}
return bytesRead;
}
int
sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
{
int i;
int outQ;
WinSockData *data;
SocketError = 0;
_farsetsel(flat_selector);
if (!SockMap)
GetSocketMap();
for (i = 0; i < MAXSOCKETS; i++) {
if (FARPKL(&SockMap->sock[i]) == s) {
break;
}
}
if (i == MAXSOCKETS) {
SocketError = WSAENOTSOCK;
return SOCKET_ERROR;
}
outQ = i + MAXSOCKETS;
if (MGenGetQueueCtr(outQ) >= QLIMIT) {
SocketError = WSAEWOULDBLOCK;
return SOCKET_ERROR;
}
data = GetFreeBufferToQueue(PRIVATEQ, len + sizeof(WinSockData));
if (!data) {
SocketError = WSAEWOULDBLOCK;
return SOCKET_ERROR;
}
FARPOKL(&data->s, s);
FARPOKL(&data->len, len);
if (to) {
fmemcpyto(&data->addr, to, tolen);
FARPOKL(&data->addrlen, tolen);
} else {
FARPOKL(&data->addrlen, 0);
}
FARPOKL(&data->flags, flags);
fmemcpyto(data->data, buf, len);
MGenMoveTo(PRIVATEQ, outQ);
return len;
}
int
ioctlsocket(SOCKET s, long cmd, unsigned long *argp)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
IoctlArgs *args;
int retVal;
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKIOCTL);
args = (IoctlArgs *) p->Data;
FARPOKL(&args->s, s);
FARPOKL(&args->cmd, cmd);
switch(cmd) {
case FIONBIO:
FARPOKL(args->data, *argp);
break;
default:
return SOCKET_ERROR;
}
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
int
setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
SetSockOptArgs *args;
int retVal;
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKSETOPT);
args = (SetSockOptArgs *) p->Data;
FARPOKL(&args->s, s);
FARPOKL(&args->level, level);
FARPOKL(&args->optname, optname);
FARPOKL(&args->optlen, optlen);
fmemcpyto(args->optval, optval, optlen);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
int
WSAGetLastError(void)
{
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
_farsetsel(flat_selector);
if (SocketError) {
int err = SocketError;
SocketError = 0;
return err;
}
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKGETLASTERROR);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
}
unsigned long inet_addr(const char *cp)
{
int ret;
unsigned int ha1, ha2, ha3, ha4;
unsigned long ipaddr;
ret = sscanf(cp, "%d.%d.%d.%d", &ha1, &ha2, &ha3, &ha4);
if (ret != 4)
return -1;
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
return ipaddr;
#if 0
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
LPCData *p;
LPCReturn *r;
int retVal;
SocketError = 0;
_farsetsel(flat_selector);
p = (LPCData *) FARPKL(&n->rtqDatum);
SetLPCData(p);
FARPOKL(&p->service, LPC_SOCKINETADDR);
fstrcpyto(p->Data, cp);
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
PostWindowsMessage();
while ((n = MGenGetNode(REC_QUEUE)) == 0)
Yield();
r = (LPCReturn *) FARPKL(&n->rtqDatum);
if (FARPKS(&r->error) != LPC_NOERROR) {
return -1;
}
retVal = FARPKL(r->Data);
// get ready for next call
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
return retVal;
#endif
}
char *inet_ntoa (struct in_addr in)
{
static char buf [32];
sprintf(buf, "%u.%u.%u.%u", in.S_un.S_un_b.s_b1, in.S_un.S_un_b.s_b2, in.S_un.S_un_b.s_b3, in.S_un.S_un_b.s_b4);
return buf;
}