summaryrefslogtreecommitdiffstats
path: root/Mac/Unsupported/GUSI1-mods/GUSINetDB.cp
diff options
context:
space:
mode:
Diffstat (limited to 'Mac/Unsupported/GUSI1-mods/GUSINetDB.cp')
-rw-r--r--Mac/Unsupported/GUSI1-mods/GUSINetDB.cp582
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;
+}
+