home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-03 | 59.1 KB | 2,295 lines |
- Newsgroups: comp.sources.unix
- From: i3558@newsie.dc.dk (Soeren Michael Roug)
- Subject: v26i092: ns2tab - Increasing the usefullnes of the nameserver, Part01/03
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: i3558@newsie.dc.dk (Soeren Michael Roug)
- Posting-Number: Volume 26, Issue 92
- Archive-Name: ns2tab/part01
-
- Have you ever had one of the following needs?:
-
- - To coordinate /usr/lib/aliases with /etc/group.
- - To extract a /etc/hosts table from the nameserver.
- - To provide slightly different /etc/group files on different systems.
- - To provide slightly different /usr/lib/aliases on different systems.
- - To update the GECOS field in /etc/passwd on several computers at once.
- - To have a central point where you maintain NFS hardmounts. With all
- the different filesystem table formats out there that could not be done.
- - To provide different /etc/printcap files on different systems.
-
- Then this piece of software is for you!
-
- The principle is, as in Hesiod, to load the information in the BIND
- nameserver and then extract the information again in various styles.
-
- If you find it usefull, then send a short note to <smr@dc.dk>. You don't
- have to write that you like it, but I will use the responses to determine
- how many resources to use to bring out new [and improved] versions.
-
- Also, I would like to get suggestions for new types of tables, see also
- the TODO file.
-
- BTW. There is NO WARRANTY on this package of any kind, so don't come
- to me, if you have overwritten your filesystem table with an error message.
-
- March 22, 1993
- Sincerely,
-
- Soren Roug <smr@dc.dk>
- Datacentralen A/S
- Denmark
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 3)."
- # Contents: MANIFEST Makefile README TODO debug.c ns2tab.8 p_time.c
- # prime.c readv.c res.h send.c skip.c subr.c vtable.c vtable.h
- # Wrapped by i3558@ulrik.dc.dk on Fri Mar 26 15:05:32 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(828 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This file
- X Makefile 1
- X README 1
- X TODO 1 Ideas to improve this product
- X debug.c 1
- X getinfo.c 2
- X hash.c 2 Hash package
- X list.c 3
- X main.c 2
- X ns2tab.8 1 Man page
- X p_time.c 1
- X prime.c 1 Primes
- X readv.c 1 Emulation of readv(2) and writev(2)
- X res.h 1
- X send.c 1
- X skip.c 1
- X subr.c 1
- X vtable.c 1 Variable length tables
- X vtable.h 1 Variable length tables
- END_OF_FILE
- if test 828 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(982 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- XCFLAGS= -g -DBSD=43 -DSYSV -DEMULATE_HESIOD #SCO & SYSV4
- X#LIBS= $(RES) -lsocket #SCO
- X#RES= #SCO
- X#SUPS= readv.o #SCO
- XRES= -lresolv #SYSV4
- XLIBS= -L/usr/ucblib $(RES) -lsocket -lnsl -lucb #SYSV4
- XSUPS= #SYSV4 & BSD
- X#CFLAGS= -O -DBSD=43 -DEMULATE_HESIOD #BSD
- X#RES= #BSD
- X#LIBS= $(RES) #BSD
- X
- XSRCS= main.c getinfo.c debug.c send.c skip.c list.c subr.c \
- X hash.c prime.c vtable.c p_time.c readv.c
- XOBJS= main.o getinfo.o debug.o send.o skip.o list.o subr.o \
- X hash.o prime.o vtable.o p_time.o $(SUPS)
- XPROGRAM= ns2tab
- X
- Xall: $(PROGRAM)
- X
- X$(PROGRAM): $(OBJS)
- X $(CC) -o $@ $(OBJS) $(LIBS)
- X
- Xclean:
- X rm -f $(OBJS) core $(PROGRAM) ID
- X
- Xcleandir: clean
- X rm -f tags .depend
- X
- Xdepend: $(SRCS)
- X mkdep $(CFLAGS) $(SRCS)
- X
- Xinstall:
- X install -s -o bin -g bin -m 755 $(PROGRAM) $(DESTDIR)/usr/local/bin
- X# install -c -o bin -g bin -m 444 $(PROGRAM).8 \
- X# $(DESTDIR)/usr/local/man/man8
- X
- Xlint: $(SRCS)
- X lint $(SRCS)
- X
- Xtags: $(CSRCS)
- X ctags $(CSRCS)
- X
- Xmakekit: ;makekit -m
- END_OF_FILE
- if test 982 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(1350 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XThis is the README file for ns2tab version 1.0
- X
- XHave you ever had one of the following needs?:
- X
- X- To coordinate /usr/lib/aliases with /etc/group.
- X- To extract a /etc/hosts table from the nameserver.
- X- To provide slightly different /etc/group files on different systems.
- X- To provide slightly different /usr/lib/aliases on different systems.
- X- To update the GECOS field in /etc/passwd on several computers at once.
- X- To have a central point where you maintain NFS hardmounts. With all
- X the different filesystem table formats out there that could not be done.
- X- To provide different /etc/printcap files on different systems.
- X
- XThen this piece of software is for you!
- X
- XThe principle is, as in Hesiod, to load the information in the BIND
- Xnameserver and then extract the information again in various styles.
- X
- XIf you find it usefull, then send a short note to <smr@dc.dk>. You don't
- Xhave to write that you like it, but I will use the responses to determine
- Xhow many resources to use to bring out new [and improved] versions.
- X
- XAlso, I would like to get suggestions for new types of tables, see also
- Xthe TODO file.
- X
- XBTW. There is NO WARRANTY on this package of any kind, so don't come
- Xto me, if you have overwritten your filesystem table with an error message.
- X
- X March 22, 1993
- X Sincerely,
- X
- X Soren Roug <smr@dc.dk>
- X Datacentralen A/S
- X Denmark
- END_OF_FILE
- if test 1350 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'TODO' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'TODO'\"
- else
- echo shar: Extracting \"'TODO'\" \(417 characters\)
- sed "s/^X//" >'TODO' <<'END_OF_FILE'
- X- Full emulation of Hesiod.
- X
- X- Software that can use these tables and install them the correct place.
- X
- X- Examples of correct use.
- X
- X- An /etc/ethers extraction facility.
- X
- X- An automount map extraction facility for those automounters that doesn't
- X have NIS.
- X
- X- I need a little program that can get the serial number from a domain.
- X With this I can test for updates, and if nothing has changed, avoid
- X a costly XFER.
- END_OF_FILE
- if test 417 -ne `wc -c <'TODO'`; then
- echo shar: \"'TODO'\" unpacked with wrong size!
- fi
- # end of 'TODO'
- fi
- if test -f 'debug.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'debug.c'\"
- else
- echo shar: Extracting \"'debug.c'\" \(10002 characters\)
- sed "s/^X//" >'debug.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1985,1989 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted provided
- X * that: (1) source distributions retain this entire copyright notice and
- X * comment, and (2) distributions including binaries display the following
- X * acknowledgement: ``This product includes software developed by the
- X * University of California, Berkeley and its contributors'' in the
- X * documentation or other materials provided with the distribution and in
- X * all advertising materials mentioning features or use of this software.
- X * Neither the name of the University nor the names of its contributors may
- X * be used to endorse or promote products derived from this software without
- X * specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)debug.c 5.22 (Berkeley) 6/29/90";
- 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.30 6/27/90
- X *
- X *******************************************************************************
- X */
- X
- X#include <sys/types.h>
- X#include <netinet/in.h>
- X#include <stdio.h>
- X#include <arpa/nameser.h>
- X#include <arpa/inet.h>
- X#include <resolv.h>
- X#include <netdb.h>
- X#include "res.h"
- X
- X#ifndef __STDC__
- Xextern char ctime();
- X#endif
- 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 qclass;
- 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,", authority 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 qclass = _getshort(cp);
- X cp += sizeof(u_short);
- X fprintf(file,", type = %s", p_type(type));
- X fprintf(file,", class = %s\n", p_class(qclass));
- 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
- 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, qclass, dlen, n, c;
- X unsigned long rrttl, ttl;
- X struct in_addr inaddr;
- X char *cp1, *cp2;
- X int debug;
- 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 qclass = _getshort(cp);
- X cp += sizeof(u_short);
- X rrttl = _getlong(cp);
- X cp += sizeof(u_long);
- X dlen = _getshort(cp);
- X cp += sizeof(u_short);
- X
- X debug = _res.options & (RES_DEBUG|RES_DEBUG2);
- X if (debug) {
- X if (_res.options & RES_DEBUG2) {
- X fprintf(file,"\n\ttype = %s, class = %s, dlen = %d",
- X p_type(type), p_class(qclass), dlen);
- X }
- X if (type == T_SOA) {
- X fprintf(file,"\n\tttl = %lu (%s)", rrttl, P_time(rrttl));
- X }
- X (void) putc('\n', file);
- X }
- X
- X cp1 = cp;
- X
- X /*
- X * Print type specific data, if appropriate
- X */
- X switch (type) {
- X case T_A:
- X switch (qclass) {
- 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 fprintf(file,"\taddress, class = %d, len = %d\n",
- X qclass, dlen);
- X cp += dlen;
- X }
- X break;
- X
- X case T_CNAME:
- X fprintf(file,"\tcanonical name = ");
- 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_MX:
- X fprintf(file,"\tpreference = %u",_getshort(cp));
- X cp += sizeof(u_short);
- X fprintf(file,", mail exchanger = ");
- X goto doname;
- X case T_NS:
- X fprintf(file,"\tnameserver = ");
- X goto doname;
- X case T_PTR:
- X fprintf(file,"\tname = ");
- Xdoname:
- X cp = Print_cdname(cp, msg, eom, file);
- X (void) putc('\n', file);
- 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 if (!debug)
- X (void) putc('\n', file);
- 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 = %lu", _getlong(cp));
- X cp += sizeof(u_long);
- X ttl = _getlong(cp);
- X fprintf(file,"\n\trefresh = %lu (%s)", ttl, P_time(ttl));
- X cp += sizeof(u_long);
- X ttl = _getlong(cp);
- X fprintf(file,"\n\tretry = %lu (%s)", ttl, P_time(ttl));
- X cp += sizeof(u_long);
- X ttl = _getlong(cp);
- X fprintf(file,"\n\texpire = %lu (%s)", ttl, P_time(ttl));
- X cp += sizeof(u_long);
- X ttl = _getlong(cp);
- X fprintf(file,"\n\tminimum ttl = %lu (%s)\n", ttl, P_time(ttl));
- X cp += sizeof(u_long);
- X break;
- X
- X case T_MINFO:
- X if (!debug)
- X (void) putc('\n', file);
- 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 (void) putc('\n', file);
- X break;
- X
- X case T_UINFO:
- X fprintf(file,"\tuser info = %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 = %lu\n",type == T_UID ? 'u' : 'g',
- X _getlong(cp));
- X cp += sizeof(int);
- X } else {
- X fprintf(file,"\t%cid of length %d?\n",
- X type == T_UID ? 'u' : 'g', dlen);
- X cp += dlen;
- X }
- X break;
- X
- X case T_WKS: {
- X struct protoent *protoPtr;
- X
- X if (dlen < sizeof(u_long) + 1)
- X break;
- X if (!debug)
- X (void) putc('\n', file);
- X bcopy(cp, (char *)&inaddr, sizeof(inaddr));
- X cp += sizeof(u_long);
- X if ((protoPtr = getprotobynumber(*cp)) != NULL) {
- X fprintf(file,"\tinet address = %s, protocol = %s\n\t",
- X inet_ntoa(inaddr), protoPtr->p_name);
- X } else {
- X fprintf(file,"\tinet address = %s, protocol = %d\n\t",
- X inet_ntoa(inaddr), *cp);
- X }
- X cp++;
- X n = 0;
- X while (cp < cp1 + dlen) {
- X c = *cp++;
- X do {
- X struct servent *s;
- X
- X if (c & 0200) {
- X s = getservbyport(n, NULL);
- X if (s != NULL) {
- X fprintf(file," %s", s->s_name);
- X } else {
- X fprintf(file," #%d", n);
- X }
- X }
- X c <<= 1;
- X } while (++n & 07);
- X }
- X putc('\n',file);
- X }
- X break;
- X
- X case T_NULL:
- X fprintf(file, "\tNULL (dlen %d)\n", dlen);
- X cp += dlen;
- X break;
- X
- X default:
- X fprintf(file,"\t??? unknown type %d ???\n", type);
- X cp += dlen;
- X }
- X if (_res.options & RES_DEBUG && type != T_SOA) {
- X fprintf(file,"\tttl = %lu (%s)\n", rrttl, P_time(rrttl));
- X }
- X if (cp != cp1 + dlen) {
- X fprintf(file,
- X "\n*** Error: record size incorrect (%d != %d)\n\n",
- X cp - cp1, dlen);
- X cp = NULL;
- X }
- X return (cp);
- X}
- END_OF_FILE
- if test 10002 -ne `wc -c <'debug.c'`; then
- echo shar: \"'debug.c'\" unpacked with wrong size!
- fi
- # end of 'debug.c'
- fi
- if test -f 'ns2tab.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ns2tab.8'\"
- else
- echo shar: Extracting \"'ns2tab.8'\" \(6917 characters\)
- sed "s/^X//" >'ns2tab.8' <<'END_OF_FILE'
- X.TH NS2ALIASES 8 "April 4, 1992"
- X.UC 6
- X.SH NAME
- Xns2tab \- Extract a sendmail aliases table from the nameserver
- X.SH SYNOPSIS
- X.B ns2tab
- X[
- X.I option ...
- X]
- X.SH DESCRIPTION
- X.I Ns2tab
- Xis a program to query Internet domain name servers and print the
- Xinformation retrieved in different formats. Supported formats include
- Xaliases(5) for sendmail, /etc/group, /etc/passwd, /etc/hosts and
- Xaliases.text for the Elm mailer.
- X.sp 1
- X.SH ARGUMENTS
- XIf given no arguments, \fIns2tab\fP will query the domain found in
- X/etc/resolv.conf and print on stdout an aliases-table.
- XBehaviour can be modified by the \fBstyle\fP=XX argument, where XX is
- Xone of:
- X.IP aliases
- XOutput is in /usr/lib/aliases format, which also is compatiple
- Xwith an mh-alias file. Information is gathered from MB, MR, MINFO, MG
- Xand UINFO resource records. Maillists with no members are ignored.
- X.IP elm
- XThis is a slightly different way of representing the same information
- Xfor elm.
- XThis style will only be used if you don't intend to have have an
- X/usr/lib/aliases or equivalent.
- X.IP lelm
- XKnown as local elm, because it make elm expect that the recipients will
- Xbe expanded into real adresslists by the mail agent. In short, if you use
- Xthis, then you must also generate an /usr/lib/aliases file (if you use
- Xsendmail).
- X.IP group
- XOutputs maillists in group format.
- XIf any members are groups (They have a MINFO record) they will be expanded
- Xunless there is a UID. This will be done recursively. Beware that this
- Xopens an alley to loop referencing.
- XInformation is gathered from MINFO, MG, GID and UINFO resource records.
- X.IP nrgroup
- XNonrecursive group format.
- X.IP pwupd
- XRuns through the passwd table using getpwent(3), looks up each name
- Xin the nameserver, and outputs the account-line with the GECOS field
- Xreplaced with the value of the UINFO resource record.
- X.IP hosts
- XAs you would expect: /usr/hosts. To avoid excessive long lines host-aliases
- Xare not domain-expanded.
- XInformation is gathered from A, CNAME and HINFO records.
- X.LP
- XThe next set of styles are only relevant if you have linked in Hesiod
- Xemulation. The intent is to allow you to use Hesiod, even though not all
- Xof your computers support it. The query class does not have to HS, but
- Xcan be anything supported by your nameserver. This way you can get
- XHesiod functionality even if none of your computers support it.
- XNote that \fIns2tab\fP defaults to query the IN class.
- X.IP fstab
- X.I Ns2tab
- Xwill prepend \fBfilsys\fP to your current domain, look for TXT records
- Xand print in /etc/fstab style as in Ultrix 4.x and BSD4.2.
- X.IP checklist
- XSame, but output is in /etc/checklist format as used on HP/UX and others:
- X.IP filesys
- XSCO Unix V.3.2 /etc/default/filesys format.
- X.IP vfstab
- XUNIX V.4 /etc/vfstab format.
- X.IP passwd
- X.I Ns2tab
- Xprepends \fBpasswd\fP and outputs password file entries.
- X.IP printcap
- XOutput is in /etc/printcap format.
- X.LP
- X.B server=\fIserver\fP
- Xwill set the server to query. If not used \fIns2tab\fP will default
- Xto a value found in /etc/resolv.conf
- XRemember to query an autoritative server, otherwise you get no output.
- X.LP
- X.B out=\fIfilename\fP
- XOpens a file where all output will go.
- X.LP
- X.B domain=\fIdomain\fP
- XThe domain to query. If specified more than once \fIns2tab\fP will
- Xload the additional domains into the same internal tables, overwriting
- Xif there is any redundant data. This feature allow you to have special
- Xversions of the same file for a single or a cluster of computers.
- XConsider: ns2tab domain=dc.dk load domain=cluster1.dc.dk style=group
- X.LP
- X.B class=\fI{IN,CHAOS,HS,ANY}\fP
- XSets the query class. \fINs2tab\fP assume IN semantics for all
- Xressource records no matter what class you use.
- X.LP
- X.B suffix=\fIdomain\fP
- XUse this argument if the domain to query is subjugated a higher level
- Xdomain. (meaning: it doesn't have its own SOA).
- X.LP
- X.B load
- XExplicitly load the resource records.
- X.I Ns2tab
- Xwill do it automatically if when it is time to print.
- X.B print
- XPrint in the style previously set.
- XIt will allow you to print several styles in the same run.
- X.SH EXAMPLES
- XGiven the following nameserver records, the format for each style is
- Xshown below.
- X.RS .5i
- X.nf
- Xbob MR robert
- Xrnews MR "|/usr/local/bin/uurec"
- Xrobert MB hostx
- X UINFO "Robert Robespierre,MH-2323,3998"
- X
- Xwheel MINFO wagner root
- X GID 0
- X UINFO "Root task force"
- X MG robert
- X MG james
- X
- Xdyer.filsys IN TXT "NFS /mit/dyer eurydice w /mit/dyer"
- X
- X\fBAliases format:\fP
- Xbob: robert
- Xrnews: "|/usr/local/bin/uurec"
- X# robert +- Robert Robespierre,MH-2323,3998
- Xrobert: robert@hostx
- X# Root task force
- Xwheel-request: wagner
- Xowner-wheel: root
- Xwheel: robert,james
- X.sp 1
- X\fBelm format:\fP
- Xbob = = robert
- Xrnews = = "|/usr/local/bin/uurec"
- Xrobert = Robert Robespierre,MH-2323,3998 = robert@hostx
- Xwheel-request = wheel Request = wagner
- Xowner-wheel = wheel Errors = root
- Xwheel = Root task force = robert, james
- X.sp 1
- X\fBgroup format:\fP
- Xwheel:*:0:robert,james
- X.sp 1
- X\fBfstab format:\fP
- X/mit/dyer@eurydice:/mit/dyer:rw:0:0:nfs:hard,intr:
- X.sp 1
- X- and if robert has a \fBpasswd\fP entry like:
- Xrobert:Idh.wiU8oiJww:3028:1:Robert Robespierre,MH-4572,3652:/u/robert:
- Xit will become:
- Xrobert:Idh.wiU8oiJww:3028:1:Robert Robespierre,MH-2323,3998:/u/robert:
- X.fi
- X.RE
- X.sp 1
- XTry: ns2tab server=dc.dk dom=dc.dk out=/tmp/aliases style=aliases
- Xout=/tmp/elm style=elm
- X.SH DIAGNOSTICS
- XIf the lookup request was not successful, an error message is printed.
- XPossible errors are:
- X.IP "Timed out" 5
- XThe server did not respond to a request after a certain amount of
- Xtime (changed with \fBtimeout=\fIvalue\fR)
- Xand a certain number of retries (changed with \fBretry=\fIvalue\fR).
- X.IP "No response from server" 5
- XNo name server is running on the server machine.
- X.IP "No records" 5
- XThe server does not have resource records of the current query type for the
- Xhost, although the host name is valid.
- XThe query type is specified with the \fBquerytype\fP command.
- X.IP "Non-existent domain" 5
- XThe host or domain name does not exist.
- X.IP "Connection refused" 5
- X.ns
- X.IP "Network is unreachable" 5
- XThe connection to the name server could not be made
- Xat the current time.
- X.IP "Server failure" 5
- XThe name server found an internal inconsistency in its database
- Xand could not return a valid answer.
- X.IP "Refused" 5
- XThe name server refused to service the request.
- X.IP "Format error" 5
- XThe name server found that the request packet was not in the proper format.
- XIt may indicate an error in \fIns2tab\fP.
- X.sp 1
- X.SH FILES
- X.ta \w'/etc/resolv.confXXX'u
- X/etc/resolv.conf initial domain name and
- X name server addresses.
- X.SH ENVIRONMENT
- X.ta \w'LOCALDOMAINXXXX'u
- XLOCALDOMAIN overrides default domain.
- X.SH BUGS
- XI'm sure I left some in.. but I've forgotten where..
- X.SH SEE ALSO
- Xresolver(3), resolver(5), named(8), nslookup(8),
- X.br
- XRFC-1034 ``Domain Names \- Concepts and Facilities''
- X.br
- XRFC-1035 ``Domain Names \- Implementation and Specification''
- X.br
- X``The \fIHesiod\fP Name Server'' by Stephen P. Dryer
- X.SH AUTHOR
- XSoren Roug, based on the nslookup program developed by
- XAndrew Cherenson
- END_OF_FILE
- if test 6917 -ne `wc -c <'ns2tab.8'`; then
- echo shar: \"'ns2tab.8'\" unpacked with wrong size!
- fi
- # end of 'ns2tab.8'
- fi
- if test -f 'p_time.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'p_time.c'\"
- else
- echo shar: Extracting \"'p_time.c'\" \(982 characters\)
- sed "s/^X//" >'p_time.c' <<'END_OF_FILE'
- X#include <sys/types.h>
- X#include <netinet/in.h>
- X#include <stdio.h>
- X#include <arpa/nameser.h>
- X#include <arpa/inet.h>
- X#include <resolv.h>
- X
- Xstatic char nbuf[40];
- X/*
- X * Return a mnemonic for a time to live
- X */
- Xchar *
- XP_time(value)
- X u_long value;
- X{
- X int secs, mins, hours;
- X register char *p;
- X
- X if (value == 0) {
- X strcpy(nbuf, "0 secs");
- X return(nbuf);
- X }
- X
- X secs = value % 60;
- X value /= 60;
- X mins = value % 60;
- X value /= 60;
- X hours = value % 24;
- X value /= 24;
- X
- X#define PLURALIZE(x) x, (x == 1) ? "" : "s"
- X p = nbuf;
- X if (value) {
- X (void)sprintf(p, "%d day%s", PLURALIZE(value));
- X while (*++p);
- X }
- X if (hours) {
- X if (value)
- X *p++ = ' ';
- X (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
- X while (*++p);
- X }
- X if (mins) {
- X if (value || hours)
- X *p++ = ' ';
- X (void)sprintf(p, "%d min%s", PLURALIZE(mins));
- X while (*++p);
- X }
- X if (secs || ! (value || hours || mins)) {
- X if (value || hours || mins)
- X *p++ = ' ';
- X (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
- X }
- X return(nbuf);
- X}
- END_OF_FILE
- if test 982 -ne `wc -c <'p_time.c'`; then
- echo shar: \"'p_time.c'\" unpacked with wrong size!
- fi
- # end of 'p_time.c'
- fi
- if test -f 'prime.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'prime.c'\"
- else
- echo shar: Extracting \"'prime.c'\" \(1560 characters\)
- sed "s/^X//" >'prime.c' <<'END_OF_FILE'
- X/*
- X**
- X** Copyright (c) 1987, Robert L. McQueer
- X** All Rights Reserved
- X**
- X** Permission granted for use, modification and redistribution of this
- X** software provided that no use is made for commercial gain without the
- X** written consent of the author, that all copyright notices remain intact,
- X** and that all changes are clearly documented. No warranty of any kind
- X** concerning any use which may be made of this software is offered or implied.
- X**
- X*/
- X
- X/* return smallest prime >= i */
- Xint
- Xnext_prime(int i)
- X{
- X if (i <= 2)
- X return (2);
- X if ((i%2) == 0)
- X ++i;
- X while (! is_prime(i))
- X i += 2;
- X return (i);
- X}
- X
- X/*
- X** simply check all factors <= the square root of the number, with
- X** a minor wrinkle:
- X**
- X** we split our checks into two separate chains which cover all
- X** numbers with no factors of 2 or 3, avoiding many of the non-
- X** prime factors. factor1 winds up being all integers = 5 mod 6,
- X** factor2 all integers >= 7 which = 1 mod 6. Anything = 0,2,3 or
- X** 4 mod 6 divides by 2 or 3.
- X**
- X** this gives a rather small number of redundant factor checks for
- X** reasonable sized arguments (say < 10000). Only for extremely large
- X** numbers would the extra overhead justify a "smarter" algorithm.
- X**
- X** only valid for i >= 2.
- X*/
- Xint
- Xis_prime(int i)
- X{
- X int factor1,factor2;
- X
- X if (i == 2 || i == 3)
- X return(1);
- X
- X if ((i%3) == 0 || (i%2) == 0)
- X return(0);
- X
- X factor1 = 5;
- X factor2 = 7;
- X while ((factor1 * factor1) <= i)
- X {
- X if ((i % factor1) == 0)
- X return (0);
- X if ((i % factor2) == 0)
- X return (0);
- X factor1 += 6;
- X factor2 += 6;
- X }
- X
- X return (1);
- X}
- END_OF_FILE
- if test 1560 -ne `wc -c <'prime.c'`; then
- echo shar: \"'prime.c'\" unpacked with wrong size!
- fi
- # end of 'prime.c'
- fi
- if test -f 'readv.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'readv.c'\"
- else
- echo shar: Extracting \"'readv.c'\" \(1130 characters\)
- sed "s/^X//" >'readv.c' <<'END_OF_FILE'
- X#include <sys/types.h>
- X#include <sys/uio.h>
- X#include <errno.h>
- X
- Xint readv(fd, iov, iovcnt)
- X int fd;
- X struct iovec *iov;
- X int iovcnt;
- X{
- X int i,len, total;
- X char *base;
- X
- X errno = 0;
- X for (i=0,total=0; i<iovcnt; i++,iov++) {
- X len = iov->iov_len;
- X base = iov->iov_base;
- X while (len > 0) {
- X register int nbytes;
- X nbytes = read(fd, base, len);
- X if (nbytes < 0 && total == 0) {
- X return(-1);
- X }
- X if (nbytes <= 0) {
- X return(total);
- X }
- X errno = 0;
- X len -= nbytes;
- X total += nbytes;
- X base += nbytes;
- X }
- X }
- X return(total);
- X}
- X
- Xint
- Xwritev(fd,iov,iovcnt)
- X int fd;
- X struct iovec *iov;
- X int iovcnt;
- X{
- X int i,len,total;
- X char *base;
- X
- X errno = 0;
- X for (i=0,total=0; i<iovcnt; i++, iov++) {
- X len = iov->iov_len;
- X base = iov->iov_base;
- X while (len > 0) {
- X register int nbytes;
- X nbytes = write(fd, base, len);
- X if (nbytes < 0 && total == 0) {
- X return(-1);
- X }
- X if (nbytes <= 0) {
- X return(total);
- X }
- X
- X errno = 0;
- X len -= nbytes;
- X total += nbytes;
- X base += nbytes;
- X }
- X }
- X return(total);
- X}
- END_OF_FILE
- if test 1130 -ne `wc -c <'readv.c'`; then
- echo shar: \"'readv.c'\" unpacked with wrong size!
- fi
- # end of 'readv.c'
- fi
- if test -f 'res.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'res.h'\"
- else
- echo shar: Extracting \"'res.h'\" \(2625 characters\)
- sed "s/^X//" >'res.h' <<'END_OF_FILE'
- X/*
- X *******************************************************************************
- X *
- X * res.h --
- X *
- X * Definitions used by modules of the name server lookup program.
- X *
- X * Copyright (c) 1985
- X * Andrew Cherenson
- X * U.C. Berkeley
- X * CS298-26 Fall 1985
- X *
- X *******************************************************************************
- X */
- X
- X#define TRUE 1
- X#define FALSE 0
- Xtypedef int Boolean;
- X
- X/*
- X * Define return statuses in addtion to the ones defined in namserv.h
- X * let SUCCESS be a synonym for NOERROR
- X *
- X * TIME_OUT - a socket connection timed out.
- X * NO_INFO - the server didn't find any info about the host.
- X * ERROR - one of the following types of errors:
- X * dn_expand, res_mkquery failed
- X * bad command line, socket operation failed, etc.
- X * NONAUTH - the server didn't have the desired info but
- X * returned the name(s) of some servers who should.
- X * NO_RESPONSE - the server didn't respond.
- X *
- X */
- X
- X#define SUCCESS 0
- X#define TIME_OUT -1
- X#define NO_INFO -2
- X#define ERROR -3
- X#define NONAUTH -4
- X#define NO_RESPONSE -5
- X
- X/*
- X * Define additional options for the resolver state structure.
- X *
- X * RES_DEBUG2 more verbose debug level
- X */
- X
- X#define RES_DEBUG2 0x80000000
- X
- X/*
- X * Maximum length of server, host and file names.
- X */
- X
- X#define NAME_LEN 256
- X
- X
- X/*
- X * Modified struct hostent from <netdb.h>
- X *
- X * "Structures returned by network data base library. All addresses
- X * are supplied in host order, and returned in network order (suitable
- X * for use in system calls)."
- X */
- X
- Xtypedef struct {
- X char *name; /* official name of host */
- X char **domains; /* domains it serves */
- X char **addrList; /* list of addresses from name server */
- X} ServerInfo;
- X
- Xtypedef struct {
- X char *name; /* official name of host */
- X char **aliases; /* alias list */
- X char **addrList; /* list of addresses from name server */
- X int addrType; /* host address type */
- X int addrLen; /* length of address */
- X ServerInfo **servers;
- X} HostInfo;
- X
- X
- X/*
- X * FilePtr is used for directing listings to a file.
- X * It is global so the Control-C handler can close it.
- X */
- X
- Xextern FILE *filePtr;
- X
- X/*
- X * TCP/UDP port of server.
- X */
- Xextern unsigned short nsport;
- X
- X/*
- X * External routines:
- X */
- X
- Xextern Boolean IsAddr();
- Xextern int Print_query();
- Xextern char *Print_cdname();
- Xextern char *Print_cdname2(); /* fixed width */
- Xextern char *Print_rr();
- Xextern char *DecodeType(); /* descriptive version of p_type */
- Xextern char *DecodeError();
- Xextern void NsError();
- Xextern void PrintServer();
- Xextern void PrintHostInfo();
- Xextern void ShowOptions();
- Xextern void FreeHostInfoPtr();
- Xextern FILE *OpenFile();
- Xextern char *res_skip();
- END_OF_FILE
- if test 2625 -ne `wc -c <'res.h'`; then
- echo shar: \"'res.h'\" unpacked with wrong size!
- fi
- # end of 'res.h'
- fi
- if test -f 'send.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'send.c'\"
- else
- echo shar: Extracting \"'send.c'\" \(8182 characters\)
- sed "s/^X//" >'send.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1985, 1989 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted provided
- X * that: (1) source distributions retain this entire copyright notice and
- X * comment, and (2) distributions including binaries display the following
- X * acknowledgement: ``This product includes software developed by the
- X * University of California, Berkeley and its contributors'' in the
- X * documentation or other materials provided with the distribution and in
- X * all advertising materials mentioning features or use of this software.
- X * Neither the name of the University nor the names of its contributors may
- X * be used to endorse or promote products derived from this software without
- X * specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)send.c 5.17 (Berkeley) 6/29/90";
- X#endif /* not lint */
- X
- X/*
- X *******************************************************************************
- X *
- X * send.c --
- X *
- X * Routine to send request packets to a name server.
- X *
- X * Based on "@(#)res_send.c 6.25 (Berkeley) 6/1/90".
- X *
- X *******************************************************************************
- X */
- X
- X
- X/*
- X * Send query to name server and wait for reply.
- X */
- X
- X#include <sys/types.h>
- 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 <arpa/inet.h>
- X#include <resolv.h>
- X#include "res.h"
- X
- X#ifdef ultrix
- X#define nsaddr_list(i) ns_list[(i)].addr
- X#else
- X#define nsaddr_list(i) nsaddr_list[(i)]
- X#endif
- X
- Xextern int errno;
- X
- Xstatic int s = -1; /* socket used for communications */
- 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 SR 1 /* SendRequest style */
- X
- X#ifndef DEBUG
- X#define DEBUG
- X#endif
- X
- Xunsigned short nsport = NAMESERVER_PORT;
- X
- X
- X
- X/*
- X *******************************************************************************
- X *
- X * SendRequest --
- X *
- X * Sends a request packet to a name server whose address
- X * is specified by the first argument and returns with
- X * the answer packet.
- X *
- X * Results:
- X * SUCCESS - the request was sent and an answer
- X * was received.
- X * TIME_OUT - the virtual circuit connection timed-out
- X * or a reply to a datagram wasn't received.
- X *
- X *
- X *******************************************************************************
- X */
- X
- Xint
- XSendRequest(nsAddrPtr, buf, buflen, answer, anslen, trueLenPtr)
- X struct in_addr *nsAddrPtr;
- X char *buf;
- X int buflen;
- X char *answer;
- X u_int anslen;
- X int *trueLenPtr;
- X{
- X register int n;
- X int try, resplen, ns;
- X int gotsomewhere = 0, connected = 0;
- X int connreset = 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#if SR
- X struct sockaddr_in sin;
- X
- X if (_res.options & RES_DEBUG2) {
- X printf("------------\nSendRequest(), len %d\n", buflen);
- X Print_query(buf, buf+buflen, 1);
- X }
- X sin.sin_family = AF_INET;
- X sin.sin_port = htons(nsport);
- X sin.sin_addr = *nsAddrPtr;
- X#else
- X#ifdef DEBUG
- X if (_res.options & RES_DEBUG) {
- X printf("res_send()\n");
- X p_query(buf);
- X }
- X#endif
- X if (!(_res.options & RES_INIT))
- X if (res_init() == -1) {
- X return(-1);
- X }
- X#endif /* SR */
- X id = hp->id;
- X /*
- X * Send request, RETRY times, or until successful
- X */
- X for (try = 0; try < _res.retry; try++) {
- X#if !SR
- 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
- X#endif /* !SR */
- X usevc:
- X {
- X int truncated = 0;
- X
- X /*
- X * Use virtual circuit;
- X * at most one attempt per server.
- X */
- X try = _res.retry;
- 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 (vc) failed");
- X#endif
- X continue;
- X }
- X#if SR
- X if (connect(s, &sin,
- X#else
- X if (connect(s, &(_res.nsaddr_list(ns)),
- X#endif
- X sizeof(struct sockaddr)) < 0) {
- X terrno = errno;
- X#ifdef DEBUG
- X if (_res.options & RES_DEBUG)
- X perror("connect failed");
- X#endif
- 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
- 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
- X (void) close(s);
- X s = -1;
- X /*
- X * A long running process might get its TCP
- X * connection reset if the remote server was
- X * restarted. Requery the server instead of
- X * trying a new one. When there is only one
- X * server, this means that a query might work
- X * instead of failing. We only allow one reset
- X * per query to prevent looping.
- X */
- X if (terrno == ECONNRESET && !connreset) {
- X connreset = 1;
- X ns--;
- X }
- 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
- 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
- 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 }
- X#if SR
- X if (_res.options & RES_DEBUG) {
- X if (_res.options & RES_DEBUG2)
- X printf("------------\nGot answer (%d bytes):\n",
- X resplen);
- X else
- X printf("------------\nGot answer:\n");
- X Print_query(answer, answer+resplen, 1);
- X }
- X (void) close(s);
- X s = -1;
- X *trueLenPtr = resplen;
- X return (SUCCESS);
- X#else
- X#ifdef DEBUG
- X if (_res.options & RES_DEBUG) {
- X printf("got answer:\n");
- X p_query(answer);
- X }
- X#endif
- X /*
- X * If using virtual circuits, we assume that the first server
- X * is preferred * over the rest (i.e. it is on the local
- X * machine) and only keep that one open.
- X * If we have temporarily opened a virtual circuit,
- X * or if we haven't been asked to keep a socket open,
- X * close the socket.
- X */
- X if ( ((_res.options & RES_USEVC) == 0 || ns != 0) ||
- X (_res.options & RES_STAYOPEN) == 0) {
- X (void) close(s);
- X s = -1;
- X }
- X return (resplen);
- X }
- X#endif /* SR */
- X }
- X if (s >= 0) {
- X (void) close(s);
- X s = -1;
- X }
- X#if SR
- X if (errno == ECONNREFUSED)
- X return NO_RESPONSE;
- X else
- X return ERROR;
- X#else
- X errno = terrno;
- X return (-1);
- X#endif
- 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.
- X *
- X * Called from the interrupt handler.
- X */
- XSendRequest_close()
- X{
- X if (s != -1) {
- X (void) close(s);
- X s = -1;
- X }
- X}
- END_OF_FILE
- if test 8182 -ne `wc -c <'send.c'`; then
- echo shar: \"'send.c'\" unpacked with wrong size!
- fi
- # end of 'send.c'
- fi
- if test -f 'skip.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'skip.c'\"
- else
- echo shar: Extracting \"'skip.c'\" \(4295 characters\)
- sed "s/^X//" >'skip.c' <<'END_OF_FILE'
- 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 provided
- X * that: (1) source distributions retain this entire copyright notice and
- X * comment, and (2) distributions including binaries display the following
- X * acknowledgement: ``This product includes software developed by the
- X * University of California, Berkeley and its contributors'' in the
- X * documentation or other materials provided with the distribution and in
- X * all advertising materials mentioning features or use of this software.
- X * Neither the name of the University nor the names of its contributors may
- X * be used to endorse or promote products derived from this software without
- X * specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)skip.c 5.9 (Berkeley) 8/3/90";
- X#endif /* not lint */
- X
- X/*
- X *******************************************************************************
- X *
- X * skip.c --
- X *
- X * Routines to skip over portions of a query buffer.
- X *
- X * Note: this file has been submitted for inclusion in
- X * BIND resolver library. When this has been done, this file
- X * is no longer necessary (assuming there haven't been any
- X * changes).
- X *
- X * Adapted from 4.3BSD BIND res_debug.c
- X *
- X *******************************************************************************
- X */
- X
- X#include <sys/types.h>
- X#include <netinet/in.h>
- X#include <stdio.h>
- X#include <arpa/nameser.h>
- X
- Xchar *res_skip_rr();
- X
- X
- X/*
- X *******************************************************************************
- X *
- X * res_skip --
- X *
- X * Skip the contents of a query.
- X *
- X * Interpretation of numFieldsToSkip argument:
- X * res_skip returns pointer to:
- X * 1 -> start of question records.
- X * 2 -> start of authoritative answer records.
- X * 3 -> start of additional records.
- X * 4 -> first byte after end of additional records.
- X *
- X * Results:
- X * (address) - success operation.
- X * NULL - a resource record had an incorrect format.
- X *
- X *******************************************************************************
- X */
- X
- Xchar *
- Xres_skip(msg, numFieldsToSkip, eom)
- X char *msg;
- X int numFieldsToSkip;
- X char *eom;
- X{
- X register char *cp;
- X register HEADER *hp;
- X register int tmp;
- X register int n;
- X
- X /*
- X * Skip the header fields.
- X */
- X hp = (HEADER *)msg;
- X cp = msg + sizeof(HEADER);
- X
- X /*
- X * skip question records.
- X */
- X if (n = ntohs(hp->qdcount) ) {
- X while (--n >= 0 && cp < eom) {
- X tmp = dn_skipname(cp, eom);
- X if (tmp == -1) return(NULL);
- X cp += tmp;
- X cp += sizeof(u_short); /* type */
- X cp += sizeof(u_short); /* class */
- X }
- X }
- X if (--numFieldsToSkip <= 0) return(cp);
- X
- X /*
- X * skip authoritative answer records
- X */
- X if (n = ntohs(hp->ancount)) {
- X while (--n >= 0 && cp < eom) {
- X cp = res_skip_rr(cp, eom);
- X if (cp == NULL) return(NULL);
- X }
- X }
- X if (--numFieldsToSkip == 0) return(cp);
- X
- X /*
- X * skip name server records
- X */
- X if (n = ntohs(hp->nscount)) {
- X while (--n >= 0 && cp < eom) {
- X cp = res_skip_rr(cp, eom);
- X if (cp == NULL) return(NULL);
- X }
- X }
- X if (--numFieldsToSkip == 0) return(cp);
- X
- X /*
- X * skip additional records
- X */
- X if (n = ntohs(hp->arcount)) {
- X while (--n >= 0 && cp < eom) {
- X cp = res_skip_rr(cp, eom);
- X if (cp == NULL) return(NULL);
- X }
- X }
- X
- X return(cp);
- X}
- X
- X
- X/*
- X *******************************************************************************
- X *
- X * res_skip_rr --
- X *
- X * Skip over resource record fields.
- X *
- X * Results:
- X * (address) - success operation.
- X * NULL - a resource record had an incorrect format.
- X *******************************************************************************
- X */
- X
- Xchar *
- Xres_skip_rr(cp, eom)
- X char *cp;
- X char *eom;
- X{
- X int tmp;
- X int dlen;
- X
- X if ((tmp = dn_skipname(cp, eom)) == -1)
- X return (NULL); /* compression error */
- X cp += tmp;
- X if ((cp + RRFIXEDSZ) > eom)
- X return (NULL);
- X cp += sizeof(u_short); /* type */
- X cp += sizeof(u_short); /* class */
- X cp += sizeof(u_long); /* ttl */
- X dlen = _getshort(cp);
- X cp += sizeof(u_short); /* dlen */
- X cp += dlen;
- X if (cp > eom)
- X return (NULL);
- X return (cp);
- X}
- END_OF_FILE
- if test 4295 -ne `wc -c <'skip.c'`; then
- echo shar: \"'skip.c'\" unpacked with wrong size!
- fi
- # end of 'skip.c'
- fi
- if test -f 'subr.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'subr.c'\"
- else
- echo shar: Extracting \"'subr.c'\" \(7036 characters\)
- sed "s/^X//" >'subr.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1985,1989 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted provided
- X * that: (1) source distributions retain this entire copyright notice and
- X * comment, and (2) distributions including binaries display the following
- X * acknowledgement: ``This product includes software developed by the
- X * University of California, Berkeley and its contributors'' in the
- X * documentation or other materials provided with the distribution and in
- X * all advertising materials mentioning features or use of this software.
- X * Neither the name of the University nor the names of its contributors may
- X * be used to endorse or promote products derived from this software without
- X * specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X/*
- X *******************************************************************************
- X *
- X * subr.c --
- X *
- X * Miscellaneous subroutines for the name server
- X * lookup program.
- X *
- X * Copyright (c) 1985
- X * Andrew Cherenson
- X * U.C. Berkeley
- X * CS298-26 Fall 1985
- X *
- X *******************************************************************************
- X */
- X
- X#include <sys/types.h>
- X#include <netdb.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <stdio.h>
- X#include <arpa/nameser.h>
- X#include <arpa/inet.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include "res.h"
- X
- X/*
- X *******************************************************************************
- X *
- X * OpenFile --
- X *
- X * Parses a command string for a file name and opens
- X * the file.
- X *
- X * Results:
- X * file pointer - the open was successful.
- X * NULL - there was an error opening the file or
- X * the input string was invalid.
- X *
- X *******************************************************************************
- X */
- X
- XFILE *
- XOpenFile(string, file)
- X char *string;
- X char *file;
- X{
- X char *redirect;
- X FILE *tmpPtr;
- X
- X /*
- X * Open an output file if we see '>' or >>'.
- X * Check for overwrite (">") or concatenation (">>").
- X */
- X
- X redirect = strchr(string, '>');
- X if (redirect == NULL) {
- X return(NULL);
- X }
- X if (redirect[1] == '>') {
- X sscanf(redirect, ">> %s", file);
- X tmpPtr = fopen(file, "a+");
- X } else {
- X sscanf(redirect, "> %s", file);
- X tmpPtr = fopen(file, "w");
- X }
- X
- X if (tmpPtr != NULL) {
- X redirect[0] = '\0';
- X }
- X
- X return(tmpPtr);
- X}
- X
- X/*
- X *******************************************************************************
- X *
- X * DecodeError --
- X *
- X * Converts an error code into a character string.
- X *
- X *******************************************************************************
- X */
- X
- Xchar *
- XDecodeError(result)
- X int result;
- X{
- X switch (result) {
- X case NOERROR: return("Success"); break;
- X case FORMERR: return("Format error"); break;
- X case SERVFAIL: return("Server failed"); break;
- X case NXDOMAIN: return("Non-existent domain"); break;
- X case NOTIMP: return("Not implemented"); break;
- X case REFUSED: return("Query refused"); break;
- X case NOCHANGE: return("No change"); break;
- X case TIME_OUT: return("Timed out"); break;
- X case NO_INFO: return("No information"); break;
- X case ERROR: return("Unspecified error"); break;
- X case NONAUTH: return("Non-authoritative answer"); break;
- X case NO_RESPONSE: return("No response from server"); break;
- X default: break;
- X }
- X return("BAD ERROR VALUE");
- X}
- X
- X
- Xint
- XStringToClass(qclass, dflt)
- X char *qclass;
- X int dflt;
- X{
- X if (strcasecmp(qclass, "IN") == 0)
- X return(C_IN);
- X if (strcasecmp(qclass, "CHAOS") == 0)
- X return(C_CHAOS);
- X if (strcasecmp(qclass, "ANY") == 0)
- X return(C_ANY);
- X#ifndef C_HS
- X#define C_HS 4
- X#endif
- X if (strcasecmp(qclass, "HS") == 0)
- X return(C_HS);
- X fprintf(stderr, "unknown query class: %s\n", qclass);
- X return(dflt);
- X}
- X
- X
- X/*
- X *******************************************************************************
- X *
- X * StringToType --
- X *
- X * Converts a string form of a query type name to its
- X * corresponding integer value.
- X *
- X *******************************************************************************
- X */
- X
- Xint
- XStringToType(type, dflt)
- X char *type;
- X int dflt;
- X{
- X if (strcasecmp(type, "A") == 0)
- X return(T_A);
- X if (strcasecmp(type, "NS") == 0)
- X return(T_NS); /* authoritative server */
- X if (strcasecmp(type, "MX") == 0)
- X return(T_MX); /* mail exchanger */
- X if (strcasecmp(type, "CNAME") == 0)
- X return(T_CNAME); /* canonical name */
- X if (strcasecmp(type, "SOA") == 0)
- X return(T_SOA); /* start of authority zone */
- X if (strcasecmp(type, "MB") == 0)
- X return(T_MB); /* mailbox domain name */
- X if (strcasecmp(type, "MG") == 0)
- X return(T_MG); /* mail group member */
- X if (strcasecmp(type, "MR") == 0)
- X return(T_MR); /* mail rename name */
- X if (strcasecmp(type, "WKS") == 0)
- X return(T_WKS); /* well known service */
- X if (strcasecmp(type, "PTR") == 0)
- X return(T_PTR); /* domain name pointer */
- X if (strcasecmp(type, "HINFO") == 0)
- X return(T_HINFO); /* host information */
- X if (strcasecmp(type, "MINFO") == 0)
- X return(T_MINFO); /* mailbox information */
- X if (strcasecmp(type, "AXFR") == 0)
- X return(T_AXFR); /* zone transfer */
- X if (strcasecmp(type, "MAILA") == 0)
- X return(T_MAILA); /* mail agent */
- X if (strcasecmp(type, "MAILB") == 0)
- X return(T_MAILB); /* mail box */
- X if (strcasecmp(type, "ANY") == 0)
- X return(T_ANY); /* matches any type */
- X if (strcasecmp(type, "UINFO") == 0)
- X return(T_UINFO); /* user info */
- X if (strcasecmp(type, "UID") == 0)
- X return(T_UID); /* user id */
- X if (strcasecmp(type, "GID") == 0)
- X return(T_GID); /* group id */
- X fprintf(stderr, "unknown query type: %s\n", type);
- X return(dflt);
- X}
- X
- X/*
- X *******************************************************************************
- X *
- X * DecodeType --
- X *
- X * Converts a query type to a descriptive name.
- X * (A more verbose form of p_type.)
- X *
- X *
- X *******************************************************************************
- X */
- X
- Xstatic char nbuf[20];
- X
- Xchar *
- XDecodeType(type)
- X int type;
- X{
- X switch (type) {
- X case T_A:
- X return("address");
- X case T_NS:
- X return("name server");
- X case T_CNAME:
- X return("canonical name");
- X case T_SOA:
- X return("start of authority");
- X case T_MB:
- X return("mailbox");
- X case T_MG:
- X return("mail group member");
- X case T_MR:
- X return("mail rename");
- X case T_NULL:
- X return("null");
- X case T_WKS:
- X return("well-known service");
- X case T_PTR:
- X return("domain name pointer");
- X case T_HINFO:
- X return("host information");
- X case T_MINFO:
- X return("mailbox information");
- X case T_MX:
- X return("mail exchanger");
- X case T_UINFO:
- X return("user information");
- X case T_UID:
- X return("user ID");
- X case T_GID:
- X return("group ID");
- X case T_AXFR:
- X return("zone transfer");
- X case T_MAILB:
- X return("mailbox-related data");
- X case T_MAILA:
- X return("mail agent");
- X case T_ANY:
- X return("\"any\"");
- X default:
- X (void) sprintf(nbuf, "%d", type);
- X return (nbuf);
- X }
- X}
- END_OF_FILE
- if test 7036 -ne `wc -c <'subr.c'`; then
- echo shar: \"'subr.c'\" unpacked with wrong size!
- fi
- # end of 'subr.c'
- fi
- if test -f 'vtable.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vtable.c'\"
- else
- echo shar: Extracting \"'vtable.c'\" \(3648 characters\)
- sed "s/^X//" >'vtable.c' <<'END_OF_FILE'
- X/*
- X * VARIABLE LENGTH TABLES
- X *
- X * Features: Grows according to how many records you put into it.
- X * It it not possible to have empty slots in the table.
- X */
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <assert.h>
- X#include "vtable.h"
- X#include <string.h>
- X#ifndef SYSV
- X#include <memory.h>
- X#endif
- X
- Xvtable *
- XVTableCreate(int recsize)
- X{
- X vtable *vt;
- X
- X assert(recsize);
- X vt = (vtable *)malloc(sizeof(vtable));
- X assert(vt);
- X memset(vt,0,sizeof(vtable));
- X vt->rec_size = recsize;
- X vt->cmp = (vtablecmp)memcmp;
- X vt->magic = 0xdb;
- X return vt;
- X}
- X
- XVTableSet(vtable *vt,int recsize)
- X{
- X memset(vt,0,sizeof(vtable));
- X vt->rec_size = recsize;
- X vt->cmp = (vtablecmp)memcmp;
- X vt->magic = 0xdb;
- X}
- X
- Xint
- XVTableAlloc(vtable *vt,int nelem)
- X{
- X /* Allocate more space */
- X if(nelem <= 0 || nelem == vt->num_slots)
- X return 0;
- X if(nelem < vt->num_slots)
- X {
- X if(vt->end > nelem)
- X return 1;
- X }
- X vt->num_slots = nelem;
- X if(vt->end == 0)
- X vt->data = malloc(vt->num_slots * vt->rec_size);
- X else
- X vt->data = realloc(vt->data,vt->num_slots * vt->rec_size);
- X return 0;
- X}
- X
- Xvoid VTableSetCmp(vtable *vt,vtablecmp cmp)
- X{
- X vt->cmp = cmp;
- X}
- X
- Xvoid
- XVTableAppend(vtable *vt,char *data)
- X{
- X assert(vt && (vt->magic == 0xdb));
- X if(vt->num_slots == vt->end)
- X { /* Allocate more space */
- X vt->num_slots += (vt->num_slots / 2) + 2;
- X if(vt->end == 0)
- X vt->data = malloc(vt->num_slots * vt->rec_size);
- X else
- X vt->data = realloc(vt->data,vt->num_slots * vt->rec_size);
- X }
- X memcpy(vt->data + (vt->rec_size * vt->end),data,vt->rec_size);
- X vt->end++;
- X}
- X
- X/*
- X * Only to be used if your table was created with VTableCreate
- X */
- Xvoid
- XVTableDestroy(vtable *vt)
- X{
- X assert(vt && (vt->magic == 0xdb));
- X if(vt->data) free(vt->data);
- X vt->data = NULL;
- X vt->num_slots = 0;
- X vt->magic = 0;
- X free(vt);
- X}
- X
- Xvoid
- XVTableClean(vtable *vt)
- X{
- X if(vt->data) free(vt->data);
- X/* vt->rec_size = 0; */
- X vt->data = NULL;
- X vt->num_slots = 0;
- X vt->end = 0;
- X}
- X
- Xchar *
- XVTableIndex(vtable *vt,int inx)
- X{
- X if(!vt->data) return NULL;
- X if((inx >= vt->end)|| inx <0) return NULL;
- X return vt->data + (inx * vt->rec_size);
- X}
- X
- X/*
- X * This function is designed for a while loop.
- X */
- Xchar *
- XVTableNext(vtable *vt,int *inx,int step)
- X{
- X char *rec;
- X
- X assert(vt && (vt->magic == 0xdb));
- X rec = VTableIndex(vt,*inx);
- X if(rec)
- X (*inx)+= step;
- X return rec;
- X}
- X
- Xchar *
- XVTableLookup(vtable *vt,char *key)
- X{
- X register int position;
- X
- X if(!vt->data) return (char*)0;
- X for(position = 0; position < vt->end; position++)
- X {
- X if(!(*vt->cmp)(key,vt->data + (position * vt->rec_size),vt->rec_size))
- X break;
- X }
- X if(position == vt->end) return (char*)0;
- X
- X return vt->data + (position * vt->rec_size);
- X}
- X
- Xvoid
- XVTableRemove(vtable *vt,char *rec)
- X{
- X register int position;
- X
- X if(!vt->data) return;
- X for(position = 0; position < vt->end; position++)
- X {
- X if(!(*vt->cmp)(rec,vt->data + (position * vt->rec_size),vt->rec_size))
- X break;
- X }
- X if(position == vt->end) return;
- X
- X VTableIRemove(vt,position);
- X return ;
- X}
- X
- Xvoid
- XVTableIRemove(vtable *vt,int position)
- X{
- X if(position >= vt->end || position < 0) return;
- X
- X if(!vt->data) return;
- X /* Ripple children down one space from "position" */
- X vt->end--;
- X if((vt->end - position) > 0)
- X {
- X bcopy(vt->data + ((position+1) * vt->rec_size),
- X vt->data + (position * vt->rec_size),
- X (vt->end - position) * vt->rec_size);
- X }
- X return ;
- X}
- X
- Xint
- XVTableSize(vtable *vt)
- X{
- X return vt->end;
- X}
- X
- X/*
- X * Keep the allocated space.
- X */
- Xvoid
- XVTableZero(vtable *vt)
- X{
- X vt->end = 0;
- X}
- END_OF_FILE
- if test 3648 -ne `wc -c <'vtable.c'`; then
- echo shar: \"'vtable.c'\" unpacked with wrong size!
- fi
- # end of 'vtable.c'
- fi
- if test -f 'vtable.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vtable.h'\"
- else
- echo shar: Extracting \"'vtable.h'\" \(744 characters\)
- sed "s/^X//" >'vtable.h' <<'END_OF_FILE'
- X#ifndef _VTABLE_H_
- X#define _VTABLE_H_
- Xtypedef int (*vtablecmp)(void*,void*,int);
- X/*
- X * Variable length tables;
- X */
- Xtypedef struct {
- X int magic;
- X int end;
- X char *data;
- X int rec_size;
- X int num_slots;
- X vtablecmp cmp;
- X} vtable;
- X
- Xvtable *VTableCreate(int recsize);
- Xint VTableSet(vtable *,int recsize);
- Xvoid VTableAppend(vtable *,char *data);
- Xvoid VTableDestroy(vtable *);
- Xchar * VTableIndex(vtable *,int inx);
- Xchar * VTableNext(vtable *,int *inx,int step);
- Xvoid VTableRemove(vtable *,char *rec);
- Xvoid VTableIRemove(vtable *,int position);
- X
- Xextern int VTableSize(vtable *vt);
- Xextern void VTableZero(vtable *vt);
- Xextern void VTableSetCmp(vtable *,vtablecmp);
- Xextern int VTableAlloc(vtable *,int);
- X#endif /* _VTABLE_H_ */
- END_OF_FILE
- if test 744 -ne `wc -c <'vtable.h'`; then
- echo shar: \"'vtable.h'\" unpacked with wrong size!
- fi
- # end of 'vtable.h'
- fi
- echo shar: End of archive 1 \(of 3\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-