# This file is for use with Windows NT or 95 socket library. # These TAWK functions provide the extern function definitions for, # and a high level interface to, the socket # functions provided in the Win32 library. # This file is included in the TAWK version 5.0 library. # Download this file to obtain any updates or bug fixes # to this library file. # Documentation is available on the Microsoft Developer's Network CD. # Socket Types global SOCK_STREAM = 1 # stream socket global SOCK_DGRAM = 2 # datagram socket global SOCK_RAW = 3 # raw-protocol interface global SOCK_RDM = 4 # reliably-delivered message global SOCK_SEQPACKET = 5 # sequenced packet stream # Socket Domains global PF_UNSPEC = 0 # unspecified global PF_UNIX = 1 # local to host (pipes, portals) global PF_INET = 2 # internetwork: UDP, TCP, etc. global PF_IMPLINK = 3 # arpanet imp addresses global PF_PUP = 4 # pup protocols: e.g. BSP global PF_CHAOS = 5 # mit CHAOS protocols global PF_IPX = 6 # IPX and SPX global PF_NS = 6 # XEROX NS protocols global PF_ISO = 7 # ISO protocols global PF_OSI = 7 # OSI is ISO global PF_ECMA = 8 # european computer manufacturers global PF_DATAKIT = 9 # datakit protocols global PF_CCITT = 10 # CCITT protocols, X.25 etc global PF_SNA = 11 # IBM SNA global PF_DECnet = 12 # DECnet global PF_DLI = 13 # Direct data link interface global PF_LAT = 14 # LAT global PF_HYLINK = 15 # NSC Hyperchannel global PF_APPLETALK = 16 # AppleTalk global PF_NETBIOS = 17 # NetBios-style addresses # Internet Socket Protocols global IPPROTO_IP = 0 # dummy for IP global IPPROTO_ICMP = 1 # control message protocol global IPPROTO_GGP = 2 # gateway^2 (deprecated) global IPPROTO_TCP = 6 # tcp global IPPROTO_PUP = 12 # pup global IPPROTO_UDP = 17 # user datagram protocol global IPPROTO_IDP = 22 # xns idp global IPPROTO_ND = 77 # UNOFFICIAL net disk proto global IPPROTO_RAW = 255 # raw IP packet # C Structures used by sockets: #struct sockaddr { # u_short sa_family; /* address family */ # char sa_data[14]; /* up to 14 bytes of direct address */ #}; # This structure is created dynamically by the TAWK function: make_fd_set. #typedef struct fd_set { # u_int fd_count; /* number SET */ # SOCKET fd_array[FD_SETSIZE]; /* array of SOCKETs */ #}; # This structure is created in the TAWK function: select, below. # TAWK simply uses floating point for time, eg: 1.3 seconds. #struct timeval { # long tv_sec; /* seconds */ # long tv_usec; /* microseconds */ #}; # TAWK Socket Functions # Notes: # # Most low-level socket functions have been renamed by a prepended underscore. # For example, the raw socket() function can be invoked as _socket(). # You might have to use the low-level socket functions if you # run out of TAWK file descriptors. # # This file renames most of the low-level socket functions, and provides # TAWK functions that provide the same functionality, but that # use and return TAWK compatible file descriptors. These file # descriptors can be used in TAWK I/O functions, for example, # getline, fread, fwrite. # # Socket functions are as follows: # TAWK function UNIX function # ------------- ------------- # socket socket # socket_accept accept # socket_bind bind # socket_close close # socket_connect connect # socket_ioctl ioctl # socket_listen listen # socket_recv recv or recvfrom # socket_select select # socket_send send or sendto # socket_shutdown # socket_error uses errno variable # getsockopt getsockopt # setsockopt setsockopt # getsockname getsockname # getpeername getpeername # gethostbyaddr gethostbyaddr # gethostbyname gethostbyname # gethostname gethostname # inet_addr inet_addr # inet_ntoa inet_ntoa # getservbyport getservbyport # getservbyname getservbyname # getprotobyname getprotobyname # getprotobynumber getprotobynumber # socketpair # The following start and stop the Windows NT socket service. # These happen automatically if your program uses any function in this file. local inited = 0 INIT { WSAStartup(0x101,strdup("\0",2000)); inited = 1 } TERM { if (inited) WSACleanup() } extern int winapi name "socket" _socket(int af, int type, int protocol); # Function attempts to open a socket. # Returns an open file handle on success, or 0 on failure. function socket(af,type,protocol) { ret = _socket(af,type,protocol) if (ret == -1) return 0 else { print "ret =",ret return fdopen(ret,"r+h") } } extern int winapi name "accept" _accept( int s, struct sockaddr *addr, int *addrlen); # Function accepts a connection on socket s, which must be open in listen mode. # Return -1 on error, or a new socket handle. # On success, socname is filled in with the name of the connected address. function socket_accept(s,ref socname) { local namelen = 16 # Maximum name length local ret socname = strdup("\0",16) ret = _accept(fileno(s,1),socname,namelen) socname = substr(socname,1,namelen) if (ret == -1) return 0 else return fdopen(ret,"r+h") } # Binds socket s to the given address. # Return TRUE on success, FALSE on failure. extern int winapi name "bind" _bind(int s, struct sockaddr *addr, int namelen) function socket_bind(s,socname) { return ! _bind(fileno(s,1),socname,length(socname)) } extern int winapi name "closesocket" _closesocket(int s); function socket_close(s) { return ! _closesocket(fileno(s,1)) } extern int winapi name "connect" _connect( int s, struct sockaddr *name, int namelen); function socket_connect(s,socname) { return ! _connect(fileno(s,1),socname,length(socname)) } extern int winapi name "getpeername" _getpeername( int s, struct sockaddr *name, int * namelen); function getpeername(s) { local namelen = 16 # Maximum peer name local sockaddr = strdup("\0",namelen) if (_getpeername(s,sockaddr,namelen)) return # Failure return substr(sockaddr,1,namelen); } extern int winapi name "getsockname" _getsockname( int s, struct sockaddr *name, int * namelen); # Return the socket name in whatever format function getsockname(s) { local namelen = 16 # Maximum socket name length local sockaddr = strdup("\0",namelen) if (_getsockname(s,sockaddr,namelen)) return # Failure return substr(sockaddr,1,namelen); } extern int winapi name "getsockopt" _getsockopt(int s, int level, int optname, char * optval, int *optlen); function getsockopt(s,level,optname) { local optlen = 100 # Maximum option value length local optval = strdup("\0",optlen) if (_getsockopt(fileno(s,1),level,optname,optval,optlen) == 0) return substr(optval,1,optlen) } extern int winapi name "ioctlsocket" _ioctlsocket(int s, long cmd, long *argp); function socket_ioctl(s,cmd,arg) { return ! _ioctlsocket(fileno(s,1),cmd,arg) } # Use pack/unpack #extern long winapi htonl(long hostlong); # Use pack/unpack #extern short winapi htons(short hostshort); # Function returns the internet address number given a dotted address: "a.b.c.d" extern long winapi inet_addr(char * cp); # Function returns the dotted address given an internet address number extern char * winapi inet_ntoa(long sin); extern int winapi name "listen" _listen(int s, int backlog); function socket_listen(s,backlog) { if (argcount() == 1) backlog = 1 return ! _listen(fileno(s,1),backlog) } # Use pack/unpack #extern long winapi ntohl(long netlong); # Use pack/unpack #extern short winapi ntohs(short netshort); # Can also use fread! extern int winapi name "recv" _recv(int s, char * buf, int len, int flags); extern int winapi name "recvfrom" _recvfrom(int s, char * buf, int len, int flags, struct sockaddr *from, int * fromlen); # Receive a message from a socket. # Return the message, or "" if error. # If from argument is provided, it gets the senders address. function socket_recv(s,len,flags,from) { local buf = strdup("\0",len) local fromlen = 16 # Maximum address length if (argcount() == 4) { from = strdup("\0",fromlen) ret = _recvfrom(fileno(s,1),buf,len,flags,from,fromlen) from = substr(from,1,fromlen) } else { ret = _recv(fileno(s,1),buf,len,flags) } if (ret <= 0) return "" else return substr(buf,1,ret) } extern int winapi name "select" _select(int nfds, struct fd_set *readfds, struct fd_set *writefds, struct fd_set *exceptfds, struct timeval *timeout); # Return a Windows NT compatible set of file descriptors given # a TAWK array of file handles local function make_fd_set(fds) { local ret, i; if (typeof(fds) != "array" || length(fds) == 0) return 0 ret = pack("@l",length(fds)) # First word is number of handles for (i = 1; i <= length(fds); i++) { ret = ret pack("@l",fileno(fds[i],1)) } return ret } # Check on status of some sockets. # rfds is an optional array of sockets to be checked for readability # wfds is an optional array of sockets to be checked for writability # efds is an optional array of sockets to be checked for errors # timeout is the number of seconds to wait. It can be a float, eg: 0.1 function socket_select(rfds,wfds,efds,timeout) { local readfds, writefds, exceptfds; return _select(0,make_fd_set(rfds),make_fd_set(wfds),make_fd_set(efds), pack("@l @l",int(timeout),int((timeout - int(timeout)) * 1e6))) } # Can also use fwrite! extern int winapi name "send" _send(int s, char * buf, int len, int flags); extern int winapi name "sendto" _sendto(int s, char * buf, int len, int flags, struct sockaddr *to, int tolen); function socket_send(s,msg,flags,to) { if (argcount() == 4) { return _sendto(fileno(s,1),msg,length(msg),flags,to,length(to)) } else { return _send(fileno(s,1),msg,length(msg),flags) } } extern int winapi name "setsockopt" _setsockopt(int s, int level, int optname, char * optval, int optlen); # Set socket option optname to optval. # Return TRUE on success, FALSE on failure. function setsockopt(s,level,optname,optval) { return ! _setsockopt(fileno(s,1),level,optname,optval,length(optval)) } extern int winapi name "shutdown" _shutdown(int s, int how); function socket_shutdown(s,how) { return ! _shutdown(fileno(s,1),how) } #/* Database function prototypes */ #struct hostent { # char FAR * h_name; /* official name of host */ # char FAR * FAR * h_aliases; /* alias list */ # short h_addrtype; /* host address type */ # short h_length; /* length of address */ # char FAR * FAR * h_addr_list; /* list of addresses */ ##define h_addr h_addr_list[0] /* address, for backward compat */ #}; global struct_hostent = "name@p aliases@p addrtype@s length@s addrlist@l" extern struct hostent * winapi name "gethostbyaddr" _gethostbyaddr( char * addr, int len, int type); function gethostbyaddr(addr,type) { local ar, ret ret = _gethostbyaddr(addr,length(addr),type) if (ret == 0) return unpack(struct_hostent,ret,ar) return ar } extern struct hostent * winapi name "gethostbyname" _gethostbyname(char * name); function gethostbyname(name) { local ar, ret ret = _gethostbyname(name) if (ret == 0) return unpack(struct_hostent,ret,ar) return ar } extern int winapi name "gethostname" _gethostname(char * name, int namelen); function gethostname() { local buf = strdup("\0",300) if (0 == _gethostname(name,length(name))) return "" return substr(name,1,index(name,"\0")) } #struct servent { # char FAR * s_name; /* official service name */ # char FAR * FAR * s_aliases; /* alias list */ # short s_port; /* port # */ # char FAR * s_proto; /* protocol to use */ #}; global struct_servent = "name@p aliases@p port@s @2x proto@p" extern struct servent * winapi name "getservbyport" _getservbyport(int port, char * proto); function getservbyport(port,proto) { local ret, ar ret = _getservbyport(port,proto?proto:0) if (ret == 0) return; unpack(struct_servent,ret,ar) return ar } extern struct servent * winapi name "getservbyname" _getservbyname(char * name, char * proto); function getservbyname(name,proto) { local ret, ar ret = _getservbyname(name,proto?proto:0) if (ret == 0) return; unpack(struct_servent,ret,ar) return ar } # This is the structure definition in C: #struct protoent { # char FAR * p_name; /* official protocol name */ # char FAR * FAR * p_aliases; /* alias list */ # short p_proto; /* protocol # */ #}; # And this is the structure definition in TAWK: global struct_protoent = "name@p aliases@p proto@s" extern struct protoent * winapi name "getprotobynumber" _getprotobynumber(int proto); function getprotobynumber(proto) { local ret, ar ret = _getprotobynumber(proto) if (ret == 0) return; unpack(struct_protoent,ret,ar) return ar } extern struct protoent * winapi name "getprotobyname" _getprotobyname(char * name); function getprotobyname(name) { local ret, ar ret = _getprotobyname(name) if (ret == 0) return; unpack(struct_protoent,ret,ar) return ar } # More Windows NT routines: extern int winapi WSAStartup(int wVersionRequired, void* lpWSAData); extern int winapi WSACleanup(); extern void winapi WSASetLastError(int iError); extern int winapi WSAGetLastError(); function socket_error() { return WSAGetLastError() } # These are the Windows specific functions. You probably do not need them, # so they are commented out. # extern int winapi WSAIsBlocking(void); #extern int winapi WSAUnhookBlockingHook(void); #extern PROC winapi WSASetBlockingHook(PROC lpBlockFunc); #extern int winapi WSACancelBlockingCall(void); #extern HANDLE winapi WSAAsyncGetServByName(HWND hWnd, int wMsg, char * name, char * proto, char * buf, int buflen); #extern HANDLE winapi WSAAsyncGetServByPort(HWND hWnd, int wMsg, int port, char * proto, char * buf, int buflen); #extern HANDLE winapi WSAAsyncGetProtoByName(HWND hWnd, int wMsg, char * name, char * buf, int buflen); #extern HANDLE winapi WSAAsyncGetProtoByNumber(HWND hWnd, int wMsg, int number, char * buf, int buflen); #extern HANDLE winapi WSAAsyncGetHostByName(HWND hWnd, int wMsg, char * name, char * buf, int buflen); #extern HANDLE winapi WSAAsyncGetHostByAddr(HWND hWnd, int wMsg, char * addr, int len, int type, char * buf, int buflen); #extern int winapi WSACancelAsyncRequest(HANDLE hAsyncTaskHandle); #extern int winapi WSAAsyncSelect(int s, HWND hWnd, int wMsg, long lEvent); #extern int winapi WSARecvEx(int s, char * buf, int len, int *flags);