Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!bcm!soma!masscomp-request
From: sob@cortex.neuro.bcm.tmc.edu (Stan Barber)
Newsgroups: comp.sys.masscomp
Subject: name server resolver library for MASSCOMP (part 2 of 7)
Message-ID: <3470@soma.bcm.tmc.edu>
Date: 5 Jul 88 00:59:43 GMT
Sender: masscomp@soma.bcm.tmc.edu
Lines: 1481
Approved: masscomp@soma.bcm.tmc.edu

If you are on the internet and want your Masscomp to understand the Domain
Name Service, here is the first step. This is the resolver library.
This code is based on BIND 4.8 with all patches to date.

Enjoy.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	tools/nslookup/Makefile
#	tools/nslookup/commands.l
#	tools/nslookup/debug.c
#	tools/nslookup/getinfo.c
# This archive created: Mon Jul  4 20:27:53 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test ! -d 'tools'
then
	echo shar: "creating directory 'tools'"
	mkdir 'tools'
fi
echo shar: "entering directory 'tools'"
cd 'tools'
if test ! -d 'nslookup'
then
	echo shar: "creating directory 'nslookup'"
	mkdir 'nslookup'
fi
echo shar: "entering directory 'nslookup'"
cd 'nslookup'
echo shar: "extracting 'Makefile'" '(1666 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'Makefile'
	X#
	X# Copyright (c) 1987 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#	from @(#)Makefile	5.16 (Berkeley) 2/20/88
	X#
	XSHELL=/bin/sh
	XCFLAGS=	-O -DSYS5 -DEXOS -I../../include -I/usr/include/NET-5000
	XRES=	../../res/libresolv.a
	XLIBC=	/lib/libc.a
	XLIBS=	-ll ${RES} -lsocket
	XCSRCS=	main.c getinfo.c debug.c send.c skip.c list.c subr.c
	XSRCS=	${CSRCS} commands.c
	XOBJS=	main.o getinfo.o debug.o send.o skip.o list.o subr.o commands.o
	X
	X.SUFFIXES: .1 .0
	X
	X.1.0:
	X	../manroff $*.1 > $*.0
	X
	Xnslookup: ${OBJS} ${LIBC}
	X	${CC} -o $@ ${OBJS} ${LIBS}
	X
	Xclean: FRC
	X	rm -f ${OBJS} core nslookup commands.c nslookup.0 lex.yy.c lex.yy.o
	X
	Xdepend: ${SRCS} FRC
	X	../mkdep ${CFLAGS} ${SRCS}
	X
	Xinstall: nslookup.0 FRC
	X	../installit -s -o bin -g bin -m 755 nslookup ${DESTDIR}/usr/local/nslookup
	X	../installit -c -o bin -g bin -m 444 nslookup.help ${DESTDIR}/usr/local/nslookup.help
	X	../installit -c -o bin -g bin -m 444 nslookup.0 ${DESTDIR}/usr/local/man/cat1/nslookup.0
	X
	Xlint: ${SRCS} FRC
	X	lint ${CFLAGS} ${SRCS}
	X
	Xtags: ${CSRCS} FRC
	X	ctags ${CSRCS}
	X
	XFRC:
	X
	X# DO NOT DELETE THIS LINE -- mkdep uses it.
	X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
	X
	Xmain.c:
	Xgetinfo.c:
	Xdebug.c:
	Xsend.c:
	Xskip.c:
	Xlist.c:
	Xsubr.c:
	Xcommands.c:
	X
	X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
SHAR_EOF
if test 1666 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 1666 characters)'
fi
fi
echo shar: "extracting 'commands.l'" '(3974 characters)'
if test -f 'commands.l'
then
	echo shar: "will not over-write existing file 'commands.l'"
else
sed 's/^	X//' << \SHAR_EOF > 'commands.l'
	X%{
	X/*
	X *******************************************************************************
	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 *	@(#)commands.l	5.6 (Berkeley) 11/20/87
	X *
	X *  commands.l
	X *
	X *  	Andrew Cherenson 	CS298-26  Fall 1985
	X *
	X *	Lex input file for the nslookup program command interpreter.
	X *	When a sequence is recognized, the associated action
	X *	routine is called. The action routine may need to
	X *	parse the string for additional information.
	X *
	X *  Recognized commands: (identifiers are shown in uppercase)
	X *
	X *	server NAME	- set default server to NAME, using default server
	X *	lserver NAME	- set default server to NAME, using initial server
	X *	finger [NAME]	- finger the optional NAME
	X *	root		- set default server to the root
	X *	ls NAME		- list the domain NAME
	X *	view FILE	- sorts and view the file with more
	X *	set OPTION	- set an option
	X *	help 		- print help information
	X *	? 		- print help information
	X *	opt[ions]	- print options, current server, host
	X *	NAME		- print info about the host/domain NAME 
	X *			  using default server.
	X *	NAME1 NAME2	- as above, but use NAME2 as server
	X *
	X *
	X *   yylex Results:
	X *	0		upon end-of-file.
	X *	1		after each command.
	X *  
	X *******************************************************************************
	X */
	X
	X#include "res.h"
	Xextern char rootServerName[];
	X
	X%}
	XWS	[ \t]
	XLET	[A-Za-z0-9.*]
	XNAME	[A-Za-z0-9.*=_/-]
	X%%
	X^{WS}*server{WS}+{LET}{NAME}*{WS}*$ 	{ 
	X					    /* 
	X					     * 0 == use current server to find
	X					     *	    the new one.
	X					     * 1 == use original server to find
	X					     *	    the new one.
	X					     */
	X					    SetDefaultServer(yytext, 0); 
	X					    return(1);
	X					}
	X^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ 	{ 
	X					    SetDefaultServer(yytext, 1); 
	X					    return(1);
	X					}
	X^{WS}*root{WS}*$ 			{ 
	X					    SetDefaultServer(rootServerName, 1);
	X					    return(1);
	X					}
	X^{WS}*finger({WS}+{LET}{NAME}*)?{WS}+>>?{WS}*{NAME}+{WS}*$ 	{
	X					    /* 
	X					     * 2nd arg. 
	X					     *  0 == output to stdout
	X					     *  1 == output to file
	X					     */
	X					    Finger(yytext, 1); 
	X					    return(1);
	X					}
	X^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ 	{ 
	X					    Finger(yytext, 0); 
	X					    return(1);
	X					}
	X^{WS}*view{WS}+{NAME}+{WS}*$ 	{ 
	X					    ViewList(yytext); 
	X					    return(1);
	X					}
	X^{WS}*ls{WS}+(("-a"|"-h"|"-m"|"-s"|"-d"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$	{ 
	X  					    /* 
	X  					     * 2nd arg. 
	X  					     *  0 == output to stdout
	X					     *  1 == output to file
	X					     */
	X					    ListHosts(yytext, 1);
	X					    return(1);
	X					}
	X^{WS}*ls{WS}+(("-a"|"-h"|"-m"|"-s"|"-d"){WS}+)?{LET}{NAME}*{WS}*$ 	{ 
	X					    ListHosts(yytext, 0);
	X					    return(1);
	X					}
	X^{WS}*set{WS}+{NAME}+{WS}*$	 	{ 
	X					    SetOption(yytext); 
	X					    return(1);
	X					}
	X^{WS}*help{WS}*$ 			{ 
	X					    extern void PrintHelp();
	X
	X					    PrintHelp();
	X					    return(1);
	X					}
	X^{WS}*"?"{WS}*$ 			{ 
	X					    PrintHelp();
	X					    return(1);
	X					}
	X^{WS}*opt(ions)?{WS}*$ 			{ 
	X					    ShowOptions(TRUE); 
	X					    return(1);
	X					}
	X^{WS}*{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ 	{
	X					    /* 
	X					     * 0 == output to stdout
	X					     * 1 == output to file
	X					     */
	X					    LookupHost(yytext, 1); 
	X					    return(1);
	X					}
	X^{WS}*{LET}{NAME}*{WS}*$		{
	X					    LookupHost(yytext, 0); 
	X					    return(1);
	X					}
	X^{WS}*{LET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ 	{
	X					    /* 
	X					     * 0 == output to stdout
	X					     * 1 == output to file
	X					     */
	X					    LookupHostWithServer(yytext, 1); 
	X					    return(1);
	X					}
	X^{WS}*{LET}{NAME}*{WS}+{LET}{NAME}*{WS}*$	{
	X					    LookupHostWithServer(yytext, 0); 
	X					    return(1);
	X					}
	X^{WS}*\n				{ 
	X					    return(1);
	X					}
	X^.*\n					{ 
	X					    printf("Unrecognized command: %s", 
	X					    		yytext); 
	X					    return(1);
	X					}
	X\n					{ ; }
	X%%
SHAR_EOF
if test 3974 -ne "`wc -c < 'commands.l'`"
then
	echo shar: "error transmitting 'commands.l'" '(should have been 3974 characters)'
fi
fi
echo shar: "extracting 'debug.c'" '(8484 characters)'
if test -f 'debug.c'
then
	echo shar: "will not over-write existing file 'debug.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'debug.c'
	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#ifndef lint
	Xstatic char sccsid[] = "@(#)debug.c	5.11 (Berkeley) 4/5/88";
	X#endif /* not lint */
	X
	X/*
	X *******************************************************************************
	X *
	X *  debug.c --
	X *
	X *	Routines to print out packets received from a name server query.
	X *
	X *      Modified version of 4.3BSD BIND res_debug.c 5.6 9/14/85
	X *
	X *******************************************************************************
	X */
	X
	X#include 
	X#ifdef EXOS
	X#include 
	X#endif
	X#include 
	X#include 
	X#include 
	X#include 
	X#include "res.h"
	X
	Xextern char ctime();
	X
	X/*
	X *  Imported from res_debug.c
	X */
	Xextern char *_res_resultcodes[];
	Xextern char *_res_opcodes[];
	X
	X/*
	X *  Used to highlight the start of a record when printing it.
	X */
	X#define INDENT "    ->  "
	X
	X
	X
	X/*
	X * Print the contents of a query.
	X * This is intended to be primarily a debugging routine.
	X */
	X
	XPrint_query(msg, eom, printHeader)
	X	char *msg, *eom;
	X	int printHeader;
	X{
	X	Fprint_query(msg, eom, printHeader,stdout);
	X}
	X
	XFprint_query(msg, eom, printHeader,file)
	X	char *msg, *eom;
	X	int printHeader;
	X	FILE *file;
	X{
	X	register char *cp;
	X	register HEADER *hp;
	X	register int n;
	X	short class;
	X	short type;
	X
	X	/*
	X	 * Print header fields.
	X	 */
	X	hp = (HEADER *)msg;
	X	cp = msg + sizeof(HEADER);
	X	if (printHeader || (_res.options & RES_DEBUG2)) {
	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," response");
	X	    } else {
	X		    fprintf(file," query");
	X	    }
	X	    if (hp->aa)
	X		    fprintf(file,", auth. answer");
	X	    if (hp->tc)
	X		    fprintf(file,", truncation");
	X	    if (hp->rd)
	X		    fprintf(file,", want recursion");
	X	    if (hp->ra)
	X		    fprintf(file,", recursion avail.");
	X	    if (hp->pr)
	X		    fprintf(file,", primary");
	X	    fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount));
	X	    fprintf(file,",  answers = %d", ntohs(hp->ancount));
	X	    fprintf(file,",  auth. records = %d", ntohs(hp->nscount));
	X	    fprintf(file,",  additional = %d\n\n", ntohs(hp->arcount));
	X	}
	X
	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 = Print_cdname(cp, msg, eom, file);
	X			if (cp == NULL)
	X				return;
	X			type = _getshort(cp);
	X			cp += sizeof(u_short);
	X			class = _getshort(cp);
	X			cp += sizeof(u_short);
	X			fprintf(file,", type = %s", p_type(type));
	X			fprintf(file,", class = %s\n", p_class(class));
	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, INDENT);
	X			cp = Print_rr(cp, msg, eom, 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,"    AUTHORITY RECORDS:\n");
	X		while (--n >= 0) {
	X			fprintf(file, INDENT);
	X			cp = Print_rr(cp, msg, eom, 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, INDENT);
	X			cp = Print_rr(cp, msg, eom, file);
	X			if (cp == NULL)
	X				return;
	X		}
	X	}
	X	fprintf(file,"\n------------\n");
	X
	X}
	X
	X
	Xchar *
	XPrint_cdname_sub(cp, msg, eom, file, format)
	X	char *cp, *msg, *eom;
	X	FILE *file;
	X	int format;
	X{
	X	int n;
	X	char name[MAXDNAME];
	X	extern char *strcpy();
	X
	X	if ((n = dn_expand(msg, eom, cp, name, sizeof(name))) < 0)
	X		return (NULL);
	X	if (name[0] == '\0') {
	X	    (void) strcpy(name, "(root)");
	X	}
	X	if (format) {
	X	    fprintf(file, "%-30s", name);
	X	} else {
	X	    fputs(name, file);
	X	}
	X	return (cp + n);
	X}
	X
	Xchar *
	XPrint_cdname(cp, msg, eom, file)
	X	char *cp, *msg, *eom;
	X	FILE *file;
	X{
	X    return(Print_cdname_sub(cp, msg, eom, file, 0));
	X}
	X
	Xchar *
	XPrint_cdname2(cp, msg, eom, file)
	X	char *cp, *msg, *eom;
	X	FILE *file;
	X{
	X    return(Print_cdname_sub(cp, msg, eom, file, 1));
	X}
	X
	X/*
	X * Print resource record fields in human readable form.
	X */
	Xchar *
	XPrint_rr(cp, msg, eom, file)
	X	char *cp, *msg, *eom;
	X	FILE *file;
	X{
	X	int type, class, dlen, n, c;
	X	long ttl;
	X	struct in_addr inaddr;
	X	char *cp1;
	X
	X	if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) {
	X		fprintf(file, "(name truncated?)\n");
	X		return (NULL);			/* compression error */
	X	}
	X
	X	type = _getshort(cp);
	X	cp += sizeof(u_short);
	X	class = _getshort(cp);
	X	cp += sizeof(u_short);
	X	ttl = _getlong(cp);
	X	cp += sizeof(u_long);
	X	dlen = _getshort(cp);
	X	cp += sizeof(u_short);
	X
	X	if (_res.options & RES_DEBUG2) {
	X	    fprintf(file,"\n\ttype = %s, class = %s, ttl = %u, dlen = %d",
	X			p_type(type), p_class(class), ttl, dlen);
	X	    fprintf(file,"\n");
	X	}
	X
	X	cp1 = cp;
	X
	X	/*
	X	 * Print type specific data, if appropriate
	X	 */
	X	switch (type) {
	X	case T_A:
	X		switch (class) {
	X		case C_IN:
	X#ifdef SYS5
	X			(void)memcpy((char *)&inaddr, cp, sizeof(inaddr));
	X#else
	X			bcopy(cp, (char *)&inaddr, sizeof(inaddr));
	X#endif
	X			if (dlen == 4) {
	X				fprintf(file,"\tinet address = %s\n",
	X					inet_ntoa(inaddr));
	X				cp += dlen;
	X			} else if (dlen == 7) {
	X				fprintf(file,"\tinet 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			fprintf(file,"\taddress, class = %d, len = %d\n",
	X			    class, dlen);
	X		}
	X		break;
	X
	X	case T_CNAME:
	X		fprintf(file,"\tcanonical name = ");
	X		goto doname;
	X
	X	case T_MX:
	X		fprintf(file,"\tpreference = %d",_getshort(cp));
	X		cp += sizeof(u_short);
	X		fprintf(file,", mail exchanger = ");
	X		goto doname;
	X
	X	case T_MG:
	X		fprintf(file,"\tmail group member = ");
	X		goto doname;
	X	case T_MB:
	X		fprintf(file,"\tmail box = ");
	X		goto doname;
	X	case T_MR:
	X		fprintf(file,"\tmailbox rename = ");
	X		goto doname;
	X	case T_NS:
	X		fprintf(file,"\tnameserver = ");
	X		goto doname;
	X	case T_PTR:
	X		fprintf(file,"\thost name = ");
	Xdoname:
	X		cp = Print_cdname(cp, msg, eom, file);
	X		fprintf(file,"\n");
	X		break;
	X
	X	case T_HINFO:
	X		if (n = *cp++) {
	X			fprintf(file,"\tCPU=%.*s", 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 = Print_cdname(cp, msg, eom, file);
	X		fprintf(file,"\n\tmail addr = ");
	X		cp = Print_cdname(cp, msg, eom, 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_MINFO:
	X		fprintf(file,"\trequests = ");
	X		cp = Print_cdname(cp, msg, eom, file);
	X		fprintf(file,"\n\terrors = ");
	X		cp = Print_cdname(cp, msg, eom, 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%cid %ld\n", type == T_UID ? 'u' : 'g',
	X			    _getlong(cp));
	X			cp += sizeof(int);
	X		} else
	X			fprintf(file,"\t%cid of length %ld?\n",
	X			    type == T_UID ? 'u' : 'g', dlen);
	X		break;
	X
	X	case T_WKS:
	X		if (dlen < sizeof(u_long) + 1)
	X			break;
	X#ifdef SYS5
	X		(void)memcpy((char *)&inaddr, cp, sizeof(inaddr));
	X#else
	X		bcopy(cp, (char *)&inaddr, sizeof(inaddr));
	X#endif
	X		cp += sizeof(u_long);
	X		fprintf(file,"\tinet 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	case T_NULL:
	X		fprintf(file, "(type NULL, dlen %d)\n", dlen);
	X		break;
	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	return (cp);
	X}
SHAR_EOF
if test 8484 -ne "`wc -c < 'debug.c'`"
then
	echo shar: "error transmitting 'debug.c'" '(should have been 8484 characters)'
fi
fi
echo shar: "extracting 'getinfo.c'" '(19262 characters)'
if test -f 'getinfo.c'
then
	echo shar: "will not over-write existing file 'getinfo.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'getinfo.c'
	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#ifndef lint
	Xstatic char sccsid[] = "@(#)getinfo.c	5.16 (Berkeley) 3/11/88";
	X#endif /* not lint */
	X
	X/*
	X *******************************************************************************
	X *
	X *  getinfo.c --
	X *
	X *	Routines to create requests to name servers 
	X *	and interpret the answers.
	X *
	X *	Adapted from 4.3BSD BIND gethostnamadr.c
	X *
	X *******************************************************************************
	X */
	X
	X#include 
	X#ifdef EXOS
	X#include 
	X#endif
	X#include 
	X#include 
	X#include 
	X#include 
	X#include 
	X#include 
	X#include "res.h"
	X
	Xextern char *_res_resultcodes[];
	Xextern char *res_skip();
	X
	X#define	MAXALIASES	35
	X#define MAXADDRS	35
	X#define MAXDOMAINS	35
	X#define MAXSERVERS	10
	X
	Xstatic char *addr_list[MAXADDRS + 1];
	X
	Xstatic char *host_aliases[MAXALIASES];
	Xstatic int   host_aliases_len[MAXALIASES];
	Xstatic char  hostbuf[BUFSIZ+1];
	X
	Xtypedef struct {
	X    char *name;
	X    char *domain[MAXDOMAINS];
	X    int   numDomains;
	X    char *address[MAXADDRS];
	X    int   numAddresses;
	X} ServerTable;
	X
	XServerTable server[MAXSERVERS];
	X
	Xtypedef union {
	X    HEADER qb1;
	X    char qb2[PACKETSZ];
	X} querybuf;
	X
	Xstatic union {
	X    long al;
	X    char ac;
	X} align;
	X
	X
	X/*
	X *******************************************************************************
	X *
	X *  GetAnswer --
	X *
	X *	Interprets an answer packet and retrieves the following
	X *	information:
	X *
	X *  Results:
	X *      SUCCESS         the info was retrieved.
	X *      NO_INFO         the packet did not contain an answer.
	X *	NONAUTH		non-authoritative information was found.
	X *      ERROR           the answer was malformed.
	X *      Other errors    returned in the packet header.
	X *
	X *******************************************************************************
	X */
	X
	Xstatic int
	XGetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isserver)
	X	struct in_addr 		*nsAddrPtr;
	X	char 			*msg;
	X	int 			queryType;
	X	int 			msglen;
	X	int 			iquery;
	X	register HostInfo 	*hostPtr;
	X	int			isserver;
	X{
	X	register HEADER 	*headerPtr;
	X	register char 		*cp;
	X	querybuf 		answer;
	X	char 			*eom, *bp, **aliasPtr;
	X	char 			**addrPtr;
	X	char			*namePtr;
	X	char			*dnamePtr;
	X	int 			type, class;
	X	int 			qdcount, ancount, arcount, nscount, buflen;
	X	int 			haveanswer, getclass;
	X	int 			numAliases = 0;
	X	int 			numAddresses = 0;
	X	int 			n, i, j;
	X	int 			len;
	X	int 			dlen;
	X	int 			status;
	X	int			numServers;
	X	int			found;
	X
	X
	X	/*
	X	 *  If the hostPtr was used before, free up 
	X	 *  the calloc'd areas.
	X	 */
	X	FreeHostInfoPtr(hostPtr);
	X	    
	X	status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer, 
	X				sizeof(answer), &n, !isserver);
	X
	X	if (status != SUCCESS) {
	X		if (_res.options & RES_DEBUG2)
	X			printf("SendRequest failed\n");
	X		return (status);
	X	}
	X	eom = (char *) &answer + n;
	X
	X	headerPtr = (HEADER *) &answer;
	X	qdcount = ntohs(headerPtr->qdcount);
	X	ancount = ntohs(headerPtr->ancount);
	X	arcount = ntohs(headerPtr->arcount);
	X	nscount = ntohs(headerPtr->nscount);
	X
	X	if (headerPtr->rcode != NOERROR) {
	X	    if (_res.options & RES_DEBUG && !isserver) {
	X		printf(
	X		"Failed: %s, num. answers = %d, ns = %d, additional = %d\n", 
	X			_res_resultcodes[headerPtr->rcode], ancount, nscount,
	X			arcount);
	X	    }
	X	    return (headerPtr->rcode);
	X	}
	X
	X	/*
	X	 * If there are no answer, n.s. or additional records 
	X	 * then return with an error.
	X	 */
	X	if (ancount == 0 && nscount == 0 && arcount == 0) {
	X	    return (NO_INFO);
	X	}
	X
	X
	X	bp 	= hostbuf;
	X	buflen 	= sizeof(hostbuf);
	X	cp 	= (char *) &answer + sizeof(HEADER);
	X
	X	/*
	X	 * For inverse queries, the desired information is returned
	X	 * in the question section. If there are no question records,
	X	 * return with an error.
	X	 *
	X	 */
	X	if (qdcount) {
	X	    if (iquery) {
	X		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) {
	X		    return (ERROR);
	X		}
	X		cp += n + QFIXEDSZ;
	X		len = strlen(bp) + 1;
	X		hostPtr->name = Calloc((unsigned)1, (unsigned)len);
	X#ifdef SYS5
	X		(void)memcpy(hostPtr->name, bp, len);
	X#else
	X		bcopy(bp, hostPtr->name, len);
	X#endif
	X	    } else {
	X		cp += dn_skipname(cp, eom) + QFIXEDSZ;
	X	    }
	X	    while (--qdcount > 0) {
	X		cp += dn_skipname(cp, eom) + QFIXEDSZ;
	X	    }
	X	} else if (iquery) {
	X	    return (NO_INFO);
	X	}
	X
	X	aliasPtr 	= host_aliases;
	X	addrPtr	 	= addr_list;
	X	haveanswer 	= 0;
	X
	X	/*
	X	 * Scan through the answer resource records.
	X	 * Answers for address query types are saved.
	X	 * Other query type answers are just printed.
	X	 */
	X	if (isserver == 0 && !headerPtr->aa && headerPtr->ancount)
	X	    printf("Non-authoritative answer:\n");
	X	while (--ancount >= 0 && cp < eom) {
	X	    if (queryType != T_A) {
	X		if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
	X		    return(ERROR);
	X		}
	X		continue;
	X	    } else {
	X		if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
	X		    return(ERROR);
	X		}
	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		dlen = _getshort(cp);
	X		cp += sizeof(u_short);
	X		if (type == T_CNAME) {
	X		    /*
	X		     * Found an alias.
	X		     */
	X		    cp += dlen;
	X		    if (aliasPtr >= &host_aliases[MAXALIASES-1])
	X			    continue;
	X		    *aliasPtr++ = bp;
	X		    n = strlen(bp) + 1;
	X		    host_aliases_len[numAliases] = n;
	X		    numAliases++;
	X		    bp += n;
	X		    buflen -= n;
	X		    continue;
	X		} else if (type == T_PTR) {
	X		    /*
	X		     *  Found a "pointer" to the real name.
	X		     */
	X		    if((n= dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0){
	X			cp += n;
	X			continue;
	X		    }
	X		    cp += n;
	X		    len = strlen(bp) + 1;
	X		    hostPtr->name = Calloc((unsigned)1, (unsigned)len);
	X#ifdef SYS5
	X		    (void)memcpy(hostPtr->name, bp, len);
	X#else
	X		    bcopy(bp, hostPtr->name, len);
	X#endif
	X		    haveanswer = 1;
	X		    break;
	X		} else if (type != T_A) {
	X		    cp += dlen;
	X		    continue;
	X		}
	X		if (haveanswer) {
	X		    if (n != hostPtr->addrLen) {
	X			cp += dlen;
	X			continue;
	X		    }
	X		    if (class != getclass) {
	X			cp += dlen;
	X			continue;
	X		    }
	X		} else {
	X		    hostPtr->addrLen = dlen;
	X		    getclass = class;
	X		    hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC;
	X		    if (!iquery) {
	X			len = strlen(bp) + 1;
	X			hostPtr->name = Calloc((unsigned)1, (unsigned)len);
	X#ifdef SYS5
	X			(void)memcpy(hostPtr->name, bp, len);
	X#else
	X			bcopy(bp, hostPtr->name, len);
	X#endif
	X		    }
	X		}
	X		bp += (((u_long)bp) % sizeof(align));
	X
	X		if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
	X			if (_res.options & RES_DEBUG)
	X				printf("Size (%d) too big\n", dlen);
	X			break;
	X		}
	X#ifdef SYS5
	X		(void)memcpy(*addrPtr++ = bp, cp, dlen);
	X#else
	X		bcopy(cp, *addrPtr++ = bp, dlen);
	X#endif
	X		bp +=dlen;
	X		cp += dlen;
	X		numAddresses++;
	X		haveanswer = 1;
	X	    }
	X	}
	X
	X	if (queryType == T_A && haveanswer) {
	X
	X	    /*
	X	     *  Go through the alias and address lists and return them
	X	     *  in the hostPtr variable.
	X	     */
	X
	X	    if (numAliases > 0) {
	X		hostPtr->aliases = (char **) Calloc((unsigned)1+numAliases, 
	X							sizeof(char *));
	X		for (i = 0; i < numAliases; i++) {
	X		    hostPtr->aliases[i] = Calloc((unsigned)1, (unsigned)host_aliases_len[i]);
	X#ifdef SYS5
	X		    (void)memcpy( hostPtr->aliases[i], host_aliases[i],
	X#else
	X		    bcopy(host_aliases[i], hostPtr->aliases[i],
	X#endif
	X			    host_aliases_len[i]);
	X		}
	X		hostPtr->aliases[i] = NULL;
	X	    }
	X	    if (numAddresses > 0) {
	X		hostPtr->addrList = (char **) Calloc((unsigned)1+numAddresses, 
	X							sizeof(char *));
	X		for (i = 0; i < numAddresses; i++) {
	X		    hostPtr->addrList[i] = Calloc((unsigned)1, (unsigned)hostPtr->addrLen);
	X#ifdef SYS5
	X		    (void)memcpy( hostPtr->addrList[i], addr_list[i],
	X#else
	X		    bcopy(addr_list[i], hostPtr->addrList[i], 
	X#endif
	X			    hostPtr->addrLen);
	X		}
	X		hostPtr->addrList[i] = NULL;
	X	    }
	X	    hostPtr->servers= NULL;
	X	    return (SUCCESS);
	X	}
	X
	X	/*
	X	 * At this point, for the T_A query type, only empty answers remain.
	X	 * For other query types, additional information might be found
	X	 * in the additional resource records part.
	X	 */
	X
	X	cp = res_skip((char *) &answer, 2, eom);
	X
	X	numServers = 0;
	X	while (--nscount >= 0 && cp < eom) {
	X	    /*
	X	     *  Go through the NS records and retrieve the
	X	     *  names of hosts that server the requested domain, 
	X	     *  their addresses and other domains they might serve.
	X	     */
	X
	X	  if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
	X	      return(ERROR);
	X	  }
	X	  cp += n;
	X	  len = strlen(bp) + 1;
	X	  dnamePtr = Calloc((unsigned)1, (unsigned)len);   /* domain name */
	X#ifdef SYS5
	X	  (void)memcpy(dnamePtr, bp, len);
	X#else
	X	  bcopy(bp, dnamePtr, len);
	X#endif
	X	  type = _getshort(cp);
	X	  cp += sizeof(u_short);
	X	  class = _getshort(cp);
	X	  cp += sizeof(u_short) + sizeof(u_long);
	X	  dlen = _getshort(cp);
	X	  cp += sizeof(u_short);
	X
	X	  if (type != T_NS) {
	X	      cp += dlen;
	X	  } else {
	X	    if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
	X	        return(ERROR);
	X	    }
	X	    cp += n;
	X	    len = strlen(bp) + 1;
	X	    namePtr = Calloc((unsigned)1, (unsigned)len); /* server host name */
	X#ifdef SYS5
	X	    (void)memcpy(namePtr, bp, len);
	X#else
	X	    bcopy(bp, namePtr, len);
	X#endif
	X	    /*
	X	     * Store the information keyed by the server host name.
	X	     */
	X	    found = FALSE;
	X	    for (j = 0; j < numServers; j++) {
	X		if (strcmp(namePtr, server[j].name) == 0) {
	X		    found = TRUE;
	X		    free(namePtr);
	X		    break;
	X		}
	X	    }
	X	    if (found) {
	X		server[j].numDomains++;
	X		if (server[j].numDomains <= MAXDOMAINS) {
	X		    server[j].domain[server[j].numDomains-1] = dnamePtr;
	X		}
	X	    } else {
	X		if (numServers > MAXSERVERS) {
	X		    break;
	X		}
	X		numServers++;
	X		server[numServers -1].name = namePtr;
	X		server[numServers -1].domain[0] = dnamePtr;
	X		server[numServers -1].numDomains = 1;
	X		server[numServers -1].numAddresses = 0;
	X	    }
	X	  }
	X	}
	X
	X	if (!headerPtr->aa && (queryType != T_A) && arcount > 0) {
	X	    printf("Authoritative answers can be found from:\n");
	X	}
	X
	X	/*
	X	 * Additional resource records contain addresses of
	X	 * servers.
	X	 */
	X	cp = res_skip((char *) &answer, 3, eom);
	X	while (--arcount >= 0 && cp < eom) {
	X	    /*
	X	     * If we don't need to save the record, just print it.
	X	     */
	X	    if (queryType != T_A) {
	X		if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
	X		    return(ERROR);
	X		}
	X		continue;
	X
	X	    } else {
	X	      if ((n = dn_expand((char *) &answer, 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	      dlen = _getshort(cp);
	X	      cp += sizeof(u_short);
	X
	X	      if (type != T_A)  {
	X		  cp += dlen;
	X		  continue;
	X	      } else {
	X		for (j = 0; j < numServers; j++) {
	X		  if (strcmp(bp, server[j].name) == 0) {
	X		    server[j].numAddresses++;
	X		    if (server[j].numAddresses <= MAXADDRS) {
	X		     server[j].address[server[j].numAddresses-1]=Calloc((unsigned)1,(unsigned)dlen);
	X#ifdef SYS5
	X		     (void)memcpy(server[j].address[server[j].numAddresses-1],
	X				cp, dlen);
	X#else
	X		     bcopy(cp,server[j].address[server[j].numAddresses-1],
	X				dlen);
	X#endif
	X		     break;
	X		    }
	X		  }
	X		}
	X		cp += dlen;
	X	      }
	X	    }
	X	}
	X
	X	/*
	X	 * If we are returning name server info, transfer it to
	X	 * the hostPtr.
	X	 *
	X	 */
	X	if (numServers > 0) {
	X	  hostPtr->servers = (ServerInfo **) Calloc((unsigned)numServers+1, 
	X					sizeof(ServerInfo *));
	X	  for (i = 0; i < numServers; i++) {
	X	    hostPtr->servers[i] = (ServerInfo *) Calloc((unsigned)1, sizeof(ServerInfo));
	X	    hostPtr->servers[i]->name = server[i].name;
	X
	X
	X	    hostPtr->servers[i]->domains = (char **)
	X				Calloc((unsigned)server[i].numDomains+1,sizeof(char *));
	X	    for (j = 0; j < server[i].numDomains; j++) {
	X	      hostPtr->servers[i]->domains[j] = server[i].domain[j];
	X	    }
	X	    hostPtr->servers[i]->domains[j] = NULL;
	X
	X
	X	    hostPtr->servers[i]->addrList = (char **)
	X				Calloc((unsigned)server[i].numAddresses+1,sizeof(char *));
	X	    for (j = 0; j < server[i].numAddresses; j++) {
	X	      hostPtr->servers[i]->addrList[j] = server[i].address[j];
	X	    }
	X	    hostPtr->servers[i]->addrList[j] = NULL;
	X
	X	  }
	X	  hostPtr->servers[i] = NULL;
	X	}
	X
	X
	X	if (queryType != T_A) {
	X	    return(SUCCESS);
	X	} else {
	X	    return(NONAUTH);
	X	}
	X}
	X
	X/*
	X *******************************************************************************
	X *
	X *  GetHostInfo --
	X *
	X *	Retrieves host name, address and alias information
	X *	for a domain.
	X *
	X *  Results:
	X *	ERROR		- res_mkquery failed.
	X *	+ return values from GetAnswer()
	X *
	X *******************************************************************************
	X */
	X
	Xint
	XGetHostInfo(nsAddrPtr, queryClass, queryType, name, hostPtr, isserver)
	X	struct in_addr *nsAddrPtr;
	X	int 		queryClass;
	X	int 		queryType;
	X	char 		*name;
	X	HostInfo 	*hostPtr;
	X	int		isserver;
	X{
	X	int 	 n;
	X	int 	 result;
	X	register char *cp, **domain;
	X	querybuf buf;
	X	extern char *Calloc(), *hostalias();
	X
	X	/* catch explicit addresses */
	X	if (isdigit(*name) && (queryType == T_A)) {
	X	    long ina;
	X
	X	    ina = inet_addr(name);
	X
	X	    if (ina == -1)
	X		return(ERROR);
	X
	X	    hostPtr->name = Calloc((unsigned)strlen(name)+3,1);
	X	    (void)sprintf(hostPtr->name,"[%s]",name);
	X	    hostPtr->aliases = 0;
	X	    hostPtr->servers = 0;
	X	    hostPtr->addrType = AF_INET;
	X	    hostPtr->addrLen = 4;
	X	    hostPtr->addrList = (char **)Calloc((unsigned)2,sizeof(char *));
	X	    hostPtr->addrList[0] = Calloc(sizeof(long),sizeof(char));
	X#ifdef SYS5
	X	    (void)memcpy(hostPtr->addrList[0],(char *)&ina,sizeof(ina));
	X#else
	X	    bcopy((char *)&ina,hostPtr->addrList[0],sizeof(ina));
	X#endif
	X	    hostPtr->addrList[1] = 0;
	X
	X	    return(SUCCESS);
	X	}
	X
	X	for (cp = name, n = 0; *cp; cp++)
	X		if (*cp == '.')
	X			n++;
	X	if ((n && *--cp == '.') ||
	X	    (isserver == 0 && (_res.options & RES_DEFNAMES) == 0)) {
	X		int defflag = _res.options & RES_DEFNAMES;
	X
	X		_res.options &= ~RES_DEFNAMES;
	X		if (n && *cp == '.')
	X			*cp = 0;
	X		result = GetHostDomain(nsAddrPtr, queryClass, queryType,
	X			name, (char *)NULL, hostPtr, isserver);
	X		if (n && *cp == 0)
	X			*cp = '.';
	X		if (defflag)
	X			_res.options |= RES_DEFNAMES;
	X		return (result);
	X	}
	X	if (n == 0 && (cp = hostalias(name)))
	X		return (GetHostDomain(nsAddrPtr, queryClass, queryType,
	X			cp, (char *)NULL, hostPtr, isserver));
	X	for (domain = _res.dnsrch; *domain; domain++) {
	X		result = GetHostDomain(nsAddrPtr, queryClass, queryType,
	X			name, *domain, hostPtr, isserver);
	X		if ((result != NXDOMAIN && result != NO_INFO) ||
	X		    (_res.options & RES_DNSRCH) == 0)
	X			return (result);
	X	}
	X	if (n)
	X		return (GetHostDomain(nsAddrPtr, queryClass, queryType,
	X			name, (char *)NULL, hostPtr, isserver));
	X	return (result);
	X}
	X
	XGetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isserver)
	X	struct in_addr *nsAddrPtr;
	X	int 		queryClass;
	X	int 		queryType;
	X	char 		*name, *domain;
	X	HostInfo 	*hostPtr;
	X	int		isserver;
	X{
	X	querybuf buf;
	X	char nbuf[2*MAXDNAME+2];
	X	int n;
	X
	X	if (domain) {
	X		(void)sprintf(nbuf, "%.*s.%.*s",
	X			MAXDNAME, name, MAXDNAME, domain);
	X		name = nbuf;
	X	}
	X	n = res_mkquery(QUERY, name, queryClass, queryType,
	X			(char *)0, 0, (char *)0, (char *) &buf, sizeof(buf));
	X	if (n < 0) {
	X	    if (_res.options & RES_DEBUG) {
	X		printf("Res_mkquery failed\n");
	X	    }
	X	    return (ERROR);
	X	}
	X
	X	n = GetAnswer(nsAddrPtr, queryType, (char *) &buf, n, 0, hostPtr,
	X	    isserver);
	X
	X	/*
	X	 * GetAnswer didn't find a name, so set it to the specified one.
	X	 */
	X	if (n == NONAUTH) {
	X	    if (hostPtr->name == NULL) {
	X		int len = strlen(name) + 1;
	X		hostPtr->name = Calloc((unsigned)len, sizeof(char));
	X#ifdef SYS5
	X		(void)memcpy(hostPtr->name, name, len);
	X#else
	X		bcopy(name, hostPtr->name, len);
	X#endif
	X
	X	    }
	X	}
	X	return(n);
	X}
	X
	X
	X/*
	X *******************************************************************************
	X *
	X *  FindHostInfo --
	X *
	X *	Performs an inverse query to find the host name
	X *	that corresponds to the given address.
	X *
	X *  Results:
	X *	ERROR		- res_mkquery failed.
	X *	+ return values from GetAnswer()
	X *
	X *******************************************************************************
	X */
	X
	Xint
	XFindHostInfo(nsAddrPtr, address, len, hostPtr)
	X	struct in_addr 	*nsAddrPtr;
	X	struct in_addr	*address;
	X	int 		len;
	X	HostInfo 	*hostPtr;
	X{
	X	int 	 n;
	X	querybuf buf;
	X
	X	n = res_mkquery(IQUERY, (char *)0, C_IN, T_A,
	X		(char *)address, len, (char *)0, (char *) &buf, sizeof(buf));
	X	if (n < 0) {
	X	    if (_res.options & RES_DEBUG) {
	X		printf("Res_mkquery failed\n");
	X	    }
	X	    return (ERROR);
	X	}
	X	return(GetAnswer(nsAddrPtr, T_A, (char *) &buf, n, 1, hostPtr, 1));
	X}
	X
	X/*
	X *******************************************************************************
	X *
	X *  FreeHostInfoPtr --
	X *
	X *	Deallocates all the calloc'd areas for a HostInfo
	X *	variable.
	X *
	X *******************************************************************************
	X */
	X
	Xvoid
	XFreeHostInfoPtr(hostPtr)
	X    HostInfo *hostPtr;
	X{
	X	int i, j;
	X
	X	if (hostPtr->name != NULL) {
	X	    free(hostPtr->name);
	X	    hostPtr->name = NULL;
	X	}
	X
	X	if (hostPtr->aliases != NULL) {
	X	    i = 0;
	X	    while (hostPtr->aliases[i] != NULL) {
	X		free(hostPtr->aliases[i]);
	X		i++;
	X	    }
	X	    free((char *)hostPtr->aliases);
	X	    hostPtr->aliases = NULL;
	X	}
	X
	X	if (hostPtr->addrList != NULL) {
	X	    i = 0;
	X	    while (hostPtr->addrList[i] != NULL) {
	X		free(hostPtr->addrList[i]);
	X		i++;
	X	    }
	X	    free((char *)hostPtr->addrList);
	X	    hostPtr->addrList = NULL;
	X	}
	X
	X	if (hostPtr->servers != NULL) {
	X	    i = 0;
	X	    while (hostPtr->servers[i] != NULL) {
	X
	X		if (hostPtr->servers[i]->name != NULL) {
	X		    free(hostPtr->servers[i]->name);
	X		}
	X
	X		if (hostPtr->servers[i]->domains != NULL) {
	X		    j = 0;
	X		    while (hostPtr->servers[i]->domains[j] != NULL) {
	X			free(hostPtr->servers[i]->domains[j]);
	X			j++;
	X		    }
	X		    free((char *)hostPtr->servers[i]->domains);
	X		}
	X
	X		if (hostPtr->servers[i]->addrList != NULL) {
	X		    j = 0;
	X		    while (hostPtr->servers[i]->addrList[j] != NULL) {
	X			free(hostPtr->servers[i]->addrList[j]);
	X			j++;
	X		    }
	X		    free((char *)hostPtr->servers[i]->addrList);
	X		}
	X		free((char *)hostPtr->servers[i]);
	X		i++;
	X	    }
	X	    free((char *)hostPtr->servers);
	X	    hostPtr->servers = NULL;
	X	}
	X}
	X
	X/*
	X *******************************************************************************
	X *
	X *  GetHostList --
	X *
	X *	Performs a completion query when given an incomplete
	X *	name.
	X *
	X *	Still under development.
	X *
	X *******************************************************************************
	X */
	X
	X#if  notdef
	X
	Xint
	XGetHostList(nsAddrPtr, queryType, name, defaultName, hostPtr)
	X	struct in_addr 	*nsAddrPtr;
	X	int 		queryType;
	X	char 		*name, *defaultName;
	X	HostInfo 	*hostPtr;
	X{
	X	int 	 n;
	X	querybuf buf;
	X
	X	n = res_mkquery(CQUERYM, name, C_IN, T_A, defaultName, 0, (char *)0,
	X		(char *) &buf, sizeof(buf));
	X	if (n < 0) {
	X		if (_res.options & RES_DEBUG)
	X			printf("Res_mkquery failed\n");
	X		return (ERROR);
	X	}
	X	return(GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, 1));
	X}
	X#endif  notdef
SHAR_EOF
if test 19262 -ne "`wc -c < 'getinfo.c'`"
then
	echo shar: "error transmitting 'getinfo.c'" '(should have been 19262 characters)'
fi
fi
exit 0
#	End of shell archive