diff options
Diffstat (limited to 'Mac/Unsupported/GUSI1-mods/GUSINetDB.cp')
-rw-r--r-- | Mac/Unsupported/GUSI1-mods/GUSINetDB.cp | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/Mac/Unsupported/GUSI1-mods/GUSINetDB.cp b/Mac/Unsupported/GUSI1-mods/GUSINetDB.cp new file mode 100644 index 0000000..8b2140e --- /dev/null +++ b/Mac/Unsupported/GUSI1-mods/GUSINetDB.cp @@ -0,0 +1,582 @@ +/********************************************************************* +Project : GUSI - Grand Unified Socket Interface +File : GUSINetDB.cp - Convert internet names to adresses +Author : Matthias Neeracher + + This file was derived from the socket library by + + Charlie Reiman <creiman@ncsa.uiuc.edu> and + Tom Milligan <milligan@madhaus.utcs.utoronto.ca> + +Language : MPW C++ + +$Log$ +Revision 1.1 2000/09/12 20:24:49 jack +Moved to Unsupported. + +Revision 1.1 1998/08/18 14:52:38 jack +Putting Python-specific GUSI modifications under CVS. + +Revision 1.3 1994/08/10 00:07:30 neeri +Sanitized for universal headers. + +Revision 1.2 1994/05/01 23:43:31 neeri +getservbyname() without /etc/services would fail. + +Revision 1.1 1994/02/25 02:29:36 neeri +Initial revision + +Revision 0.5 1993/10/31 00:00:00 neeri +Deferred opening of resolver + +Revision 0.4 1993/07/29 00:00:00 neeri +Real getservent code (adapted from Sak Wathanasin) + +Revision 0.3 1993/01/19 00:00:00 neeri +Can't set aliases to NULL. + +Revision 0.2 1992/11/21 00:00:00 neeri +Remove force_active + +Revision 0.1 1992/09/14 00:00:00 neeri +Maybe it works, maybe it doesn't + +*********************************************************************/ + +#include "GUSIINET_P.h" + +#include "TFileSpec.h" +#include "Folders.h" +#include "PLStringFuncs.h" + +#ifdef __MWERKS__ +// +// I disapprove of the way dnr.c is written +// This disapproval gets stronger with every version +// +#include "dnr.c" +#pragma require_prototypes reset +#pragma cplusplus reset +#endif + +#if GENERATING68K +#pragma segment GUSIINET +#endif + +static pascal void DNRDone(struct hostInfo *, Boolean * done) +{ + *done = true; +} + +#if GENERATINGCFM +RoutineDescriptor uDNRDone = + BUILD_ROUTINE_DESCRIPTOR(uppResultProcInfo, DNRDone); +#else +#define uDNRDone DNRDone +#endif + +int h_errno; + +/* + * Gethostbyname and gethostbyaddr each return a pointer to an + * object with the following structure describing an Internet + * host referenced by name or by address, respectively. This + * structure contains the information obtained from the MacTCP + * name server. + * + * struct hostent + * { + * char *h_name; + * char **h_aliases; + * int h_addrtype; + * int h_length; + * char **h_addr_list; + * }; + * #define h_addr h_addr_list[0] + * + * The members of this structure are: + * + * h_name Official name of the host. + * + * h_aliases A zero terminated array of alternate names for the host. + * + * h_addrtype The type of address being returned; always AF_INET. + * + * h_length The length, in bytes, of the address. + * + * h_addr_list A zero terminated array of network addresses for the host. + * + * Error return status from gethostbyname and gethostbyaddr is + * indicated by return of a null pointer. The external integer + * h_errno may then be checked to see whether this is a + * temporary failure or an invalid or unknown host. The + * routine herror can be used to print an error message + * describing the failure. If its argument string is non-NULL, + * it is printed, followed by a colon and a space. The error + * message is printed with a trailing newline. + * + * h_errno can have the following values: + * + * HOST_NOT_FOUND No such host is known. + * + * TRY_AGAIN This is usually a temporary error and + * means that the local server did not + * receive a response from an authoritative + * server. A retry at some later time may + * succeed. + * + * NO_RECOVERY Some unexpected server failure was encountered. + * This is a non-recoverable error. + * + * NO_DATA The requested name is valid but does not + * have an IP address; this is not a + * temporary error. This means that the name + * is known to the name server but there is + * no address associated with this name. + * Another type of request to the name server + * using this domain name will result in an + * answer; for example, a mail-forwarder may + * be registered for this domain. + * (NOT GENERATED BY THIS IMPLEMENTATION) + */ + +static struct hostInfo macHost; + +#define MAXALIASES 0 +static char *aliasPtrs[MAXALIASES+1] = {NULL}; +static ip_addr *addrPtrs[NUM_ALT_ADDRS+1]; + +static struct hostent unixHost = +{ + macHost.cname, + aliasPtrs, + AF_INET, + sizeof(ip_addr), + (char **) addrPtrs +}; + +inline struct in_addr make_in_addr(ip_addr addr) +{ + struct in_addr res; + + res.s_addr = addr; + + return res; +} + +struct hostent * gethostbyname(char *name) +{ + Boolean done; + int i; + + if (!strcmp(name, "localhost")) { + in_addr ipaddr; + + ipaddr = make_in_addr(ip_addr(gethostid())); + + if (ipaddr.s_addr) + return gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET); + + h_errno = HOST_NOT_FOUND; + + return NULL; + } + + if (INETSockets.Resolver()) { + h_errno = NO_RECOVERY; + return NULL; + } + + for (i=0; i<NUM_ALT_ADDRS; i++) + macHost.addr[i] = 0; + + done = false; + + if (StrToAddr(name, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault) + SPINP(!done,SP_NAME,0L); + + switch (macHost.rtnCode) { + case noErr: break; + + case nameSyntaxErr: h_errno = HOST_NOT_FOUND; return(NULL); + case cacheFault: h_errno = NO_RECOVERY; return(NULL); + case noResultProc: h_errno = NO_RECOVERY; return(NULL); + case noNameServer: h_errno = HOST_NOT_FOUND; return(NULL); + case authNameErr: h_errno = HOST_NOT_FOUND; return(NULL); + case noAnsErr: h_errno = TRY_AGAIN; return(NULL); + case dnrErr: h_errno = NO_RECOVERY; return(NULL); + case outOfMemory: h_errno = TRY_AGAIN; return(NULL); + default: h_errno = NO_RECOVERY; return(NULL); + } + + /* was the 'name' an IP address? */ + if (macHost.cname[0] == 0) { + h_errno = HOST_NOT_FOUND; + return(NULL); + } + + /* for some reason there is a dot at the end of the name */ + i = int(strlen(macHost.cname)) - 1; + if (macHost.cname[i] == '.') + macHost.cname[i] = 0; + + for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++) + addrPtrs[i] = (ip_addr *) &macHost.addr[i]; + + addrPtrs[i] = NULL; + + return &unixHost; +} + +struct hostent * gethostbyaddr(const char *addrP, int, int) +{ + Boolean done; + int i; + + if (INETSockets.Resolver()) { + h_errno = NO_RECOVERY; + return NULL; + } + + for (i=0; i<NUM_ALT_ADDRS; i++) + macHost.addr[i] = 0; + + done = false; + + ip_addr addr = FIX_LOOPBACK(*(ip_addr *)addrP); + + if (AddrToName(addr, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault) + SPINP(!done,SP_ADDR,0L); + + switch (macHost.rtnCode) { + case noErr: break; + + case cacheFault: h_errno = NO_RECOVERY; return(NULL); + case noNameServer: h_errno = HOST_NOT_FOUND; return(NULL); + case authNameErr: h_errno = HOST_NOT_FOUND; return(NULL); + case noAnsErr: h_errno = TRY_AGAIN; return(NULL); + case dnrErr: h_errno = NO_RECOVERY; return(NULL); + case outOfMemory: h_errno = TRY_AGAIN; return(NULL); + default: h_errno = NO_RECOVERY; return(NULL); + } + + /* for some reason there is a dot at the end of the name */ + i = int(strlen(macHost.cname)) - 1; + if (macHost.cname[i] == '.') + macHost.cname[i] = 0; + + /* For some reason, the IP address usually seems to be set to 0 */ + if (!macHost.addr[0]) + macHost.addr[0] = addr; + + for (i=0; i<NUM_ALT_ADDRS; i++) + addrPtrs[i] = (ip_addr *) &macHost.addr[i]; + + addrPtrs[NUM_ALT_ADDRS] = NULL; + + return &unixHost; +} + +char * inet_ntoa(struct in_addr inaddr) +{ + if (INETSockets.Resolver()) { + h_errno = NO_RECOVERY; + return NULL; + } + + (void) AddrToStr(inaddr.s_addr, macHost.cname); + + return macHost.cname; +} + +struct in_addr inet_addr(char *address) +{ + if (INETSockets.Resolver()) { + h_errno = NO_RECOVERY; + return make_in_addr(0xFFFFFFFF); + } + + if (StrToAddr(address,&macHost,NULL,NULL) != noErr) + return make_in_addr(0xFFFFFFFF); + + /* was the 'address' really a name? */ + if (macHost.cname[0] != 0) + return make_in_addr(0xFFFFFFFF); + + return make_in_addr(macHost.addr[0]); +} + +/* + * gethostid() + * + * Get internet address of current host + */ + +long gethostid() +{ + static long sHostID = 0; + if (sHostID) + return sHostID; + + struct GetAddrParamBlock pbr; + + pbr.ioCRefNum = INETSockets.Driver(); + pbr.csCode = ipctlGetAddr; + + if (PBControlSync(ParmBlkPtr(&pbr))) + return 0; + else + return sHostID = (long)pbr.ourAddress; +} + +/* + * gethostname() + * + * Try to get my host name from DNR. If it fails, just return my + * IP address as ASCII. This is non-standard, but it's a mac, + * what do you want me to do? + */ + +int gethostname(char *machname, int buflen) +{ + static char * sHostName = nil; + + if (!sHostName) { + in_addr ipaddr; + struct hostent *hp; + + ipaddr = make_in_addr(ip_addr(gethostid())); + + if (!ipaddr.s_addr) // TCP/IP not up at all + return GUSI_error(ENETDOWN); + + hp = gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET); + + if (!hp) { + // No good name + if (buflen < 16) // Not enough space + return GUSI_error(EINVAL); + sprintf(machname, "%d.%d.%d.%d", + ipaddr.s_addr>>24, + ipaddr.s_addr>>16 & 0xff, + ipaddr.s_addr>>8 & 0xff, + ipaddr.s_addr & 0xff); + return 0; + } else { + // We only cache satisfactory replies in sHostName + sHostName = new char[strlen(hp->h_name)+1]; + strcpy(sHostName, hp->h_name); + } + } + strncpy(machname, sHostName, unsigned(buflen)); + machname[buflen-1] = 0; /* extra safeguard */ + + return 0; +} + + +/* + * getservbybname() + * + */ + +static char * servlist[] = +{ + "echo 7/udp", + "discard 9/udp", + "time 37/udp", + "domain 53/udp", + "sunrpc 111/udp", + "tftp 69/udp", + "biff 512/udp", + "who 513/udp", + "talk 517/udp", + "ftp-data 20/tcp", + "ftp 21/tcp", + "telnet 23/tcp", + "smtp 25/tcp", + "time 37/tcp", + "whois 43/tcp", + "domain 53/tcp", + "hostnames 101/tcp", + "nntp 119/tcp", + "finger 79/tcp", + "ntp 123/tcp", + "uucp 540/tcp", + NULL +}; + +static char servline[128]; +static struct servent serv; +static FILE * servfil; +static int servptr; +static char * servalias[8]; +static int servstay = 0; + +void setservent(int stayopen) +{ + if (servfil && servfil != (FILE *) -1) { + rewind(servfil); + } + servptr = 0; + servstay = servstay || stayopen; +} + +void endservent() +{ + if (servfil && servfil != (FILE *) -1) { + fclose(servfil); + servfil = NULL; + } + + servstay = 0; +} + +struct servent * getservent() +{ + char * p; + int aliascount; + + if (!servfil) { + TFileSpec serv; + + if (!FindFolder( + kOnSystemDisk, + kPreferencesFolderType, + kDontCreateFolder, + &serv.vRefNum, + &serv.parID) + ) { + PLstrcpy(serv.name, (StringPtr) "\p/etc/services"); + + if (servfil = fopen(serv.FullPath(), "r")) + goto retry; + } + servfil = (FILE *) -1; + servptr = 0; + } + +retry: + if (servfil == (FILE *) -1) + if (!servlist[servptr]) + return (struct servent *) NULL; + else + strcpy(servline, servlist[servptr++]); + else if (!(fgets(servline, 128, servfil))) + return (struct servent *) NULL; + + if (p = strpbrk(servline, "#\n\r")) + *p = 0; + if (!servline[0]) + goto retry; + + if (!(serv.s_name = strtok(servline, " \t"))) + goto retry; + + if (!(p = strtok(NULL, " \t"))) + goto retry; + + if (!(serv.s_proto = strpbrk(p, "/,"))) + goto retry; + + *serv.s_proto++ = 0; + serv.s_port = htons(atoi(p)); + serv.s_aliases = servalias; + + for (aliascount = 0; aliascount < 7; ) + if (!(servalias[aliascount++] = strtok(NULL, " \t"))) + break; + + servalias[aliascount] = NULL; + + return &serv; +} + +struct servent * getservbyname(const char * name, const char * proto) +{ + struct servent * ent; + char ** al; + setservent(0); + + while (ent = getservent()) { + if (!strcmp(name, ent->s_name)) + goto haveName; + + for (al = ent->s_aliases; *al; ++al) + if (!strcmp(name, *al)) + goto haveName; + + continue; +haveName: + if (!proto || !strcmp(proto, ent->s_proto)) + break; + } + + if (!servstay) + endservent(); + + return ent; +} + +struct servent * getservbyport(int port, const char * proto) +{ + struct servent * ent; + + setservent(0); + + while (ent = getservent()) + if (port == ent->s_port && (!proto || !strcmp(proto, ent->s_proto))) + break; + + if (!servstay) + endservent(); + + return ent; +} + +static char tcp[] = "tcp"; +static char udp[] = "udp"; +#define MAX_PROTOENT 10 +static struct protoent protoents[MAX_PROTOENT]; +static int protoent_count=0; + +struct protoent * getprotobyname(const char * name) +{ + struct protoent *pe; + + pe = &protoents[protoent_count]; + if (strcmp(name, "udp") == 0) { + pe->p_name = udp; + pe->p_proto = IPPROTO_UDP; + } else if (strcmp (name, "tcp") == 0) { + pe->p_name = tcp; + pe->p_proto = IPPROTO_TCP; + } else { + errno = EPROTONOSUPPORT; + return NULL; + } + pe->p_aliases = aliasPtrs; + protoent_count = (protoent_count +1) % MAX_PROTOENT; + return pe; +} + +struct protoent * getprotobynumber(int proto) +{ + struct protoent *pe; + + pe = &protoents[protoent_count]; + if (proto == IPPROTO_UDP) { + pe->p_name = udp; + pe->p_proto = IPPROTO_UDP; + } else if (proto == IPPROTO_TCP) { + pe->p_name = tcp; + pe->p_proto = IPPROTO_TCP; + } else { + errno = EPROTONOSUPPORT; + return NULL; + } + pe->p_aliases = aliasPtrs; + protoent_count = (protoent_count +1) % MAX_PROTOENT; + return pe; +} + |