Received: by E40-PO.MIT.EDU (5.45/4.7) id AA25307; Thu, 16 May 91 01:14:08 EDT
Received: from Lightning.McRCIM.McGill.EDU by ATHENA.MIT.EDU with SMTP
	id AA24032; Thu, 16 May 91 01:13:52 EDT
Received: by lightning.McRCIM.McGill.EDU (5.61)
	id <9105160513.AA05899@lightning.McRCIM.McGill.EDU>; Thu, 16 May 91 01:13:45 -0400
Date: Thu, 16 May 91 01:13:45 -0400
From: der Mouse  <mouse@lightning.McRCIM.McGill.EDU>
Message-Id: <9105160513.AA05899@lightning.McRCIM.McGill.EDU>
To: tytso@ATHENA.MIT.EDU
Subject: Re: DNS performance metering: a wish list for bind 4.8.4

>> I also made it allow specification of the domain search path.
> Isn't that supported in bind 4.8.3 as the "search" keyword?  Or does
> your "path" keyword do something different?  They seem the same to
> me...

Quite possibly they are the same.  It's been a while since I fetched a
fresh copy of bind.  The distribution I have says just "4.8", no
suffix.

>> I can send my code to anyone who wants.
> Yes, yes!  I would love to see your changes!

My rewrite....

> The "toplevel" feature sounds extremely useful!!!

Well, that's why I added it :-)

Here's the code that goes into the local libc.  I am no longer sure
which of these files have been hacked upon...or more precisely which,
if any, haven't been.

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Thu May 16 01:12:18 1991
# Run this through sh to create:
#	Makefile
#	gethostinfo.c
#	gethostnamadr.c
#	herror.c
#	res_comp.c
#	res_debug.c
#	res_init.c
#	res_mkquery.c
#	res_query.c
#	res_send.c
#	sethostent.c
#	netdb.h
#	resolv.h
echo x - Makefile \(5862 characters\)
sed 's/^X//' > Makefile << \EOF
XO = gethostinfo.o gethostnamadr.o herror.o res_comp.o res_debug.o\
X res_init.o res_mkquery.o res_query.o res_send.o sethostent.o
X
XCONFIG = -DCONFFILE=\"/local/mouse/etc/resolv.conf\"
XCFLAGS = -V -DDEBUG $(CONFIG)
X
X.c.o:
X	$(CC) $(CFLAGS) -pic -c $<
X	mv $*.o $*.so
X	$(CC) $(CFLAGS) -c $<
X
Xall: $O
X
Xresolv.a: $O
X	rm -f resolv.a
X	ar cq resolv.a $O
X	ranlib resolv.a
X
Xinstall: $O resolv.a
X	cp $O ../o-files/unshared
X	@echo cp `echo $O | tr ' ' '\012' | sed -e 's/o$$/so/' | tr '\012' ' '` ../o-files/shared | sh -v
X	cp resolv.a /local/mouse/lib/libresolv.a
X	ranlib /local/mouse/lib/libresolv.a
X	( cd ../o-files ; make $(MFLAGS) install )
X
Xdepend:
X	( echo '/^# DO NOT DELETE/+2,$$c' ; \
X	  $(CC) -M $(CFLAGS) *.c | sort | uniq ; \
X	  echo . ; \
X	  echo w ; \
X	  echo q ) | ed - Makefile
X
X# DO NOT DELETE THIS LINE
X
Xgethostinfo.o: /home/lightning/mouse/include/stdio.h
Xgethostinfo.o: /local/mouse/include/netdb.h
Xgethostinfo.o: /local/mouse/include/netinet/in.h
Xgethostinfo.o: /local/mouse/include/resolv.h
Xgethostinfo.o: /local/mouse/include/stdio.h
Xgethostinfo.o: /usr/include/arpa/inet.h
Xgethostinfo.o: /usr/include/arpa/nameser.h
Xgethostinfo.o: /usr/include/ctype.h
Xgethostinfo.o: /usr/include/errno.h
Xgethostinfo.o: /usr/include/machine/param.h
Xgethostinfo.o: /usr/include/sys/errno.h
Xgethostinfo.o: /usr/include/sys/param.h
Xgethostinfo.o: /usr/include/sys/signal.h
Xgethostinfo.o: /usr/include/sys/socket.h
Xgethostinfo.o: /usr/include/sys/stdtypes.h
Xgethostinfo.o: /usr/include/sys/sysmacros.h
Xgethostinfo.o: /usr/include/sys/types.h
Xgethostinfo.o: /usr/include/vm/faultcode.h
Xgethostinfo.o: gethostinfo.c
Xgethostnamadr.o: /home/lightning/mouse/include/stdio.h
Xgethostnamadr.o: /local/mouse/include/netdb.h
Xgethostnamadr.o: /local/mouse/include/netinet/in.h
Xgethostnamadr.o: /local/mouse/include/resolv.h
Xgethostnamadr.o: /local/mouse/include/stdio.h
Xgethostnamadr.o: /usr/include/arpa/inet.h
Xgethostnamadr.o: /usr/include/arpa/nameser.h
Xgethostnamadr.o: /usr/include/ctype.h
Xgethostnamadr.o: /usr/include/errno.h
Xgethostnamadr.o: /usr/include/machine/param.h
Xgethostnamadr.o: /usr/include/sys/errno.h
Xgethostnamadr.o: /usr/include/sys/param.h
Xgethostnamadr.o: /usr/include/sys/signal.h
Xgethostnamadr.o: /usr/include/sys/socket.h
Xgethostnamadr.o: /usr/include/sys/stdtypes.h
Xgethostnamadr.o: /usr/include/sys/sysmacros.h
Xgethostnamadr.o: /usr/include/sys/types.h
Xgethostnamadr.o: /usr/include/vm/faultcode.h
Xgethostnamadr.o: gethostnamadr.c
Xherror.o: /usr/include/sys/stdtypes.h
Xherror.o: /usr/include/sys/sysmacros.h
Xherror.o: /usr/include/sys/types.h
Xherror.o: /usr/include/sys/uio.h
Xherror.o: herror.c
Xres_comp.o: /home/lightning/mouse/include/stdio.h
Xres_comp.o: /local/mouse/include/stdio.h
Xres_comp.o: /usr/include/arpa/nameser.h
Xres_comp.o: /usr/include/sys/stdtypes.h
Xres_comp.o: /usr/include/sys/sysmacros.h
Xres_comp.o: /usr/include/sys/types.h
Xres_comp.o: res_comp.c
Xres_debug.o: /home/lightning/mouse/include/stdio.h
Xres_debug.o: /local/mouse/include/netinet/in.h
Xres_debug.o: /local/mouse/include/stdio.h
Xres_debug.o: /usr/include/arpa/nameser.h
Xres_debug.o: /usr/include/sys/stdtypes.h
Xres_debug.o: /usr/include/sys/sysmacros.h
Xres_debug.o: /usr/include/sys/types.h
Xres_debug.o: res_debug.c
Xres_init.o: /home/lightning/mouse/include/stdio.h
Xres_init.o: /local/mouse/include/netinet/in.h
Xres_init.o: /local/mouse/include/resolv.h
Xres_init.o: /local/mouse/include/stdio.h
Xres_init.o: /usr/include/arpa/inet.h
Xres_init.o: /usr/include/arpa/nameser.h
Xres_init.o: /usr/include/ctype.h
Xres_init.o: /usr/include/sys/socket.h
Xres_init.o: /usr/include/sys/stdtypes.h
Xres_init.o: /usr/include/sys/sysmacros.h
Xres_init.o: /usr/include/sys/types.h
Xres_init.o: res_init.c
Xres_mkquery.o: /home/lightning/mouse/include/stdio.h
Xres_mkquery.o: /local/mouse/include/netinet/in.h
Xres_mkquery.o: /local/mouse/include/resolv.h
Xres_mkquery.o: /local/mouse/include/stdio.h
Xres_mkquery.o: /usr/include/arpa/nameser.h
Xres_mkquery.o: /usr/include/sys/stdtypes.h
Xres_mkquery.o: /usr/include/sys/sysmacros.h
Xres_mkquery.o: /usr/include/sys/types.h
Xres_mkquery.o: res_mkquery.c
Xres_query.o: /home/lightning/mouse/include/stdio.h
Xres_query.o: /local/mouse/include/netdb.h
Xres_query.o: /local/mouse/include/netinet/in.h
Xres_query.o: /local/mouse/include/resolv.h
Xres_query.o: /local/mouse/include/stdio.h
Xres_query.o: /usr/include/arpa/inet.h
Xres_query.o: /usr/include/arpa/nameser.h
Xres_query.o: /usr/include/ctype.h
Xres_query.o: /usr/include/errno.h
Xres_query.o: /usr/include/machine/param.h
Xres_query.o: /usr/include/strings.h
Xres_query.o: /usr/include/sys/errno.h
Xres_query.o: /usr/include/sys/param.h
Xres_query.o: /usr/include/sys/signal.h
Xres_query.o: /usr/include/sys/socket.h
Xres_query.o: /usr/include/sys/stdtypes.h
Xres_query.o: /usr/include/sys/sysmacros.h
Xres_query.o: /usr/include/sys/types.h
Xres_query.o: /usr/include/vm/faultcode.h
Xres_query.o: res_query.c
Xres_send.o: /home/lightning/mouse/include/stdio.h
Xres_send.o: /local/mouse/include/netinet/in.h
Xres_send.o: /local/mouse/include/resolv.h
Xres_send.o: /local/mouse/include/stdio.h
Xres_send.o: /usr/include/arpa/nameser.h
Xres_send.o: /usr/include/errno.h
Xres_send.o: /usr/include/machine/param.h
Xres_send.o: /usr/include/sys/errno.h
Xres_send.o: /usr/include/sys/param.h
Xres_send.o: /usr/include/sys/signal.h
Xres_send.o: /usr/include/sys/socket.h
Xres_send.o: /usr/include/sys/stdtypes.h
Xres_send.o: /usr/include/sys/sysmacros.h
Xres_send.o: /usr/include/sys/time.h
Xres_send.o: /usr/include/sys/types.h
Xres_send.o: /usr/include/sys/uio.h
Xres_send.o: /usr/include/time.h
Xres_send.o: /usr/include/vm/faultcode.h
Xres_send.o: res_send.c
Xsethostent.o: /local/mouse/include/netinet/in.h
Xsethostent.o: /local/mouse/include/resolv.h
Xsethostent.o: /usr/include/arpa/nameser.h
Xsethostent.o: /usr/include/sys/stdtypes.h
Xsethostent.o: /usr/include/sys/sysmacros.h
Xsethostent.o: /usr/include/sys/types.h
Xsethostent.o: sethostent.c
EOF
if test 5862 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile \(should have been 5862 characters\)
fi
echo x - gethostinfo.c \(1514 characters\)
sed 's/^X//' > gethostinfo.c << \EOF
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <ctype.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <errno.h>
X#include <arpa/inet.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
Xstatic char qbuf[512];
Xstatic char abuf[512];
Xstatic HEADER *h;
Xstatic struct hinfo result;
X
Xstruct hinfo *gethostinfo(hname)
Xchar *hname;
X{
X int ancount;
X int qdcount;
X char *ap;
X char *ae;
X int len;
X int n;
X int type;
X int class;
X int rdlen;
X
X n = res_mkquery( QUERY,
X		  hname,
X		  C_ANY,
X		  T_HINFO,
X		  (char *) 0,
X		  0,
X		  (struct rrec *) 0,
X		  &qbuf[0],
X		  sizeof(qbuf) );
X if (n < 0)
X  { return(0);
X  }
X n = res_send(&qbuf[0],n,&abuf[0],sizeof(abuf));
X if (n < 0)
X  { return(0);
X  }
X h = (HEADER *) &abuf[0];
X if (h->rcode != NOERROR)
X  { return(0);
X  }
X ap = (char *) (h+1);
X ae = &qbuf[n];
X ancount = ntohs(h->ancount);
X if (ancount <= 0)
X  { return(0);
X  }
X qdcount = ntohs(h->qdcount);
X for (;qdcount>0;qdcount--)
X  { ap += QFIXEDSZ + dn_skipname(ap);
X  }
X do
X  { n = dn_skipname(ap);
X    if (n < 0)
X     { return(0);
X     }
X    ap += n;
X    type = _getshort(ap);
X    ap += 2;
X    class = _getshort(ap);
X    ap += 2;
X    ap += 4; /* ttl */
X    rdlen = _getshort(ap);
X    ap += 2;
X  } while ((type != T_HINFO) && ((ap += rdlen),1));
X len = 0xff & (int) *ap++;
X if (len > rdlen)
X  { return(0);
X  }
X result.h_cpu = ap;
X ap += len;
X rdlen -= len + 1;
X len = 0xff & (int) *ap;
X *ap++ = '\0';
X if (len > rdlen)
X  { return(0);
X  }
X result.h_os = ap;
X ap[len] = '\0';
X return(&result);
X}
EOF
if test 1514 -ne "`wc -c gethostinfo.c`"
then
echo shar: error transmitting gethostinfo.c \(should have been 1514 characters\)
fi
echo x - gethostnamadr.c \(8321 characters\)
sed 's/^X//' > gethostnamadr.c << \EOF
X/*
X * Copyright (c) 1985, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)gethostnamadr.c	6.32 (Berkeley) 4/12/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <ctype.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <errno.h>
X#include <arpa/inet.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
X#define	MAXALIASES	35
X#define	MAXADDRS	35
X
Xstatic char *h_addr_ptrs[MAXADDRS + 1];
X
Xstatic struct hostent host;
Xstatic char *host_aliases[MAXALIASES];
Xstatic char hostbuf[BUFSIZ+1];
Xstatic struct in_addr host_addr;
Xstatic char HOSTDB[] = "/etc/hosts";
Xstatic FILE *hostf = NULL;
Xstatic char hostaddr[MAXADDRS];
Xstatic char *host_addrs[2];
Xstatic int stayopen = 0;
Xstatic char *any();
X
X#if PACKETSZ > 1024
X#define	MAXPACKET	PACKETSZ
X#else
X#define	MAXPACKET	1024
X#endif
X
Xtypedef union {
X    HEADER hdr;
X    u_char buf[MAXPACKET];
X} querybuf;
X
Xstatic union {
X    long al;
X    char ac;
X} align;
X
X
Xint h_errno;
Xextern errno;
X
Xstatic struct hostent *
Xgetanswer(answer, anslen, iquery)
X	querybuf *answer;
X	int anslen;
X	int iquery;
X{
X	register HEADER *hp;
X	register u_char *cp;
X	register int n;
X	u_char *eom;
X	char *bp, **ap;
X	int type, class, buflen, ancount, qdcount;
X	int haveanswer, getclass = C_ANY;
X	char **hap;
X
X	eom = answer->buf + anslen;
X	/*
X	 * find first satisfactory answer
X	 */
X	hp = &answer->hdr;
X	ancount = ntohs(hp->ancount);
X	qdcount = ntohs(hp->qdcount);
X	bp = hostbuf;
X	buflen = sizeof(hostbuf);
X	cp = answer->buf + sizeof(HEADER);
X	if (qdcount) {
X		if (iquery) {
X			if ((n = dn_expand((char *)answer->buf, eom,
X			     cp, bp, buflen)) < 0) {
X				h_errno = NO_RECOVERY;
X				return ((struct hostent *) NULL);
X			}
X			cp += n + QFIXEDSZ;
X			host.h_name = bp;
X			n = strlen(bp) + 1;
X			bp += n;
X			buflen -= n;
X		} else
X			cp += dn_skipname(cp, eom) + QFIXEDSZ;
X		while (--qdcount > 0)
X			cp += dn_skipname(cp, eom) + QFIXEDSZ;
X	} else if (iquery) {
X		if (hp->aa)
X			h_errno = HOST_NOT_FOUND;
X		else
X			h_errno = TRY_AGAIN;
X		return ((struct hostent *) NULL);
X	}
X	ap = host_aliases;
X	host.h_aliases = host_aliases;
X	hap = h_addr_ptrs;
X#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
X	host.h_addr_list = h_addr_ptrs;
X#endif
X	haveanswer = 0;
X	while (--ancount >= 0 && cp < eom) {
X		if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0)
X			break;
X		cp += n;
X		type = _getshort(cp);
X 		cp += sizeof(u_short);
X		class = _getshort(cp);
X 		cp += sizeof(u_short) + sizeof(u_long);
X		n = _getshort(cp);
X		cp += sizeof(u_short);
X		if (type == T_CNAME) {
X			cp += n;
X			if (ap >= &host_aliases[MAXALIASES-1])
X				continue;
X			*ap++ = bp;
X			n = strlen(bp) + 1;
X			bp += n;
X			buflen -= n;
X			continue;
X		}
X		if (iquery && type == T_PTR) {
X			if ((n = dn_expand((char *)answer->buf, eom,
X			    cp, bp, buflen)) < 0) {
X				cp += n;
X				continue;
X			}
X			cp += n;
X			host.h_name = bp;
X			return(&host);
X		}
X		if (iquery || type != T_A)  {
X#ifdef DEBUG
X			if (_res.options & RES_DEBUG)
X				printf("unexpected answer type %d, size %d\n",
X					type, n);
X#endif
X			cp += n;
X			continue;
X		}
X		if (haveanswer) {
X			if (n != host.h_length) {
X				cp += n;
X				continue;
X			}
X			if (class != getclass) {
X				cp += n;
X				continue;
X			}
X		} else {
X			host.h_length = n;
X			getclass = class;
X			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
X			if (!iquery) {
X				host.h_name = bp;
X				bp += strlen(bp) + 1;
X			}
X		}
X
X		bp += sizeof(align) - ((u_long)bp % sizeof(align));
X
X		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
X#ifdef DEBUG
X			if (_res.options & RES_DEBUG)
X				printf("size (%d) too big\n", n);
X#endif
X			break;
X		}
X		bcopy(cp, *hap++ = bp, n);
X		bp +=n;
X		cp += n;
X		haveanswer++;
X	}
X	if (haveanswer) {
X		*ap = NULL;
X#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
X		*hap = NULL;
X#endif
X			  if (host.h_addr != h_addr_ptrs[0])
X			   { host.h_addr = h_addr_ptrs[0];
X			   }
X		return (&host);
X	} else {
X		h_errno = TRY_AGAIN;
X		return ((struct hostent *) NULL);
X	}
X}
X
Xstruct hostent *
Xgethostbyname(name)
X	char *name;
X{
X	querybuf buf;
X	register char *cp;
X	int n;
X	struct hostent *hp, *gethostdomain();
X	extern struct hostent *_gethtbyname();
X
X	/*
X	 * disallow names consisting only of digits/dots, unless
X	 * they end in a dot.
X	 */
X	if (isdigit(name[0]))
X		for (cp = name;; ++cp) {
X			if (!*cp) {
X				if (*--cp == '.')
X					break;
X				h_errno = HOST_NOT_FOUND;
X				return ((struct hostent *) NULL);
X			}
X			if (!isdigit(*cp) && *cp != '.') 
X				break;
X		}
X
X	if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_search failed\n");
X#endif
X		if (errno == ECONNREFUSED)
X			return (_gethtbyname(name));
X		else
X			return ((struct hostent *) NULL);
X	}
X	return (getanswer(&buf, n, 0));
X}
X
Xstruct hostent *
Xgethostbyaddr(addr, len, type)
X	char *addr;
X	int len, type;
X{
X	int n;
X	querybuf buf;
X	register struct hostent *hp;
X	char qbuf[MAXDNAME];
X	extern struct hostent *_gethtbyaddr();
X	
X	if (type != AF_INET)
X		return ((struct hostent *) NULL);
X	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
X		((unsigned)addr[3] & 0xff),
X		((unsigned)addr[2] & 0xff),
X		((unsigned)addr[1] & 0xff),
X		((unsigned)addr[0] & 0xff));
X	n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
X	if (n < 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_query failed\n");
X#endif
X		if (errno == ECONNREFUSED)
X			return (_gethtbyaddr(addr, len, type));
X		return ((struct hostent *) NULL);
X	}
X	hp = getanswer(&buf, n, 1);
X	if (hp == NULL)
X		return ((struct hostent *) NULL);
X	hp->h_addrtype = type;
X	hp->h_length = len;
X	h_addr_ptrs[0] = (char *)&host_addr;
X	h_addr_ptrs[1] = (char *)0;
X	host_addr = *(struct in_addr *)addr;
X	return(hp);
X}
X
X_sethtent(f)
X	int f;
X{
X	if (hostf == NULL)
X		hostf = fopen(HOSTDB, "r" );
X	else
X		rewind(hostf);
X	stayopen |= f;
X}
X
X_endhtent()
X{
X	if (hostf && !stayopen) {
X		(void) fclose(hostf);
X		hostf = NULL;
X	}
X}
X
Xstruct hostent *
X_gethtent()
X{
X	char *p;
X	register char *cp, **q;
X
X	if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
X		return (NULL);
Xagain:
X	if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
X		return (NULL);
X	if (*p == '#')
X		goto again;
X	cp = any(p, "#\n");
X	if (cp == NULL)
X		goto again;
X	*cp = '\0';
X	cp = any(p, " \t");
X	if (cp == NULL)
X		goto again;
X	*cp++ = '\0';
X	/* THIS STUFF IS INTERNET SPECIFIC */
X#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */
X	host.h_addr_list = host_addrs;
X#endif
X	host.h_addr = hostaddr;
X host.h_addr_list[0] = host.h_addr;
X host.h_addr_list[1] = 0;
X	*((u_long *)host.h_addr) = inet_addr(p);
X	host.h_length = sizeof (u_long);
X	host.h_addrtype = AF_INET;
X	while (*cp == ' ' || *cp == '\t')
X		cp++;
X	host.h_name = cp;
X	q = host.h_aliases = host_aliases;
X	cp = any(cp, " \t");
X	if (cp != NULL) 
X		*cp++ = '\0';
X	while (cp && *cp) {
X		if (*cp == ' ' || *cp == '\t') {
X			cp++;
X			continue;
X		}
X		if (q < &host_aliases[MAXALIASES - 1])
X			*q++ = cp;
X		cp = any(cp, " \t");
X		if (cp != NULL)
X			*cp++ = '\0';
X	}
X	*q = NULL;
X	return (&host);
X}
X
Xstatic char *
Xany(cp, match)
X	register char *cp;
X	char *match;
X{
X	register char *mp, c;
X
X	while (c = *cp) {
X		for (mp = match; *mp; mp++)
X			if (*mp == c)
X				return (cp);
X		cp++;
X	}
X	return ((char *)0);
X}
X
Xstruct hostent *
X_gethtbyname(name)
X	char *name;
X{
X	register struct hostent *p;
X	register char **cp;
X	
X	_sethtent(0);
X	while (p = _gethtent()) {
X		if (strcasecmp(p->h_name, name) == 0)
X			break;
X		for (cp = p->h_aliases; *cp != 0; cp++)
X			if (strcasecmp(*cp, name) == 0)
X				goto found;
X	}
Xfound:
X	_endhtent();
X	return (p);
X}
X
Xstruct hostent *
X_gethtbyaddr(addr, len, type)
X	char *addr;
X	int len, type;
X{
X	register struct hostent *p;
X
X	_sethtent(0);
X	while (p = _gethtent())
X		if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
X			break;
X	_endhtent();
X	return (p);
X}
EOF
if test 8321 -ne "`wc -c gethostnamadr.c`"
then
echo shar: error transmitting gethostnamadr.c \(should have been 8321 characters\)
fi
echo x - herror.c \(1134 characters\)
sed 's/^X//' > herror.c << \EOF
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)herror.c	6.1 (Berkeley) 12/4/87";
X#endif LIBC_SCCS and not lint
X
X#include <sys/types.h>
X#include <sys/uio.h>
X
Xchar	*h_errlist[] = {
X	"Error 0",
X	"Unknown host",				/* 1 HOST_NOT_FOUND */
X	"Host name lookup failure",		/* 2 TRY_AGAIN */
X	"Unknown server error",			/* 3 NO_RECOVERY */
X	"No address associated with name",	/* 4 NO_ADDRESS */
X};
Xint	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
X
Xextern int	h_errno;
X
X/*
X * herror --
X *	print the error indicated by the h_errno value.
X */
Xherror(s)
X	char *s;
X{
X	struct iovec iov[4];
X	register struct iovec *v = iov;
X
X	if (s && *s) {
X		v->iov_base = s;
X		v->iov_len = strlen(s);
X		v++;
X		v->iov_base = ": ";
X		v->iov_len = 2;
X		v++;
X	}
X	v->iov_base = h_errno < h_nerr ? h_errlist[h_errno] : "Unknown error";
X	v->iov_len = strlen(v->iov_base);
X	v++;
X	v->iov_base = "\n";
X	v->iov_len = 1;
X	writev(2, iov, (v - iov) + 1);
X}
EOF
if test 1134 -ne "`wc -c herror.c`"
then
echo shar: error transmitting herror.c \(should have been 1134 characters\)
fi
echo x - res_comp.c \(6631 characters\)
sed 's/^X//' > res_comp.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_comp.c	6.13 (Berkeley) 3/13/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <arpa/nameser.h>
X
X
X/*
X * Expand compressed domain name 'comp_dn' to full domain name.
X * 'msg' is a pointer to the begining of the message,
X * 'eomorig' points to the first location after the message,
X * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
X * Return size of compressed name or -1 if there was an error.
X */
Xdn_expand(msg, eomorig, comp_dn, exp_dn, length)
X	u_char *msg, *eomorig, *comp_dn, *exp_dn;
X	int length;
X{
X	register u_char *cp, *dn;
X	register int n, c;
X	u_char *eom;
X	int len = -1, checked = 0;
X
X	dn = exp_dn;
X	cp = comp_dn;
X	eom = exp_dn + length - 1;
X	/*
X	 * fetch next label in domain name
X	 */
X	while (n = *cp++) {
X		/*
X		 * Check for indirection
X		 */
X		switch (n & INDIR_MASK) {
X		case 0:
X			if (dn != exp_dn) {
X				if (dn >= eom)
X					return (-1);
X				*dn++ = '.';
X			}
X			if (dn+n >= eom)
X				return (-1);
X			checked += n + 1;
X			while (--n >= 0) {
X				if ((c = *cp++) == '.') {
X					if (dn+n+1 >= eom)
X						return (-1);
X					*dn++ = '\\';
X				}
X				*dn++ = c;
X				if (cp >= eomorig)	/* out of range */
X					return(-1);
X			}
X			break;
X
X		case INDIR_MASK:
X			if (len < 0)
X				len = cp - comp_dn + 1;
X			cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
X			if (cp < msg || cp >= eomorig)	/* out of range */
X				return(-1);
X			checked += 2;
X			/*
X			 * Check for loops in the compressed name;
X			 * if we've looked at the whole message,
X			 * there must be a loop.
X			 */
X			if (checked >= eomorig - msg)
X				return (-1);
X			break;
X
X		default:
X			return (-1);			/* flag error */
X		}
X	}
X	*dn = '\0';
X	if (len < 0)
X		len = cp - comp_dn;
X	return (len);
X}
X
X/*
X * Compress domain name 'exp_dn' into 'comp_dn'.
X * Return the size of the compressed name or -1.
X * 'length' is the size of the array pointed to by 'comp_dn'.
X * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
X * is a pointer to the beginning of the message. The list ends with NULL.
X * 'lastdnptr' is a pointer to the end of the arrary pointed to
X * by 'dnptrs'. Side effect is to update the list of pointers for
X * labels inserted into the message as we compress the name.
X * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
X * is NULL, we don't update the list.
X */
Xdn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
X	u_char *exp_dn, *comp_dn;
X	int length;
X	u_char **dnptrs, **lastdnptr;
X{
X	register u_char *cp, *dn;
X	register int c, l;
X	u_char **cpp, **lpp, *sp, *eob;
X	u_char *msg;
X
X	dn = exp_dn;
X	cp = comp_dn;
X	eob = cp + length;
X	if (dnptrs != NULL) {
X		if ((msg = *dnptrs++) != NULL) {
X			for (cpp = dnptrs; *cpp != NULL; cpp++)
X				;
X			lpp = cpp;	/* end of list to search */
X		}
X	} else
X		msg = NULL;
X	for (c = *dn++; c != '\0'; ) {
X		/* look to see if we can use pointers */
X		if (msg != NULL) {
X			if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
X				if (cp+1 >= eob)
X					return (-1);
X				*cp++ = (l >> 8) | INDIR_MASK;
X				*cp++ = l % 256;
X				return (cp - comp_dn);
X			}
X			/* not found, save it */
X			if (lastdnptr != NULL && cpp < lastdnptr-1) {
X				*cpp++ = cp;
X				*cpp = NULL;
X			}
X		}
X		sp = cp++;	/* save ptr to length byte */
X		do {
X			if (c == '.') {
X				c = *dn++;
X				break;
X			}
X			if (c == '\\') {
X				if ((c = *dn++) == '\0')
X					break;
X			}
X			if (cp >= eob)
X				return (-1);
X			*cp++ = c;
X		} while ((c = *dn++) != '\0');
X		/* catch trailing '.'s but not '..' */
X		if ((l = cp - sp - 1) == 0 && c == '\0') {
X			cp--;
X			break;
X		}
X		if (l <= 0 || l > MAXLABEL)
X			return (-1);
X		*sp = l;
X	}
X	if (cp >= eob)
X		return (-1);
X	*cp++ = '\0';
X	return (cp - comp_dn);
X}
X
X/*
X * Skip over a compressed domain name. Return the size or -1.
X */
Xdn_skipname(comp_dn, eom)
X	u_char *comp_dn, *eom;
X{
X	register u_char *cp;
X	register int n;
X
X	cp = comp_dn;
X	while (cp < eom && (n = *cp++)) {
X		/*
X		 * check for indirection
X		 */
X		switch (n & INDIR_MASK) {
X		case 0:		/* normal case, n == len */
X			cp += n;
X			continue;
X		default:	/* illegal type */
X			return (-1);
X		case INDIR_MASK:	/* indirection */
X			cp++;
X		}
X		break;
X	}
X	return (cp - comp_dn);
X}
X
X/*
X * Search for expanded name from a list of previously compressed names.
X * Return the offset from msg if found or -1.
X * dnptrs is the pointer to the first name on the list,
X * not the pointer to the start of the message.
X */
Xstatic
Xdn_find(exp_dn, msg, dnptrs, lastdnptr)
X	u_char *exp_dn, *msg;
X	u_char **dnptrs, **lastdnptr;
X{
X	register u_char *dn, *cp, **cpp;
X	register int n;
X	u_char *sp;
X
X	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
X		dn = exp_dn;
X		sp = cp = *cpp;
X		while (n = *cp++) {
X			/*
X			 * check for indirection
X			 */
X			switch (n & INDIR_MASK) {
X			case 0:		/* normal case, n == len */
X				while (--n >= 0) {
X					if (*dn == '\\')
X						dn++;
X					if (*dn++ != *cp++)
X						goto next;
X				}
X				if ((n = *dn++) == '\0' && *cp == '\0')
X					return (sp - msg);
X				if (n == '.')
X					continue;
X				goto next;
X
X			default:	/* illegal type */
X				return (-1);
X
X			case INDIR_MASK:	/* indirection */
X				cp = msg + (((n & 0x3f) << 8) | *cp);
X			}
X		}
X		if (*dn == '\0')
X			return (sp - msg);
X	next:	;
X	}
X	return (-1);
X}
X
X/*
X * Routines to insert/extract short/long's. Must account for byte
X * order and non-alignment problems. This code at least has the
X * advantage of being portable.
X *
X * used by sendmail.
X */
X
Xu_short
X_getshort(msgp)
X	u_char *msgp;
X{
X	register u_char *p = (u_char *) msgp;
X#ifdef vax
X	/*
X	 * vax compiler doesn't put shorts in registers
X	 */
X	register u_long u;
X#else
X	register u_short u;
X#endif
X
X	u = *p++ << 8;
X	return ((u_short)(u | *p));
X}
X
Xu_long
X_getlong(msgp)
X	u_char *msgp;
X{
X	register u_char *p = (u_char *) msgp;
X	register u_long u;
X
X	u = *p++; u <<= 8;
X	u |= *p++; u <<= 8;
X	u |= *p++; u <<= 8;
X	return (u | *p);
X}
X
X
Xputshort(s, msgp)
X	register u_short s;
X	register u_char *msgp;
X{
X
X	msgp[1] = s;
X	msgp[0] = s >> 8;
X}
X
Xputlong(l, msgp)
X	register u_long l;
X	register u_char *msgp;
X{
X
X	msgp[3] = l;
X	msgp[2] = (l >>= 8);
X	msgp[1] = (l >>= 8);
X	msgp[0] = l >> 8;
X}
EOF
if test 6631 -ne "`wc -c res_comp.c`"
then
echo shar: error transmitting res_comp.c \(should have been 6631 characters\)
fi
echo x - res_debug.c \(8845 characters\)
sed 's/^X//' > res_debug.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_debug.c	5.22 (Berkeley) 3/7/88";
X#endif /* LIBC_SCCS and not lint */
X
X#if defined(lint) && !defined(DEBUG)
X#define DEBUG
X#endif
X
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <stdio.h>
X#include <arpa/nameser.h>
X
Xextern char *p_cdname(), *p_rr(), *p_type(), *p_class();
Xextern char *inet_ntoa();
X
Xchar *_res_opcodes[] = {
X	"QUERY",
X	"IQUERY",
X	"CQUERYM",
X	"CQUERYU",
X	"4",
X	"5",
X	"6",
X	"7",
X	"8",
X	"UPDATEA",
X	"UPDATED",
X	"UPDATEDA",
X	"UPDATEM",
X	"UPDATEMA",
X	"ZONEINIT",
X	"ZONEREF",
X};
X
Xchar *_res_resultcodes[] = {
X	"NOERROR",
X	"FORMERR",
X	"SERVFAIL",
X	"NXDOMAIN",
X	"NOTIMP",
X	"REFUSED",
X	"6",
X	"7",
X	"8",
X	"9",
X	"10",
X	"11",
X	"12",
X	"13",
X	"14",
X	"NOCHANGE",
X};
X
Xp_query(msg)
X	char *msg;
X{
X#ifdef DEBUG
X	fp_query(msg,stdout);
X#endif
X}
X
X/*
X * Print the contents of a query.
X * This is intended to be primarily a debugging routine.
X */
Xfp_query(msg,file)
X	char *msg;
X	FILE *file;
X{
X#ifdef DEBUG
X	register char *cp;
X	register HEADER *hp;
X	register int n;
X
X	/*
X	 * Print header fields.
X	 */
X	hp = (HEADER *)msg;
X	cp = msg + sizeof(HEADER);
X	fprintf(file,"HEADER:\n");
X	fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]);
X	fprintf(file,", id = %d", ntohs(hp->id));
X	fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]);
X	fprintf(file,"\theader flags: ");
X	if (hp->qr)
X		fprintf(file," qr");
X	if (hp->aa)
X		fprintf(file," aa");
X	if (hp->tc)
X		fprintf(file," tc");
X	if (hp->rd)
X		fprintf(file," rd");
X	if (hp->ra)
X		fprintf(file," ra");
X	if (hp->pr)
X		fprintf(file," pr");
X	fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount));
X	fprintf(file,", ancount = %d", ntohs(hp->ancount));
X	fprintf(file,", nscount = %d", ntohs(hp->nscount));
X	fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount));
X	/*
X	 * Print question records.
X	 */
X	if (n = ntohs(hp->qdcount)) {
X		fprintf(file,"QUESTIONS:\n");
X		while (--n >= 0) {
X			fprintf(file,"\t");
X			cp = p_cdname(cp, msg, file);
X			if (cp == NULL)
X				return;
X			fprintf(file,", type = %s", p_type(_getshort(cp)));
X			cp += sizeof(u_short);
X			fprintf(file,", class = %s\n\n", p_class(_getshort(cp)));
X			cp += sizeof(u_short);
X		}
X	}
X	/*
X	 * Print authoritative answer records
X	 */
X	if (n = ntohs(hp->ancount)) {
X		fprintf(file,"ANSWERS:\n");
X		while (--n >= 0) {
X			fprintf(file,"\t");
X			cp = p_rr(cp, msg, file);
X			if (cp == NULL)
X				return;
X		}
X	}
X	/*
X	 * print name server records
X	 */
X	if (n = ntohs(hp->nscount)) {
X		fprintf(file,"NAME SERVERS:\n");
X		while (--n >= 0) {
X			fprintf(file,"\t");
X			cp = p_rr(cp, msg, file);
X			if (cp == NULL)
X				return;
X		}
X	}
X	/*
X	 * print additional records
X	 */
X	if (n = ntohs(hp->arcount)) {
X		fprintf(file,"ADDITIONAL RECORDS:\n");
X		while (--n >= 0) {
X			fprintf(file,"\t");
X			cp = p_rr(cp, msg, file);
X			if (cp == NULL)
X				return;
X		}
X	}
X#endif
X}
X
Xchar *
Xp_cdname(cp, msg, file)
X	char *cp, *msg;
X	FILE *file;
X{
X#ifdef DEBUG
X	char name[MAXDNAME];
X	int n;
X
X	if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0)
X		return (NULL);
X	if (name[0] == '\0') {
X		name[0] = '.';
X		name[1] = '\0';
X	}
X	fputs(name, file);
X	return (cp + n);
X#endif
X}
X
X/*
X * Print resource record fields in human readable form.
X */
Xchar *
Xp_rr(cp, msg, file)
X	char *cp, *msg;
X	FILE *file;
X{
X#ifdef DEBUG
X	int type, class, dlen, n, c;
X	struct in_addr inaddr;
X	char *cp1;
X
X	if ((cp = p_cdname(cp, msg, file)) == NULL)
X		return (NULL);			/* compression error */
X	fprintf(file,"\n\ttype = %s", p_type(type = _getshort(cp)));
X	cp += sizeof(u_short);
X	fprintf(file,", class = %s", p_class(class = _getshort(cp)));
X	cp += sizeof(u_short);
X	fprintf(file,", ttl = %u", _getlong(cp));
X	cp += sizeof(u_long);
X	fprintf(file,", dlen = %d\n", dlen = _getshort(cp));
X	cp += sizeof(u_short);
X	cp1 = cp;
X	/*
X	 * Print type specific data, if appropriate
X	 */
X	switch (type) {
X	case T_A:
X		switch (class) {
X		case C_IN:
X			bcopy(cp, (char *)&inaddr, sizeof(inaddr));
X			if (dlen == 4) {
X				fprintf(file,"\tinternet address = %s\n",
X					inet_ntoa(inaddr));
X				cp += dlen;
X			} else if (dlen == 7) {
X				fprintf(file,"\tinternet address = %s",
X					inet_ntoa(inaddr));
X				fprintf(file,", protocol = %d", cp[4]);
X				fprintf(file,", port = %d\n",
X					(cp[5] << 8) + cp[6]);
X				cp += dlen;
X			}
X			break;
X		default:
X			cp += dlen;
X		}
X		break;
X	case T_CNAME:
X	case T_MB:
X#ifdef OLDRR
X	case T_MD:
X	case T_MF:
X#endif /* OLDRR */
X	case T_MG:
X	case T_MR:
X	case T_NS:
X	case T_PTR:
X		fprintf(file,"\tdomain name = ");
X		cp = p_cdname(cp, msg, file);
X		fprintf(file,"\n");
X		break;
X
X	case T_HINFO:
X		if (n = *cp++) {
X			fprintf(file,"\tCPU=%.*s\n", n, cp);
X			cp += n;
X		}
X		if (n = *cp++) {
X			fprintf(file,"\tOS=%.*s\n", n, cp);
X			cp += n;
X		}
X		break;
X
X	case T_SOA:
X		fprintf(file,"\torigin = ");
X		cp = p_cdname(cp, msg, file);
X		fprintf(file,"\n\tmail addr = ");
X		cp = p_cdname(cp, msg, file);
X		fprintf(file,"\n\tserial=%ld", _getlong(cp));
X		cp += sizeof(u_long);
X		fprintf(file,", refresh=%ld", _getlong(cp));
X		cp += sizeof(u_long);
X		fprintf(file,", retry=%ld", _getlong(cp));
X		cp += sizeof(u_long);
X		fprintf(file,", expire=%ld", _getlong(cp));
X		cp += sizeof(u_long);
X		fprintf(file,", min=%ld\n", _getlong(cp));
X		cp += sizeof(u_long);
X		break;
X
X	case T_MX:
X		fprintf(file,"\tpreference = %ld,",_getshort(cp));
X		cp += sizeof(u_short);
X		fprintf(file," name = ");
X		cp = p_cdname(cp, msg, file);
X		break;
X
X	case T_MINFO:
X		fprintf(file,"\trequests = ");
X		cp = p_cdname(cp, msg, file);
X		fprintf(file,"\n\terrors = ");
X		cp = p_cdname(cp, msg, file);
X		break;
X
X	case T_UINFO:
X		fprintf(file,"\t%s\n", cp);
X		cp += dlen;
X		break;
X
X	case T_UID:
X	case T_GID:
X		if (dlen == 4) {
X			fprintf(file,"\t%ld\n", _getlong(cp));
X			cp += sizeof(int);
X		}
X		break;
X
X	case T_WKS:
X		if (dlen < sizeof(u_long) + 1)
X			break;
X		bcopy(cp, (char *)&inaddr, sizeof(inaddr));
X		cp += sizeof(u_long);
X		fprintf(file,"\tinternet address = %s, protocol = %d\n\t",
X			inet_ntoa(inaddr), *cp++);
X		n = 0;
X		while (cp < cp1 + dlen) {
X			c = *cp++;
X			do {
X 				if (c & 0200)
X					fprintf(file," %d", n);
X 				c <<= 1;
X			} while (++n & 07);
X		}
X		putc('\n',file);
X		break;
X
X#ifdef ALLOW_T_UNSPEC
X	case T_UNSPEC:
X		{
X			int NumBytes = 8;
X			char *DataPtr;
X			int i;
X
X			if (dlen < NumBytes) NumBytes = dlen;
X			fprintf(file, "\tFirst %d bytes of hex data:",
X				NumBytes);
X			for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
X				fprintf(file, " %x", *DataPtr);
X			fputs("\n", file);
X			cp += dlen;
X		}
X		break;
X#endif /* ALLOW_T_UNSPEC */
X
X	default:
X		fprintf(file,"\t???\n");
X		cp += dlen;
X	}
X	if (cp != cp1 + dlen)
X		fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
X	fprintf(file,"\n");
X	return (cp);
X#endif
X}
X
Xstatic	char nbuf[20];
X
X/*
X * Return a string for the type
X */
Xchar *
Xp_type(type)
X	int type;
X{
X	switch (type) {
X	case T_A:
X		return("A");
X	case T_NS:		/* authoritative server */
X		return("NS");
X#ifdef OLDRR
X	case T_MD:		/* mail destination */
X		return("MD");
X	case T_MF:		/* mail forwarder */
X		return("MF");
X#endif /* OLDRR */
X	case T_CNAME:		/* connonical name */
X		return("CNAME");
X	case T_SOA:		/* start of authority zone */
X		return("SOA");
X	case T_MB:		/* mailbox domain name */
X		return("MB");
X	case T_MG:		/* mail group member */
X		return("MG");
X	case T_MX:		/* mail routing info */
X		return("MX");
X	case T_MR:		/* mail rename name */
X		return("MR");
X	case T_NULL:		/* null resource record */
X		return("NULL");
X	case T_WKS:		/* well known service */
X		return("WKS");
X	case T_PTR:		/* domain name pointer */
X		return("PTR");
X	case T_HINFO:		/* host information */
X		return("HINFO");
X	case T_MINFO:		/* mailbox information */
X		return("MINFO");
X	case T_AXFR:		/* zone transfer */
X		return("AXFR");
X	case T_MAILB:		/* mail box */
X		return("MAILB");
X	case T_MAILA:		/* mail address */
X		return("MAILA");
X	case T_ANY:		/* matches any type */
X		return("ANY");
X	case T_UINFO:
X		return("UINFO");
X	case T_UID:
X		return("UID");
X	case T_GID:
X		return("GID");
X#ifdef ALLOW_T_UNSPEC
X	case T_UNSPEC:
X		return("UNSPEC");
X#endif /* ALLOW_T_UNSPEC */
X	default:
X		(void)sprintf(nbuf, "%d", type);
X		return(nbuf);
X	}
X}
X
X/*
X * Return a mnemonic for class
X */
Xchar *
Xp_class(class)
X	int class;
X{
X
X	switch (class) {
X	case C_IN:		/* internet class */
X		return("IN");
X	case C_ANY:		/* matches any class */
X		return("ANY");
X	default:
X		(void)sprintf(nbuf, "%d", class);
X		return(nbuf);
X	}
X}
EOF
if test 8845 -ne "`wc -c res_debug.c`"
then
echo shar: error transmitting res_debug.c \(should have been 8845 characters\)
fi
echo x - res_init.c \(4612 characters\)
sed 's/^X//' > res_init.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_init.c	6.8 (Berkeley) 3/7/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <resolv.h>
X#include <arpa/inet.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <arpa/nameser.h>
X
Xchar *getenv();
X
X/*
X * Resolver configuration file. Contains the address of the
X * inital name server to query and the default domain for
X * non fully qualified domain names.
X */
X
X#ifndef	CONFFILE
X#define	CONFFILE "/etc/resolv.conf"
X#endif
Xchar *_res_conffile = CONFFILE;
X#define conffile _res_conffile
X
X/*
X * Resolver state default settings
X */
X
Xstruct state _res = { RES_TIMEOUT,	/* retransmition time interval */
X		      4,		/* number of times to retransmit */
X		      RES_DEFAULT,	/* options flags */
X		      1 };		/* number of name servers */
X
X/*
X * Set up default settings.  If the configuration file exists, the
X *  values there will have precedence.  Otherwise, the server address
X *  is set to INADDR_ANY and the default domain name comes from the
X *  gethostname().
X *
X * Return 0 if completes successfully, -1 on error
X */
Xres_init()
X{
X FILE *fp;
X char *cp;
X char **pp;
X char buf[BUFSIZ];
X int n;
X
X if (getenv("__RES_DEBUG")) _res.options |= RES_DEBUG;
X _res.nsaddr_list[0].sin_addr.s_addr = htonl(0x7f000001); /* INADDR_ANY? */
X _res.nsaddr_list[0].sin_family = AF_INET;
X _res.nsaddr_list[0].sin_port = htons(NAMESERVER_PORT);
X _res.nscount = 1;
X for (n=0;n<MAXDNSRCH;n++)
X  { _res.dnsrch[n] = 0;
X  }
X for (n=0;n<MAXTOPLEVEL;n++)
X  { _res.dnsrch[n] = 0;
X  }
X n = 0;
X fp = fopen(conffile,"r");
X if (fp)
X  { while (fgets(&buf[0],sizeof(buf),fp) == &buf[0])
X     { if (!strncmp(&buf[0],"nameserver",10) && (n < MAXNS))
X	{ cp = &buf[10];
X	  while (*cp && isascii(*cp) && isspace(*cp)) cp ++;
X	  if (*cp == '\0') continue;
X	  _res.nsaddr_list[n].sin_addr.s_addr = inet_addr(cp);
X	  if (_res.nsaddr_list[n].sin_addr.s_addr == (unsigned long int)-1)
X	   { _res.nsaddr_list[n].sin_addr.s_addr = INADDR_ANY;
X	   }
X	  _res.nsaddr_list[n].sin_family = AF_INET;
X	  _res.nsaddr_list[n].sin_port = htons(NAMESERVER_PORT);
X	  if (++n >= MAXNS)
X	   { n = MAXNS;
X#ifdef DEBUG
X	     if (_res.options & RES_DEBUG)
X	      { printf("MAXNS (%d) reached while reading %s\n",MAXNS,conffile);
X	      }
X#endif DEBUG
X	   }
X	  continue;
X	}
X       else if (!strncmp(&buf[0],"path",4))
X	{ int i;
X	  int l;
X	  static char pathbuf[256];
X	  static int pbfill = 0;
X	  cp = &buf[4];
X	  while (*cp && isascii(*cp) && isspace(*cp))
X	   { cp ++;
X	   }
X	  l = strlen(cp);
X	  if ((l > 0) && (cp[l-1] == '\n')) cp[--l] = '\0';
X	  if (l < 1) continue;
X	  for (i=0;(i<MAXDNSRCH)&&_res.dnsrch[i];i++) ;
X	  if (i < MAXDNSRCH)
X	   { if (pbfill+l < sizeof(pathbuf))
X	      { strcpy(&pathbuf[pbfill],cp);
X		_res.dnsrch[i] = &pathbuf[pbfill];
X		pbfill += l + 1;
X	      }
X#ifdef DEBUG
X	     else if (_res.options & RES_DEBUG)
X	      { printf("Out of path space while reading %s\n",conffile);
X	      }
X#endif DEBUG
X	   }
X#ifdef DEBUG
X	  else if (_res.options & RES_DEBUG)
X	   { printf("Out of dnsrch space while reading %s\n",conffile);
X	   }
X#endif DEBUG
X	  continue;
X	}
X       else if (!strncmp(&buf[0],"toplevel",8))
X	{ int i;
X	  int l;
X	  static char tlbuf[256];
X	  static int tbfill = 0;
X	  cp = &buf[8];
X	  while (*cp && isascii(*cp) && isspace(*cp))
X	   { cp ++;
X	   }
X	  l = strlen(cp);
X	  if ((l > 0) && (cp[l-1] == '\n'))
X	   { cp[--l] = '\0';
X	   }
X	  if (l < 1)
X	   { continue;
X	   }
X	  for (i=0;(i<MAXTOPLEVEL)&&_res.toplvl[i];i++) ;
X	  if (i < MAXTOPLEVEL)
X	   { if (tbfill+l < sizeof(tlbuf))
X	      { strcpy(&tlbuf[tbfill],cp);
X		_res.toplvl[i] = &tlbuf[tbfill];
X		tbfill += l + 1;
X	      }
X#ifdef DEBUG
X	     else if (_res.options & RES_DEBUG)
X	      { printf("Out of tlbuf space while reading %s\n",conffile);
X	      }
X#endif DEBUG
X	   }
X#ifdef DEBUG
X	  else if (_res.options & RES_DEBUG)
X	   { printf("Out of toplvl space while reading %s\n",conffile);
X	   }
X#endif DEBUG
X	  continue;
X	}
X     }
X    if (n > 1)
X     { _res.nscount = n;
X     }
X    fclose(fp);
X  }
X _res.options |= RES_INIT;
X return(0);
X}
EOF
if test 4612 -ne "`wc -c res_init.c`"
then
echo shar: error transmitting res_init.c \(should have been 4612 characters\)
fi
echo x - res_mkquery.c \(4818 characters\)
sed 's/^X//' > res_mkquery.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_mkquery.c	6.7 (Berkeley) 3/7/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
X/*
X * Form all types of queries.
X * Returns the size of the result or -1.
X */
Xres_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
X	int op;			/* opcode of query */
X	char *dname;		/* domain name */
X	int class, type;	/* class and type of query */
X	char *data;		/* resource record data */
X	int datalen;		/* length of data */
X	struct rrec *newrr;	/* new rr for modify or append */
X	char *buf;		/* buffer to put query */
X	int buflen;		/* size of buffer */
X{
X	register HEADER *hp;
X	register char *cp;
X	register int n;
X	char dnbuf[MAXDNAME];
X	char *dnptrs[10], **dpp, **lastdnptr;
X	extern char *index();
X
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG)
X		printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
X#endif DEBUG
X	/*
X	 * Initialize header fields.
X	 */
X	hp = (HEADER *) buf;
X	hp->id = htons(++_res.id);
X	hp->opcode = op;
X	hp->qr = hp->aa = hp->tc = hp->ra = 0;
X	hp->pr = (_res.options & RES_PRIMARY) != 0;
X	hp->rd = (_res.options & RES_RECURSE) != 0;
X	hp->rcode = NOERROR;
X	hp->qdcount = 0;
X	hp->ancount = 0;
X	hp->nscount = 0;
X	hp->arcount = 0;
X	cp = buf + sizeof(HEADER);
X	buflen -= sizeof(HEADER);
X	dpp = dnptrs;
X	*dpp++ = buf;
X	*dpp++ = NULL;
X	lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
X	/*
X	 * perform opcode specific processing
X	 */
X	switch (op) {
X	case QUERY:
X		buflen -= QFIXEDSZ;
X		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
X			return (-1);
X		cp += n;
X		buflen -= n;
X		putshort(type, cp);
X		cp += sizeof(u_short);
X		putshort(class, cp);
X		cp += sizeof(u_short);
X		hp->qdcount = htons(1);
X		if (op == QUERY || data == NULL)
X			break;
X		/*
X		 * Make an additional record for completion domain.
X		 */
X		buflen -= RRFIXEDSZ;
X		if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
X			return (-1);
X		cp += n;
X		buflen -= n;
X		putshort(T_NULL, cp);
X		cp += sizeof(u_short);
X		putshort(class, cp);
X		cp += sizeof(u_short);
X		putlong(0, cp);
X		cp += sizeof(u_long);
X		putshort(0, cp);
X		cp += sizeof(u_short);
X		hp->arcount = htons(1);
X		break;
X
X	case IQUERY:
X		/*
X		 * Initialize answer section
X		 */
X		if (buflen < 1 + RRFIXEDSZ + datalen)
X			return (-1);
X		*cp++ = '\0';	/* no domain name */
X		putshort(type, cp);
X		cp += sizeof(u_short);
X		putshort(class, cp);
X		cp += sizeof(u_short);
X		putlong(0, cp);
X		cp += sizeof(u_long);
X		putshort(datalen, cp);
X		cp += sizeof(u_short);
X		if (datalen) {
X			bcopy(data, cp, datalen);
X			cp += datalen;
X		}
X		hp->ancount = htons(1);
X		break;
X
X#ifdef ALLOW_UPDATES
X	/*
X	 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
X	 * (Record to be modified is followed by its replacement in msg.)
X	 */
X	case UPDATEM:
X	case UPDATEMA:
X
X	case UPDATED:
X		/*
X		 * The res code for UPDATED and UPDATEDA is the same; user
X		 * calls them differently: specifies data for UPDATED; server
X		 * ignores data if specified for UPDATEDA.
X		 */
X	case UPDATEDA:
X		buflen -= RRFIXEDSZ + datalen;
X		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
X			return (-1);
X		cp += n;
X		putshort(type, cp);
X                cp += sizeof(u_short);
X                putshort(class, cp);
X                cp += sizeof(u_short);
X		putlong(0, cp);
X		cp += sizeof(u_long);
X		putshort(datalen, cp);
X                cp += sizeof(u_short);
X		if (datalen) {
X			bcopy(data, cp, datalen);
X			cp += datalen;
X		}
X		if ( (op == UPDATED) || (op == UPDATEDA) ) {
X			hp->ancount = htons(0);
X			break;
X		}
X		/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
X
X	case UPDATEA:	/* Add new resource record */
X		buflen -= RRFIXEDSZ + datalen;
X		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
X			return (-1);
X		cp += n;
X		putshort(newrr->r_type, cp);
X                cp += sizeof(u_short);
X                putshort(newrr->r_class, cp);
X                cp += sizeof(u_short);
X		putlong(0, cp);
X		cp += sizeof(u_long);
X		putshort(newrr->r_size, cp);
X                cp += sizeof(u_short);
X		if (newrr->r_size) {
X			bcopy(newrr->r_data, cp, newrr->r_size);
X			cp += newrr->r_size;
X		}
X		hp->ancount = htons(0);
X		break;
X
X#endif ALLOW_UPDATES
X	}
X	return (cp - buf);
X}
EOF
if test 4818 -ne "`wc -c res_mkquery.c`"
then
echo shar: error transmitting res_mkquery.c \(should have been 4818 characters\)
fi
echo x - res_query.c \(6376 characters\)
sed 's/^X//' > res_query.c << \EOF
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_query.c	5.4 (Berkeley) 4/21/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <ctype.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <errno.h>
X#include <strings.h>
X#include <arpa/inet.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
X#if PACKETSZ > 1024
X#define MAXPACKET	PACKETSZ
X#else
X#define MAXPACKET	1024
X#endif
X
Xextern int errno;
Xint h_errno;
X
X/*
X * Formulate a normal query, send, and await answer.
X * Returned answer is placed in supplied buffer "answer".
X * Perform preliminary check of answer, returning success only
X * if no error is indicated and the answer count is nonzero.
X * Return the size of the response on success, -1 on error.
X * Error number is left in h_errno.
X * Caller must parse answer and determine whether it answers the question.
X */
Xres_query(name, class, type, answer, anslen)
X	char *name;		/* domain name */
X	int class, type;	/* class and type of query */
X	u_char *answer;		/* buffer to put answer */
X	int anslen;		/* size of answer buffer */
X{
X	char buf[MAXPACKET];
X	HEADER *hp;
X	int n;
X
X	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
X		return (-1);
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG)
X		printf("res_query(%s, %d, %d)\n", name, class, type);
X#endif
X	n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
X	    buf, sizeof(buf));
X
X	if (n <= 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_query: mkquery failed\n");
X#endif
X		h_errno = NO_RECOVERY;
X		return (n);
X	}
X	n = res_send(buf, n, answer, anslen);
X	if (n < 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_query: send error\n");
X#endif
X		h_errno = TRY_AGAIN;
X		return(n);
X	}
X
X	hp = (HEADER *) answer;
X	if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("rcode = %d, ancount=%d\n", hp->rcode,
X			    ntohs(hp->ancount));
X#endif
X		switch (hp->rcode) {
X			case NXDOMAIN:
X				h_errno = HOST_NOT_FOUND;
X				break;
X			case SERVFAIL:
X				h_errno = TRY_AGAIN;
X				break;
X			case NOERROR:
X				h_errno = NO_DATA;
X				break;
X			case FORMERR:
X			case NOTIMP:
X			case REFUSED:
X			default:
X				h_errno = NO_RECOVERY;
X				break;
X		}
X		return (-1);
X	}
X	return(n);
X}
X
X/*
X * Formulate a normal query, send, and retrieve answer in supplied buffer.
X * Return the size of the response on success, -1 on error.
X * If enabled, implement search rules until answer or unrecoverable failure
X * is detected.  Error number is left in h_errno.
X * Only useful for queries in the same name hierarchy as the local host
X * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
X */
Xres_search(name,class,type,answer,anslen)
Xchar *name;		/* domain name */
Xint class;		/* class of query */
Xint type;		/* type of query */
Xu_char *answer;		/* buffer to put answer in */
Xint anslen;		/* size of answer */
X{
X char *cp;
X char *lastdot;
X char **domain;
X int nosearch;
X int ret;
X char *hostalias();
X int had_no_data;
X
X if (((_res.options & RES_INIT) == 0) && (res_init() == -1)) return(-1);
X errno = 0;
X h_errno = HOST_NOT_FOUND;
X nosearch = ! (_res.options & RES_DNSRCH);
X lastdot = 0;
X for (cp=name;*cp;cp++) if (*cp == '.') lastdot = cp;
X if (! lastdot)
X  { cp = hostalias(name);
X    if (cp) return(res_query(cp,class,type,answer,anslen));
X  }
X if (lastdot && !nosearch)
X  { if (lastdot[1])
X     { lastdot ++;
X       for (domain=(&_res.toplvl[0]);*domain;domain++)
X	{ if (! strcasecmp(*domain,lastdot))
X	   { nosearch = 1;
X	     break;
X	   }
X	}
X     }
X    else
X     { nosearch = 1;
X     }
X  }
X if (nosearch)
X  { return(res_querydomain(name,(char *)0,class,type,answer,anslen));
X  }
X had_no_data = 0;
X for (domain=(&_res.dnsrch[0]);*domain;domain++)
X  { ret = res_querydomain(name,*domain,class,type,answer,anslen);
X    if (ret > 0) return(ret);
X    if (errno == ECONNREFUSED)
X     { h_errno = TRY_AGAIN;
X       return(-1);
X     }
X    if (h_errno == NO_DATA) had_no_data = 1;
X    if ((h_errno != HOST_NOT_FOUND) && (h_errno != NO_DATA)) break;
X  }
X if (lastdot) return(res_querydomain(name,(char *)0,class,type,answer,anslen));
X if (had_no_data) h_errno = NO_DATA;
X return(-1);
X}
X
X/*
X * Perform a call on res_query on the concatenation of name and domain,
X * removing a trailing dot from name if domain is NULL.
X */
Xres_querydomain(name, domain, class, type, answer, anslen)
X	char *name, *domain;
X	int class, type;	/* class and type of query */
X	u_char *answer;		/* buffer to put answer */
X	int anslen;		/* size of answer */
X{
X	char nbuf[2*MAXDNAME+2];
X	char *longname = nbuf;
X	int n;
X
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG)
X		printf("res_querydomain(%s, %s, %d, %d)\n",
X		    name, domain, class, type);
X#endif
X	if (domain == NULL) {
X		/*
X		 * Check for trailing '.';
X		 * copy without '.' if present.
X		 */
X		n = strlen(name) - 1;
X		if (name[n] == '.' && n < sizeof(nbuf) - 1) {
X			bcopy(name, nbuf, n);
X			nbuf[n] = '\0';
X		} else
X			longname = name;
X	} else
X		(void)sprintf(nbuf, "%.*s.%.*s",
X		    MAXDNAME, name, MAXDNAME, domain);
X
X	return (res_query(longname, class, type, answer, anslen));
X}
X
Xchar *
Xhostalias(name)
X	register char *name;
X{
X	register char *C1, *C2;
X	FILE *fp;
X	char *file, *getenv(), *strcpy(), *strncpy();
X	char buf[BUFSIZ];
X	static char abuf[MAXDNAME];
X
X	file = getenv("HOSTALIASES");
X	if (file == NULL || (fp = fopen(file, "r")) == NULL)
X		return (NULL);
X	buf[sizeof(buf) - 1] = '\0';
X	while (fgets(buf, sizeof(buf), fp)) {
X		for (C1 = buf; *C1 && !isspace(*C1); ++C1);
X		if (!*C1)
X			break;
X		*C1 = '\0';
X		if (!strcasecmp(buf, name)) {
X			while (isspace(*++C1));
X			if (!*C1)
X				break;
X			for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
X			abuf[sizeof(abuf) - 1] = *C2 = '\0';
X			(void)strncpy(abuf, C1, sizeof(abuf) - 1);
X			fclose(fp);
X			return (abuf);
X		}
X	}
X	fclose(fp);
X	return (NULL);
X}
EOF
if test 6376 -ne "`wc -c res_query.c`"
then
echo shar: error transmitting res_query.c \(should have been 6376 characters\)
fi
echo x - res_send.c \(7975 characters\)
sed 's/^X//' > res_send.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_send.c	6.19 (Berkeley) 3/7/88";
X#endif /* LIBC_SCCS and not lint */
X
X/*
X * Send query to name server and wait for reply.
X */
X
X#include <sys/param.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X#include <sys/uio.h>
X#include <netinet/in.h>
X#include <stdio.h>
X#include <errno.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
Xextern int errno;
X
Xstatic int s = -1;	/* socket used for communications */
Xstatic struct sockaddr no_addr;
X  
X
X#ifndef FD_SET
X#define	NFDBITS		32
X#define	FD_SETSIZE	32
X#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
X#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
X#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
X#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
X#endif
X
X#define KEEPOPEN (RES_USEVC|RES_STAYOPEN)
X
Xres_send(buf, buflen, answer, anslen)
X	char *buf;
X	int buflen;
X	char *answer;
X	int anslen;
X{
X	register int n;
X	int retry, v_circuit, resplen, ns;
X	int gotsomewhere = 0, connected = 0;
X	u_short id, len;
X	char *cp;
X	fd_set dsmask;
X	struct timeval timeout;
X	HEADER *hp = (HEADER *) buf;
X	HEADER *anhp = (HEADER *) answer;
X	struct iovec iov[2];
X	int terrno = ETIMEDOUT;
X	char junk[512];
X
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG) {
X		printf("res_send()\n");
X		p_query(buf);
X	}
X#endif DEBUG
X	if (!(_res.options & RES_INIT))
X		if (res_init() == -1) {
X			return(-1);
X		}
X	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
X	id = hp->id;
X	/*
X	 * Send request, RETRY times, or until successful
X	 */
X	for (retry = _res.retry; retry > 0; retry--) {
X	   for (ns = 0; ns < _res.nscount; ns++) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("Querying server (# %d) address = %s\n", ns+1,
X			      inet_ntoa(_res.nsaddr_list[ns].sin_addr));
X#endif DEBUG
X		if (v_circuit) {
X			int truncated = 0;
X
X			/*
X			 * Use virtual circuit.
X			 */
X			if (s < 0) {
X				s = socket(AF_INET, SOCK_STREAM, 0);
X				if (s < 0) {
X					terrno = errno;
X#ifdef DEBUG
X					if (_res.options & RES_DEBUG)
X					    perror("socket failed");
X#endif DEBUG
X					continue;
X				}
X				if (connect(s, &(_res.nsaddr_list[ns]),
X				   sizeof(struct sockaddr)) < 0) {
X					terrno = errno;
X#ifdef DEBUG
X					if (_res.options & RES_DEBUG)
X					    perror("connect failed");
X#endif DEBUG
X					(void) close(s);
X					s = -1;
X					continue;
X				}
X			}
X			/*
X			 * Send length & message
X			 */
X			len = htons((u_short)buflen);
X			iov[0].iov_base = (caddr_t)&len;
X			iov[0].iov_len = sizeof(len);
X			iov[1].iov_base = buf;
X			iov[1].iov_len = buflen;
X			if (writev(s, iov, 2) != sizeof(len) + buflen) {
X				terrno = errno;
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("write failed");
X#endif DEBUG
X				(void) close(s);
X				s = -1;
X				continue;
X			}
X			/*
X			 * Receive length & response
X			 */
X			cp = answer;
X			len = sizeof(short);
X			while (len != 0 &&
X			    (n = read(s, (char *)cp, (int)len)) > 0) {
X				cp += n;
X				len -= n;
X			}
X			if (n <= 0) {
X				terrno = errno;
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("read failed");
X#endif DEBUG
X				(void) close(s);
X				s = -1;
X				continue;
X			}
X			cp = answer;
X			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					fprintf(stderr, "response truncated\n");
X#endif DEBUG
X				len = anslen;
X				truncated = 1;
X			} else
X				len = resplen;
X			while (len != 0 &&
X			   (n = read(s, (char *)cp, (int)len)) > 0) {
X				cp += n;
X				len -= n;
X			}
X			if (n <= 0) {
X				terrno = errno;
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("read failed");
X#endif DEBUG
X				(void) close(s);
X				s = -1;
X				continue;
X			}
X			if (truncated) {
X				/*
X				 * Flush rest of answer
X				 * so connection stays in synch.
X				 */
X				anhp->tc = 1;
X				len = resplen - anslen;
X				while (len != 0) {
X					n = (len > sizeof(junk) ?
X					    sizeof(junk) : len);
X					if ((n = read(s, junk, n)) > 0)
X						len -= n;
X					else
X						break;
X				}
X			}
X		} else {
X			/*
X			 * Use datagrams.
X			 */
X			if (s < 0)
X				s = socket(AF_INET, SOCK_DGRAM, 0);
X#if	BSD >= 43
X			if (_res.nscount == 1 || retry == _res.retry) {
X				/*
X				 * Don't use connect if we might
X				 * still receive a response
X				 * from another server.
X				 */
X				if (connected == 0) {
X					if (connect(s, &_res.nsaddr_list[ns],
X					    sizeof(struct sockaddr)) < 0) {
X#ifdef DEBUG
X						if (_res.options & RES_DEBUG)
X							perror("connect");
X#endif DEBUG
X						continue;
X					}
X					connected = 1;
X				}
X				if (send(s, buf, buflen, 0) != buflen) {
X#ifdef DEBUG
X					if (_res.options & RES_DEBUG)
X						perror("send");
X#endif DEBUG
X					continue;
X				}
X			} else
X#endif BSD
X			if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns],
X			    sizeof(struct sockaddr)) != buflen) {
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("sendto");
X#endif DEBUG
X				continue;
X			}
X
X			/*
X			 * Wait for reply
X			 */
X			timeout.tv_sec = (_res.retrans << (_res.retry - retry))
X				/ _res.nscount;
X			if (timeout.tv_sec <= 0)
X				timeout.tv_sec = 1;
X			timeout.tv_usec = 0;
Xwait:
X			FD_ZERO(&dsmask);
X			FD_SET(s, &dsmask);
X			n = select(s+1, &dsmask, (fd_set *)NULL,
X				(fd_set *)NULL, &timeout);
X			if (n < 0) {
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("select");
X#endif DEBUG
X				continue;
X			}
X			if (n == 0) {
X				/*
X				 * timeout
X				 */
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					printf("timeout\n");
X#endif DEBUG
X				/*
X				 * Disconnect if we want to listen
X				 * for responses from more than one server.
X				 */
X				if (_res.nscount > 1 && connected) {
X					(void) connect(s, &no_addr,
X					    sizeof(no_addr));
X					connected = 0;
X				}
X				gotsomewhere = 1;
X				continue;
X			}
X			if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					perror("recvfrom");
X#endif DEBUG
X				continue;
X			}
X			gotsomewhere = 1;
X			if (id != anhp->id) {
X				/*
X				 * response from old query, ignore it
X				 */
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG) {
X					printf("old answer:\n");
X					p_query(answer);
X				}
X#endif DEBUG
X				goto wait;
X			}
X			if (!(_res.options & RES_IGNTC) && anhp->tc) {
X				/*
X				 * get rest of answer
X				 */
X#ifdef DEBUG
X				if (_res.options & RES_DEBUG)
X					printf("truncated answer\n");
X#endif DEBUG
X				(void) close(s);
X				s = -1;
X				/*
X				 * retry decremented on continue
X				 * to desired starting value
X				 */
X				retry = _res.retry + 1;
X				v_circuit = 1;
X				continue;
X			}
X		}
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG) {
X			printf("got answer:\n");
X			p_query(answer);
X		}
X#endif DEBUG
X		/*
X		 * We are going to assume that the first server is preferred
X		 * over the rest (i.e. it is on the local machine) and only
X		 * keep that one open.
X		 */
X		if ((_res.options & KEEPOPEN) == KEEPOPEN && ns == 0) {
X			return (resplen);
X		} else {
X			(void) close(s);
X			s = -1;
X			return (resplen);
X		}
X	   }
X	}
X	if (s >= 0) {
X		(void) close(s);
X		s = -1;
X	}
X	if (v_circuit == 0)
X		if (gotsomewhere == 0)
X			errno = ECONNREFUSED;
X		else
X			errno = ETIMEDOUT;
X	else
X		errno = terrno;
X	return (-1);
X}
X
X/*
X * This routine is for closing the socket if a virtual circuit is used and
X * the program wants to close it.  This provides support for endhostent()
X * which expects to close the socket.
X *
X * This routine is not expected to be user visible.
X */
X_res_close()
X{
X	if (s != -1) {
X		(void) close(s);
X		s = -1;
X	}
X}
EOF
if test 7975 -ne "`wc -c res_send.c`"
then
echo shar: error transmitting res_send.c \(should have been 7975 characters\)
fi
echo x - sethostent.c \(656 characters\)
sed 's/^X//' > sethostent.c << \EOF
X/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)sethostent.c	6.3 (Berkeley) 4/10/86";
X#endif LIBC_SCCS and not lint
X
X#include <sys/types.h>
X#include <arpa/nameser.h>
X#include <netinet/in.h>
X#include <resolv.h>
X
Xsethostent(stayopen)
X{
X	if (stayopen)
X		_res.options |= RES_STAYOPEN | RES_USEVC;
X}
X
Xendhostent()
X{
X	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
X	_res_close();
X}
X
Xsethostfile(name)
Xchar *name;
X{
X#ifdef lint
Xname = name;
X#endif
X}
EOF
if test 656 -ne "`wc -c sethostent.c`"
then
echo shar: error transmitting sethostent.c \(should have been 656 characters\)
fi
echo x - netdb.h \(2617 characters\)
sed 's/^X//' > netdb.h << \EOF
X#ifndef _NETDB_H_2d3983ad_
X#define _NETDB_H_2d3983ad_
X
X/*
X * Copyright (c) 1980,1983,1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X *	@(#)netdb.h	5.9 (Berkeley) 4/5/88
X */
X
X/*
X * Structures returned by network data base library.  All addresses are
X *  supplied in host order, and returned in network order (suitable for
X *  use in system calls).
X */
Xstruct hostent {
X  char *h_name;			/* official name of host */
X  char **h_aliases;		/* alias list */
X  int h_addrtype;		/* host address type */
X  int h_length;			/* length of address */
X  char **h_addr_list;		/* list of addresses from name server */
X  } ;
X#define h_addr h_addr_list[0]	/* address, for backward compatiblity */
X
X/*
X * Assumption here is that a network number
X * fits in 32 bits -- probably a poor one.
X */
Xstruct netent {
X  char *n_name;			/* official name of net */
X  char **n_aliases;		/* alias list */
X  int n_addrtype;		/* net address type */
X  unsigned long int n_net;	/* network # */
X  } ;
X
Xstruct servent {
X  char *s_name;			/* official service name */
X  char **s_aliases;		/* alias list */
X  int s_port;			/* port # */
X  char *s_proto;		/* protocol to use */
X  } ;
X
Xstruct protoent {
X  char *p_name;			/* official protocol name */
X  char **p_aliases;		/* alias list */
X  int p_proto;			/* protocol # */
X  } ;
X
Xstruct hinfo {
X  char *h_cpu;
X  char *h_os;
X  } ;
X
Xstruct hinfo *gethostinfo();
Xstruct hostent *gethostbyaddr();
Xstruct hostent *gethostbyname();
Xstruct hostent *gethostent();
Xstruct netent *getnetbyaddr();
Xstruct netent *getnetbyname();
Xstruct netent *getnetent();
Xstruct protoent *getprotobyname();
Xstruct protoent *getprotobynumber();
Xstruct protoent *getprotoent();
Xstruct servent *getservbyname();
Xstruct servent *getservbyport();
Xstruct servent *getservent();
X
X/* Error return codes from gethostby*() */
X
Xextern int h_errno;
X
X#define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
X#define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
X#define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
X#define	NO_DATA		4 /* Valid name, no data record of requested type */
X#define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
X
X#endif
EOF
if test 2617 -ne "`wc -c netdb.h`"
then
echo shar: error transmitting netdb.h \(should have been 2617 characters\)
fi
echo x - resolv.h \(1916 characters\)
sed 's/^X//' > resolv.h << \EOF
X#ifndef _RESOLV_H_7d037d29_
X#define _RESOLV_H_7d037d29_
X
X/*
X * Copyright (c) 1983, 1987 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X *	@(#)resolv.h	5.5 (Berkeley) 5/12/87
X */
X
X#include <netinet/in.h>
X#include <arpa/nameser.h>
X
X/*
X * Global defines and variables for resolver stub.
X */
X
X#define MAXNS        8 /* max # nameserver lines in resolv.conf */
X#define MAXDNSRCH   16 /* max # of path lines in resolv.conf */
X#define MAXTOPLEVEL 16 /* max # of toplevel lines in resolv.conf */
X
X#define RES_TIMEOUT  4 /* seconds between retries */
X
Xstruct state {
X  int retrans;					/* retry interval */
X  int retry;					/* # of retries */
X  long int options;				/* option flags (see below) */
X  int nscount;					/* number of nameservers */
X  struct sockaddr_in nsaddr_list[MAXNS];	/* nameserver addresses */
X  unsigned short int id;			/* current packet id */
X  char *dnsrch[MAXDNSRCH+1];			/* domains to search */
X  char *toplvl[MAXTOPLEVEL+1];			/* top-level domains */
X  } ;
X
X/*
X * Resolver options
X */
X#define RES_INIT     0x00000001 /* address initialized */
X#define RES_DEBUG    0x00000002 /* print debug messages */
X#define RES_AAONLY   0x00000004 /* authoritative answers only */
X#define RES_USEVC    0x00000008 /* use virtual circuit */
X#define RES_PRIMARY  0x00000010 /* query primary server only */
X#define RES_IGNTC    0x00000020 /* ignore trucation errors */
X#define RES_RECURSE  0x00000040 /* recursion desired */
X#define RES_DEFNAMES 0x00000080 /* use default domain name */
X#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */
X#define RES_DNSRCH   0x00000200 /* search up local domain tree */
X
X#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
X
Xextern struct state _res;
Xextern char *p_cdname();
Xextern char *p_rr();
Xextern char *p_type();
Xextern char *p_class();
X
X#endif
EOF
if test 1916 -ne "`wc -c resolv.h`"
then
echo shar: error transmitting resolv.h \(should have been 1916 characters\)
fi
exit 0
# end of shell archive

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu
