Annotation of 43BSDReno/usr.sbin/named/tools/nslookup/main.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1985,1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: char copyright[] =
                     22: "@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\
                     23:  All rights reserved.\n";
                     24: #endif /* not lint */
                     25: 
                     26: #ifndef lint
                     27: static char sccsid[] = "@(#)main.c     5.39 (Berkeley) 6/24/90";
                     28: #endif /* not lint */
                     29: 
                     30: /*
                     31:  *******************************************************************************
                     32:  *  
                     33:  *   main.c --
                     34:  *  
                     35:  *     Main routine and some action routines for the name server
                     36:  *     lookup program.
                     37:  *
                     38:  *     Andrew Cherenson
                     39:  *     U.C. Berkeley Computer Science Div.
                     40:  *     CS298-26, Fall 1985
                     41:  *  
                     42:  *******************************************************************************
                     43:  */
                     44: 
                     45: #include <sys/param.h>
                     46: #include <netdb.h>
                     47: #include <sys/socket.h>
                     48: #include <netinet/in.h>
                     49: #include <arpa/nameser.h>
                     50: #include <arpa/inet.h>
                     51: #include <resolv.h>
                     52: #include <signal.h>
                     53: #include <setjmp.h>
                     54: #include <ctype.h>
                     55: #include <stdio.h>
                     56: #include <stdlib.h>
                     57: #include <string.h>
                     58: #include "res.h"
                     59: #include "pathnames.h"
                     60: 
                     61: /*
                     62:  *  Default Internet address of the current host.
                     63:  */
                     64: 
                     65: #if BSD < 43
                     66: #define LOCALHOST "127.0.0.1"
                     67: #endif
                     68: 
                     69: 
                     70: /*
                     71:  * Name of a top-level name server. Can be changed with 
                     72:  * the "set root" command.
                     73:  */
                     74: 
                     75: #ifndef ROOT_SERVER
                     76: #define                ROOT_SERVER "ns.nic.ddn.mil."
                     77: #endif
                     78: char           rootServerName[NAME_LEN] = ROOT_SERVER;
                     79: 
                     80: 
                     81: /*
                     82:  *  Import the state information from the resolver library.
                     83:  */
                     84: 
                     85: extern struct state _res;
                     86: 
                     87: 
                     88: /*
                     89:  *  Info about the most recently queried host.
                     90:  */
                     91: 
                     92: HostInfo       curHostInfo;
                     93: int            curHostValid = FALSE;
                     94: 
                     95: 
                     96: /*
                     97:  *  Info about the default name server.
                     98:  */
                     99: 
                    100: HostInfo       *defaultPtr = NULL;
                    101: char           defaultServer[NAME_LEN];
                    102: struct in_addr defaultAddr;
                    103: 
                    104: 
                    105: /*
                    106:  *  Initial name server query type is Address.
                    107:  */
                    108: 
                    109: int            queryType = T_A;
                    110: int            queryClass = C_IN;
                    111: 
                    112: /*
                    113:  * Stuff for Interrupt (control-C) signal handler.
                    114:  */
                    115: 
                    116: #ifdef SVR3
                    117: extern void    IntrHandler();
                    118: #else
                    119: extern int     IntrHandler();
                    120: #endif
                    121: FILE           *filePtr;
                    122: jmp_buf                env;
                    123: 
                    124: static void CvtAddrToPtr();
                    125: static void ReadRC();
                    126: 
                    127: 
                    128: /*
                    129:  *******************************************************************************
                    130:  *
                    131:  *  main --
                    132:  *
                    133:  *     Initializes the resolver library and determines the address
                    134:  *     of the initial name server. The yylex routine is used to
                    135:  *     read and perform commands.
                    136:  *
                    137:  *******************************************************************************
                    138:  */
                    139: 
                    140: main(argc, argv)
                    141:     int                argc;
                    142:     char       **argv;
                    143: {
                    144:     char       *wantedHost = NULL;
                    145:     Boolean    useLocalServer;
                    146:     int                result;
                    147:     int                i;
                    148:     struct hostent     *hp;
                    149:     extern int h_errno;
                    150: 
                    151:     /*
                    152:      *  Initialize the resolver library routines.
                    153:      */
                    154: 
                    155:     if (res_init() == -1) {
                    156:        fprintf(stderr,"*** Can't initialize resolver.\n");
                    157:        exit(1);
                    158:     }
                    159: 
                    160:     /*
                    161:      *  Allocate space for the default server's host info and
                    162:      *  find the server's address and name. If the resolver library
                    163:      *  already has some addresses for a potential name server,
                    164:      *  then use them. Otherwise, see if the current host has a server.
                    165:      *  Command line arguments may override the choice of initial server. 
                    166:      */
                    167: 
                    168:     defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo));
                    169: 
                    170:     /*
                    171:      * Parse the arguments:
                    172:      *  no args =  go into interactive mode, use default host as server
                    173:      * 1 arg   =  use as host name to be looked up, default host will be server
                    174:      *            non-interactive mode
                    175:      *  2 args =  1st arg: 
                    176:      *              if it is '-', then 
                    177:      *                 ignore but go into interactive mode
                    178:      *              else 
                    179:      *                  use as host name to be looked up, 
                    180:      *                  go into non-interactive mode
                    181:      *         2nd arg: name or inet address of server
                    182:      *
                    183:      * "Set" options are specified with a leading - and must come before
                    184:      * any arguments. For example, to find the well-known services for
                    185:      *  a host, type "nslookup -query=wks host"
                    186:      */
                    187: 
                    188:     ReadRC();                  /* look for options file */
                    189: 
                    190:     ++argv; --argc;            /* skip prog name */
                    191: 
                    192:     while (argc && *argv[0] == '-' && argv[0][1]) {
                    193:        (void) SetOption (&(argv[0][1]));
                    194:        ++argv; --argc;
                    195:     }
                    196:     if (argc > 2) {
                    197:        Usage();
                    198:     } 
                    199:     if (argc && *argv[0] != '-') {
                    200:        wantedHost = *argv;     /* name of host to be looked up */
                    201:     }
                    202: 
                    203:     useLocalServer = FALSE;
                    204:     if (argc == 2) {
                    205:        struct in_addr addr;
                    206: 
                    207:        /*
                    208:         * Use an explicit name server. If the hostname lookup fails,
                    209:         * default to the server(s) in resolv.conf.
                    210:         */ 
                    211: 
                    212:        addr.s_addr = inet_addr(*++argv);
                    213:        if (addr.s_addr != (unsigned long)-1) {
                    214:            _res.nscount = 1;
                    215:            _res.nsaddr.sin_addr = addr;
                    216:        } else {
                    217:            hp = gethostbyname(*argv);
                    218:            if (hp == NULL) {
                    219:                fprintf(stderr, "*** Can't find server address for '%s': ", 
                    220:                        *argv);
                    221:                herror((char *)NULL);
                    222:                fputc('\n', stderr);
                    223:            } else {
                    224: #if BSD < 43
                    225:                bcopy(hp->h_addr, (char *)&_res.nsaddr.sin_addr, hp->h_length);
                    226:                _res.nscount = 1;
                    227: #else
                    228:                for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) {
                    229:                    bcopy(hp->h_addr_list[i], 
                    230:                            (char *)&_res.nsaddr_list[i].sin_addr, 
                    231:                            hp->h_length);
                    232:                }
                    233:                _res.nscount = i;
                    234: #endif
                    235:            } 
                    236:        }
                    237:     }
                    238: 
                    239: 
                    240:     if (_res.nscount == 0 || useLocalServer) {
                    241:        LocalServer(defaultPtr);
                    242:     } else {
                    243:        for (i = 0; i < _res.nscount; i++) {
                    244:            if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) {
                    245:                LocalServer(defaultPtr);
                    246:                break;
                    247:            } else {
                    248:                result = GetHostInfoByAddr(&(_res.nsaddr_list[i].sin_addr), 
                    249:                                    &(_res.nsaddr_list[i].sin_addr), 
                    250:                                    defaultPtr);
                    251:                if (result != SUCCESS) {
                    252:                    fprintf(stderr,
                    253:                    "*** Can't find server name for address %s: %s\n", 
                    254:                       inet_ntoa(_res.nsaddr_list[i].sin_addr), 
                    255:                       DecodeError(result));
                    256:                } else {
                    257:                    defaultAddr = _res.nsaddr_list[i].sin_addr;
                    258:                    break;
                    259:                }
                    260:            }
                    261:        }
                    262: 
                    263:        /*
                    264:         *  If we have exhausted the list, tell the user about the
                    265:         *  command line argument to specify an address.
                    266:         */
                    267: 
                    268:        if (i == _res.nscount) {
                    269:            fprintf(stderr, "*** Default servers are not available\n");
                    270:            exit(1);
                    271:        }
                    272: 
                    273:     }
                    274:     strcpy(defaultServer, defaultPtr->name);
                    275: 
                    276: 
                    277: #ifdef DEBUG
                    278: #ifdef DEBUG2
                    279:     _res.options |= RES_DEBUG2;
                    280: #endif
                    281:     _res.options |= RES_DEBUG;
                    282:     _res.retry    = 2;
                    283: #endif DEBUG
                    284: 
                    285:     /*
                    286:      * If we're in non-interactive mode, look up the wanted host and quit.
                    287:      * Otherwise, print the initial server's name and continue with
                    288:      * the initialization.
                    289:      */
                    290: 
                    291:     if (wantedHost != (char *) NULL) {
                    292:        LookupHost(wantedHost, 0);
                    293:     } else {
                    294:        PrintHostInfo(stdout, "Default Server:", defaultPtr);
                    295: 
                    296:        /*
                    297:         * Setup the environment to allow the interrupt handler to return here.
                    298:         */
                    299: 
                    300:        (void) setjmp(env);
                    301: 
                    302:        /* 
                    303:         * Return here after a longjmp.
                    304:         */
                    305: 
                    306:        signal(SIGINT, IntrHandler);
                    307:        signal(SIGPIPE, SIG_IGN);
                    308: 
                    309:        /*
                    310:         * Read and evaluate commands. The commands are described in commands.l
                    311:         * Yylex returns 0 when ^D or 'exit' is typed. 
                    312:         */
                    313: 
                    314:        printf("> ");
                    315:        fflush(stdout);
                    316:        while(yylex()) {
                    317:            printf("> ");
                    318:            fflush(stdout);
                    319:        }
                    320:     }
                    321:     exit(0);
                    322: }
                    323: 
                    324: 
                    325: LocalServer(defaultPtr)
                    326:     HostInfo *defaultPtr;
                    327: {
                    328:     char       hostName[NAME_LEN];
                    329: #if BSD < 43
                    330:     int                result;
                    331: #endif
                    332: 
                    333:     gethostname(hostName, sizeof(hostName));
                    334: 
                    335: #if BSD < 43
                    336:     defaultAddr.s_addr = inet_addr(LOCALHOST);
                    337:     result = GetHostInfoByName(&defaultAddr, C_IN, T_A, 
                    338:                hostName, defaultPtr, 1);
                    339:     if (result != SUCCESS) {
                    340:        fprintf(stderr,
                    341:        "*** Can't find initialize address for server %s: %s\n",
                    342:                        defaultServer, DecodeError(result));
                    343:        exit(1);
                    344:     }
                    345: #else
                    346:     defaultAddr.s_addr = htonl(INADDR_ANY);
                    347:     (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1);
                    348:     free(defaultPtr->name);
                    349:     defaultPtr->name = Calloc(1, sizeof(hostName)+1);
                    350:     strcpy(defaultPtr->name, hostName);
                    351: #endif
                    352: }
                    353: 
                    354: 
                    355: /*
                    356:  *******************************************************************************
                    357:  *
                    358:  *  Usage --
                    359:  *
                    360:  *     Lists the proper methods to run the program and exits.
                    361:  *
                    362:  *******************************************************************************
                    363:  */
                    364: 
                    365: Usage()
                    366: {
                    367:     fprintf(stderr, "Usage:\n");
                    368:     fprintf(stderr,
                    369: "   nslookup [-opt ...]             # interactive mode using default server\n");
                    370:     fprintf(stderr,
                    371: "   nslookup [-opt ...] - server    # interactive mode using 'server'\n");
                    372:     fprintf(stderr,
                    373: "   nslookup [-opt ...] host        # just look up 'host' using default server\n");
                    374:     fprintf(stderr,
                    375: "   nslookup [-opt ...] host server # just look up 'host' using 'server'\n");
                    376:     exit(1);
                    377: }
                    378: 
                    379: /*
                    380:  *******************************************************************************
                    381:  *
                    382:  * IsAddr --
                    383:  *
                    384:  *     Returns TRUE if the string looks like an Internet address.
                    385:  *     A string with a trailing dot is not an address, even if it looks
                    386:  *     like one.
                    387:  *
                    388:  *     XXX doesn't treat 255.255.255.255 as an address.
                    389:  *
                    390:  *******************************************************************************
                    391:  */
                    392: 
                    393: Boolean
                    394: IsAddr(host, addrPtr)
                    395:     char *host;
                    396:     unsigned long *addrPtr;    /* If return TRUE, contains IP address */
                    397: {
                    398:     register char *cp;
                    399:     unsigned long addr;
                    400: 
                    401:     if (isdigit(host[0])) {
                    402:            /* Make sure it has only digits and dots. */
                    403:            for (cp = host; *cp; ++cp) {
                    404:                if (!isdigit(*cp) && *cp != '.') 
                    405:                    return FALSE;
                    406:            }
                    407:            /* If it has a trailing dot, don't treat it as an address. */
                    408:            if (*--cp != '.') { 
                    409:                if ((addr = inet_addr(host)) != (unsigned long) -1) {
                    410:                    *addrPtr = addr;
                    411:                    return TRUE;
                    412: #if 0
                    413:                } else {
                    414:                    /* XXX Check for 255.255.255.255 case */
                    415: #endif
                    416:                }
                    417:            }
                    418:     }
                    419:     return FALSE;
                    420: }
                    421: 
                    422: 
                    423: /*
                    424:  *******************************************************************************
                    425:  *
                    426:  *  SetDefaultServer --
                    427:  *
                    428:  *     Changes the default name server to the one specified by
                    429:  *     the first argument. The command "server name" uses the current 
                    430:  *     default server to lookup the info for "name". The command
                    431:  *     "lserver name" uses the original server to lookup "name".
                    432:  *
                    433:  *  Side effects:
                    434:  *     This routine will cause a core dump if the allocation requests fail.
                    435:  *
                    436:  *  Results:
                    437:  *     SUCCESS         The default server was changed successfully.
                    438:  *     NONAUTH         The server was changed but addresses of
                    439:  *                     other servers who know about the requested server
                    440:  *                     were returned.
                    441:  *     Errors          No info about the new server was found or
                    442:  *                     requests to the current server timed-out.
                    443:  *
                    444:  *******************************************************************************
                    445:  */
                    446: 
                    447: int
                    448: SetDefaultServer(string, local)
                    449:     char       *string;
                    450:     Boolean    local;
                    451: {
                    452:     register HostInfo  *newDefPtr;
                    453:     struct in_addr     *servAddrPtr;
                    454:     struct in_addr     addr;
                    455:     char               newServer[NAME_LEN];
                    456:     int                        result;
                    457:     int                        i;
                    458: 
                    459:     /*
                    460:      *  Parse the command line. It maybe of the form "server name",
                    461:      *  "lserver name" or just "name".
                    462:      */
                    463: 
                    464:     if (local) {
                    465:        i = sscanf(string, " lserver %s", newServer);
                    466:     } else {
                    467:        i = sscanf(string, " server %s", newServer);
                    468:     }
                    469:     if (i != 1) {
                    470:        i = sscanf(string, " %s", newServer);
                    471:        if (i != 1) {
                    472:            fprintf(stderr,"SetDefaultServer: invalid name: %s\n",  string);
                    473:            return(ERROR);
                    474:        }
                    475:     }
                    476: 
                    477:     /*
                    478:      * Allocate space for a HostInfo variable for the new server. Don't
                    479:      * overwrite the old HostInfo struct because info about the new server
                    480:      * might not be found and we need to have valid default server info.
                    481:      */
                    482: 
                    483:     newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo));
                    484: 
                    485: 
                    486:     /*
                    487:      * A 'local' lookup uses the original server that the program was
                    488:      *  initialized with.
                    489:      *
                    490:      *  Check to see if we have the address of the server or the
                    491:      *  address of a server who knows about this domain.
                    492:      *  XXX For now, just use the first address in the list.
                    493:      */
                    494: 
                    495:     if (local) {
                    496:        servAddrPtr = &defaultAddr;
                    497:     } else if (defaultPtr->addrList != NULL) {
                    498:        servAddrPtr = (struct in_addr *) defaultPtr->addrList[0];
                    499:     } else {
                    500:        servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0];
                    501:     }
                    502: 
                    503:     result = ERROR;
                    504:     if (IsAddr(newServer, &addr.s_addr)) {
                    505:        result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr);
                    506:        /* If we can't get the name, fall through... */
                    507:     } 
                    508:     if (result != SUCCESS && result != NONAUTH) {
                    509:        result = GetHostInfoByName(servAddrPtr, C_IN, T_A, 
                    510:                        newServer, newDefPtr, 1);
                    511:     }
                    512: 
                    513:     if (result == SUCCESS || result == NONAUTH) {
                    514:            /*
                    515:             *  Found info about the new server. Free the resources for
                    516:             *  the old server.
                    517:             */
                    518: 
                    519:            FreeHostInfoPtr(defaultPtr);
                    520:            free((char *)defaultPtr);
                    521:            defaultPtr = newDefPtr;
                    522:            strcpy(defaultServer, defaultPtr->name);
                    523:            PrintHostInfo(stdout, "Default Server:", defaultPtr);
                    524:            return(SUCCESS);
                    525:     } else {
                    526:            fprintf(stderr, "*** Can't find address for server %s: %s\n",
                    527:                    newServer, DecodeError(result));
                    528:            free((char *)newDefPtr);
                    529: 
                    530:            return(result);
                    531:     }
                    532: }
                    533: 
                    534: /*
                    535:  *******************************************************************************
                    536:  *
                    537:  * DoLoookup --
                    538:  *
                    539:  *     Common subroutine for LookupHost and LookupHostWithServer.
                    540:  *
                    541:  *  Results:
                    542:  *     SUCCESS         - the lookup was successful.
                    543:  *     Misc. Errors    - an error message is printed if the lookup failed.
                    544:  *
                    545:  *******************************************************************************
                    546:  */
                    547: 
                    548: static int
                    549: DoLookup(host, servPtr, serverName)
                    550:     char       *host;
                    551:     HostInfo   *servPtr;
                    552:     char       *serverName;
                    553: {
                    554:     int result;
                    555:     struct in_addr *servAddrPtr;
                    556:     struct in_addr addr; 
                    557: 
                    558:     /* Skip escape character */
                    559:     if (host[0] == '\\')
                    560:        host++;
                    561: 
                    562:     /*
                    563:      *  If the user gives us an address for an address query, 
                    564:      *  silently treat it as a PTR query. If the query type is already
                    565:      *  PTR, then convert the address into the in-addr.arpa format.
                    566:      *
                    567:      *  Use the address of the server if it exists, otherwise use the
                    568:      * address of a server who knows about this domain.
                    569:      *  XXX For now, just use the first address in the list.
                    570:      */
                    571: 
                    572:     if (servPtr->addrList != NULL) {
                    573:        servAddrPtr = (struct in_addr *) servPtr->addrList[0];
                    574:     } else {
                    575:        servAddrPtr = (struct in_addr *) servPtr->servers[0]->addrList[0];
                    576:     }
                    577: 
                    578:     /* 
                    579:      * RFC1123 says we "SHOULD check the string syntactically for a 
                    580:      * dotted-decimal number before looking it up [...]" (p. 13).
                    581:      */
                    582:     if (queryType == T_A && IsAddr(host, &addr.s_addr)) {
                    583:        result = GetHostInfoByAddr(servAddrPtr, &addr, &curHostInfo);
                    584:     } else {
                    585:        if (queryType == T_PTR) {
                    586:            CvtAddrToPtr(host);
                    587:        } 
                    588:        result = GetHostInfoByName(servAddrPtr, queryClass, queryType, host, 
                    589:                        &curHostInfo, 0);
                    590:     }
                    591: 
                    592:     switch (result) {
                    593:        case SUCCESS:
                    594:            /*
                    595:             *  If the query was for an address, then the &curHostInfo
                    596:             *  variable can be used by Finger.
                    597:             *  There's no need to print anything for other query types
                    598:             *  because the info has already been printed.
                    599:             */
                    600:            if (queryType == T_A) {
                    601:                curHostValid = TRUE;
                    602:                PrintHostInfo(filePtr, "Name:", &curHostInfo);
                    603:            }
                    604:            break;
                    605: 
                    606:        /*
                    607:         * No Authoritative answer was available but we got names
                    608:         * of servers who know about the host.
                    609:         */
                    610:        case NONAUTH:
                    611:            PrintHostInfo(filePtr, "Name:", &curHostInfo);
                    612:            break;
                    613: 
                    614:        case NO_INFO:
                    615:            fprintf(stderr, "*** No %s (%s) records available for %s\n", 
                    616:                        DecodeType(queryType), p_type(queryType), host);
                    617:            break;
                    618: 
                    619:        case TIME_OUT:
                    620:            fprintf(stderr, "*** Request to %s timed-out\n", serverName);
                    621:            break;
                    622: 
                    623:        default:
                    624:            fprintf(stderr, "*** %s can't find %s: %s\n", serverName, host,
                    625:                    DecodeError(result));
                    626:     }
                    627:     return result;
                    628: }
                    629: 
                    630: /*
                    631:  *******************************************************************************
                    632:  *
                    633:  *  LookupHost --
                    634:  *
                    635:  *     Asks the default name server for information about the
                    636:  *     specified host or domain. The information is printed
                    637:  *     if the lookup was successful.
                    638:  *
                    639:  *  Results:
                    640:  *     ERROR           - the output file could not be opened.
                    641:  *     + results of DoLookup
                    642:  *
                    643:  *******************************************************************************
                    644:  */
                    645: 
                    646: int
                    647: LookupHost(string, putToFile)
                    648:     char       *string;
                    649:     Boolean    putToFile;
                    650: {
                    651:     char       host[NAME_LEN];
                    652:     char       file[NAME_LEN];
                    653:     int                result;
                    654: 
                    655:     /*
                    656:      *  Invalidate the current host information to prevent Finger 
                    657:      *  from using bogus info.
                    658:      */
                    659: 
                    660:     curHostValid = FALSE;
                    661: 
                    662:     /*
                    663:      *  Parse the command string into the host and
                    664:      *  optional output file name.
                    665:      *
                    666:      */
                    667: 
                    668:     sscanf(string, " %s", host);       /* removes white space */
                    669:     if (!putToFile) {
                    670:        filePtr = stdout;
                    671:     } else {
                    672:        filePtr = OpenFile(string, file);
                    673:        if (filePtr == NULL) {
                    674:            fprintf(stderr, "*** Can't open %s for writing\n", file);
                    675:            return(ERROR);
                    676:        }
                    677:        fprintf(filePtr,"> %s\n", string);
                    678:     }
                    679: 
                    680:     PrintHostInfo(filePtr, "Server:", defaultPtr);
                    681: 
                    682:     result = DoLookup(host, defaultPtr, defaultServer);
                    683: 
                    684:     if (putToFile) {
                    685:        fclose(filePtr);
                    686:        filePtr = NULL;
                    687:     }
                    688:     return(result);
                    689: }
                    690: 
                    691: /*
                    692:  *******************************************************************************
                    693:  *
                    694:  *  LookupHostWithServer --
                    695:  *
                    696:  *     Asks the name server specified in the second argument for 
                    697:  *     information about the host or domain specified in the first
                    698:  *     argument. The information is printed if the lookup was successful.
                    699:  *
                    700:  *     Address info about the requested name server is obtained
                    701:  *     from the default name server. This routine will return an
                    702:  *     error if the default server doesn't have info about the 
                    703:  *     requested server. Thus an error return status might not
                    704:  *     mean the requested name server doesn't have info about the
                    705:  *     requested host.
                    706:  *
                    707:  *     Comments from LookupHost apply here, too.
                    708:  *
                    709:  *  Results:
                    710:  *     ERROR           - the output file could not be opened.
                    711:  *     + results of DoLookup
                    712:  *
                    713:  *******************************************************************************
                    714:  */
                    715: 
                    716: int
                    717: LookupHostWithServer(string, putToFile)
                    718:     char       *string;
                    719:     Boolean    putToFile;
                    720: {
                    721:     char       file[NAME_LEN];
                    722:     char       host[NAME_LEN];
                    723:     char       server[NAME_LEN];
                    724:     int                result;
                    725:     static HostInfo serverInfo;
                    726: 
                    727:     curHostValid = FALSE;
                    728: 
                    729:     sscanf(string, " %s %s", host, server);
                    730:     if (!putToFile) {
                    731:        filePtr = stdout;
                    732:     } else {
                    733:        filePtr = OpenFile(string, file);
                    734:        if (filePtr == NULL) {
                    735:            fprintf(stderr, "*** Can't open %s for writing\n", file);
                    736:            return(ERROR);
                    737:        }
                    738:        fprintf(filePtr,"> %s\n", string);
                    739:     }
                    740:     
                    741:     result = GetHostInfoByName(
                    742:                defaultPtr->addrList ?
                    743:                    (struct in_addr *) defaultPtr->addrList[0] :
                    744:                    (struct in_addr *) defaultPtr->servers[0]->addrList[0], 
                    745:                C_IN, T_A, server, &serverInfo, 1);
                    746: 
                    747:     if (result != SUCCESS) {
                    748:        fprintf(stderr,"*** Can't find address for server %s: %s\n", server,
                    749:                 DecodeError(result));
                    750:     } else {
                    751:        PrintHostInfo(filePtr, "Server:", &serverInfo);
                    752: 
                    753:        result = DoLookup(host, &serverInfo, server);
                    754:     }
                    755:     if (putToFile) {
                    756:        fclose(filePtr);
                    757:        filePtr = NULL;
                    758:     }
                    759:     return(result);
                    760: }
                    761: 
                    762: /*
                    763:  *******************************************************************************
                    764:  *
                    765:  *  SetOption -- 
                    766:  *
                    767:  *     This routine is used to change the state information
                    768:  *     that affect the lookups. The command format is
                    769:  *        set keyword[=value]
                    770:  *     Most keywords can be abbreviated. Parsing is very simplistic--
                    771:  *     A value must not be separated from its keyword by white space.
                    772:  *
                    773:  *     Valid keywords:         Meaning:
                    774:  *     all                     lists current values of options.
                    775:  *     ALL                     lists current values of options, including
                    776:  *                               hidden options.
                    777:  *     [no]d2                  turn on/off extra debugging mode.
                    778:  *     [no]debug               turn on/off debugging mode.
                    779:  *     [no]defname             use/don't use default domain name.
                    780:  *     [no]search              use/don't use domain search list.
                    781:  *     domain=NAME             set default domain name to NAME.
                    782:  *     [no]ignore              ignore/don't ignore trunc. errors.
                    783:  *     query=value             set default query type to value,
                    784:  *                             value is one of the query types in RFC883
                    785:  *                             without the leading T_. (e.g., A, HINFO)
                    786:  *     [no]recurse             use/don't use recursive lookup.
                    787:  *     retry=#                 set number of retries to #.
                    788:  *     root=NAME               change root server to NAME.
                    789:  *     time=#                  set timeout length to #.
                    790:  *     [no]vc                  use/don't use virtual circuit.
                    791:  *     port                    TCP/UDP port to server.
                    792:  *
                    793:  *     Deprecated:
                    794:  *     [no]primary             use/don't use primary server.
                    795:  *
                    796:  *  Results:
                    797:  *     SUCCESS         the command was parsed correctly.
                    798:  *     ERROR           the command was not parsed correctly.
                    799:  *
                    800:  *******************************************************************************
                    801:  */
                    802: 
                    803: int
                    804: SetOption(option)
                    805:     register char *option;
                    806: {
                    807:     char       type[NAME_LEN];
                    808:     char       *ptr;
                    809:     int                tmp;
                    810: 
                    811:     while (isspace(*option))
                    812:        ++option;
                    813:     if (strncmp (option, "set ", 4) == 0)
                    814:        option += 4;
                    815:     while (isspace(*option))
                    816:        ++option;
                    817: 
                    818:     if (*option == 0) {
                    819:        fprintf(stderr, "*** Invalid set command\n");
                    820:        return(ERROR);
                    821:     } else {
                    822:        if (strncmp(option, "all", 3) == 0) {
                    823:            ShowOptions();
                    824:        } else if (strncmp(option, "ALL", 3) == 0) {
                    825:            ShowOptions();
                    826:        } else if (strncmp(option, "d2", 2) == 0) {     /* d2 (more debug) */
                    827:            _res.options |= (RES_DEBUG | RES_DEBUG2);
                    828:        } else if (strncmp(option, "nod2", 4) == 0) {
                    829:            _res.options &= ~RES_DEBUG2;
                    830:            printf("d2 mode disabled; still in debug mode\n");
                    831:        } else if (strncmp(option, "def", 3) == 0) {    /* defname */
                    832:            _res.options |= RES_DEFNAMES;
                    833:        } else if (strncmp(option, "nodef", 5) == 0) {
                    834:            _res.options &= ~RES_DEFNAMES;
                    835:        } else if (strncmp(option, "do", 2) == 0) {     /* domain */
                    836:            ptr = strchr(option, '=');
                    837:            if (ptr != NULL) {
                    838:                sscanf(++ptr, "%s", _res.defdname);
                    839:                res_re_init();
                    840:            }
                    841:        } else if (strncmp(option, "deb", 1) == 0) {    /* debug */
                    842:            _res.options |= RES_DEBUG;
                    843:        } else if (strncmp(option, "nodeb", 5) == 0) {
                    844:            _res.options &= ~(RES_DEBUG | RES_DEBUG2);
                    845:        } else if (strncmp(option, "ig", 2) == 0) {     /* ignore */
                    846:            _res.options |= RES_IGNTC;
                    847:        } else if (strncmp(option, "noig", 4) == 0) {
                    848:            _res.options &= ~RES_IGNTC;
                    849:        } else if (strncmp(option, "po", 2) == 0) {     /* port */
                    850:            ptr = strchr(option, '=');
                    851:            if (ptr != NULL) {
                    852:                sscanf(++ptr, "%hu", &nsport);
                    853:            }
                    854: #ifdef deprecated
                    855:        } else if (strncmp(option, "pri", 3) == 0) {    /* primary */
                    856:            _res.options |= RES_PRIMARY;
                    857:        } else if (strncmp(option, "nopri", 5) == 0) {
                    858:            _res.options &= ~RES_PRIMARY;
                    859: #endif
                    860:        } else if (strncmp(option, "q", 1) == 0 ||      /* querytype */
                    861:          strncmp(option, "ty", 2) == 0) {              /* type */
                    862:            ptr = strchr(option, '=');
                    863:            if (ptr != NULL) {
                    864:                sscanf(++ptr, "%s", type);
                    865:                queryType = StringToType(type, queryType);
                    866:            }
                    867:        } else if (strncmp(option, "cl", 2) == 0) {     /* query class */
                    868:            ptr = strchr(option, '=');
                    869:            if (ptr != NULL) {
                    870:                sscanf(++ptr, "%s", type);
                    871:                queryClass = StringToClass(type, queryClass);
                    872:            }
                    873:        } else if (strncmp(option, "rec", 3) == 0) {    /* recurse */
                    874:            _res.options |= RES_RECURSE;
                    875:        } else if (strncmp(option, "norec", 5) == 0) {
                    876:            _res.options &= ~RES_RECURSE;
                    877:        } else if (strncmp(option, "ret", 3) == 0) {    /* retry */
                    878:            ptr = strchr(option, '=');
                    879:            if (ptr != NULL) {
                    880:                sscanf(++ptr, "%d", &tmp);
                    881:                if (tmp >= 0) {
                    882:                    _res.retry = tmp;
                    883:                }
                    884:            }
                    885:        } else if (strncmp(option, "ro", 2) == 0) {     /* root */
                    886:            ptr = strchr(option, '=');
                    887:            if (ptr != NULL) {
                    888:                sscanf(++ptr, "%s", rootServerName);
                    889:            }
                    890:        } else if (strncmp(option, "sea", 3) == 0) {    /* search list */
                    891:            _res.options |= RES_DNSRCH;
                    892:        } else if (strncmp(option, "nosea", 5) == 0) {
                    893:            _res.options &= ~RES_DNSRCH;
                    894:        } else if (strncmp(option, "srchl", 5) == 0) {  /* domain search list */
                    895:            ptr = strchr(option, '=');
                    896:            if (ptr != NULL) {
                    897:                res_dnsrch(++ptr);
                    898:            }
                    899:        } else if (strncmp(option, "ti", 2) == 0) {     /* timeout */
                    900:            ptr = strchr(option, '=');
                    901:            if (ptr != NULL) {
                    902:                sscanf(++ptr, "%d", &tmp);
                    903:                if (tmp >= 0) {
                    904:                    _res.retrans = tmp;
                    905:                }
                    906:            }
                    907:        } else if (strncmp(option, "v", 1) == 0) {      /* vc */
                    908:            _res.options |= RES_USEVC;
                    909:        } else if (strncmp(option, "nov", 3) == 0) {
                    910:            _res.options &= ~RES_USEVC;
                    911:        } else {
                    912:            fprintf(stderr, "*** Invalid option: %s\n",  option);
                    913:            return(ERROR);
                    914:        }
                    915:     }
                    916:     return(SUCCESS);
                    917: }
                    918: 
                    919: /*
                    920:  * Fake a reinitialization when the domain is changed.
                    921:  */
                    922: res_re_init()
                    923: {
                    924:     register char *cp, **pp;
                    925:     int n;
                    926: 
                    927:     /* find components of local domain that might be searched */
                    928:     pp = _res.dnsrch;
                    929:     *pp++ = _res.defdname;
                    930:     for (cp = _res.defdname, n = 0; *cp; cp++)
                    931:        if (*cp == '.')
                    932:            n++;
                    933:     cp = _res.defdname;
                    934:     for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) {
                    935:        cp = strchr(cp, '.');
                    936:        *pp++ = ++cp;
                    937:     }
                    938:     *pp = 0;
                    939:     _res.options |= RES_INIT;
                    940: }
                    941: 
                    942: #define SRCHLIST_SEP '/'
                    943: 
                    944: res_dnsrch(cp)
                    945:     register char *cp;
                    946: {
                    947:     register char **pp;
                    948:     int n;
                    949: 
                    950:     (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
                    951:     if ((cp = strchr(_res.defdname, '\n')) != NULL)
                    952:            *cp = '\0';
                    953:     /*
                    954:      * Set search list to be blank-separated strings
                    955:      * on rest of line.
                    956:      */
                    957:     cp = _res.defdname;
                    958:     pp = _res.dnsrch;
                    959:     *pp++ = cp;
                    960:     for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
                    961:            if (*cp == SRCHLIST_SEP) {
                    962:                    *cp = '\0';
                    963:                    n = 1;
                    964:            } else if (n) {
                    965:                    *pp++ = cp;
                    966:                    n = 0;
                    967:            }
                    968:     }
                    969:     if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) {
                    970:        *cp = '\0';
                    971:     }
                    972:     *pp = NULL;
                    973: }
                    974: 
                    975: 
                    976: /*
                    977:  *******************************************************************************
                    978:  *
                    979:  *  ShowOptions --
                    980:  *
                    981:  *     Prints out the state information used by the resolver
                    982:  *     library and other options set by the user.
                    983:  *
                    984:  *******************************************************************************
                    985:  */
                    986: 
                    987: void
                    988: ShowOptions()
                    989: {
                    990:     register char **cp;
                    991: 
                    992:     PrintHostInfo(stdout, "Default Server:", defaultPtr);
                    993:     if (curHostValid) {
                    994:        PrintHostInfo(stdout, "Host:", &curHostInfo);
                    995:     }
                    996: 
                    997:     printf("Set options:\n");
                    998:     printf("  %sdebug  \t", (_res.options & RES_DEBUG) ? "" : "no");
                    999:     printf("  %sdefname\t", (_res.options & RES_DEFNAMES) ? "" : "no");
                   1000:     printf("  %ssearch\t", (_res.options & RES_DNSRCH) ? "" : "no");
                   1001:     printf("  %srecurse\n", (_res.options & RES_RECURSE) ? "" : "no");
                   1002: 
                   1003:     printf("  %sd2\t\t", (_res.options & RES_DEBUG2) ? "" : "no");
                   1004:     printf("  %svc\t\t", (_res.options & RES_USEVC) ? "" : "no");
                   1005:     printf("  %signoretc\t", (_res.options & RES_IGNTC) ? "" : "no");
                   1006:     printf("  port=%u\n", nsport);
                   1007: 
                   1008:     printf("  querytype=%s\t", p_type(queryType));
                   1009:     printf("  class=%s\t", p_class(queryClass));
                   1010:     printf("  timeout=%d\t", _res.retrans);
                   1011:     printf("  retry=%d\n", _res.retry);
                   1012:     printf("  root=%s\n", rootServerName);
                   1013:     printf("  domain=%s\n", _res.defdname);
                   1014:     
                   1015:     if (cp = _res.dnsrch) {
                   1016:        printf("  srchlist=%s", *cp);
                   1017:        for (cp++; *cp; cp++) {
                   1018:            printf("%c%s", SRCHLIST_SEP, *cp);
                   1019:        }
                   1020:        putchar('\n');
                   1021:     }
                   1022:     putchar('\n');
                   1023: }
                   1024: #undef SRCHLIST_SEP
                   1025: 
                   1026: /*
                   1027:  *******************************************************************************
                   1028:  *
                   1029:  *  PrintHelp --
                   1030:  *
                   1031:  *     Prints out the help file.
                   1032:  *     (Code taken from Mail.)
                   1033:  *
                   1034:  *******************************************************************************
                   1035:  */
                   1036: 
                   1037: void
                   1038: PrintHelp()
                   1039: {
                   1040:        register int c;
                   1041:        register FILE *helpFilePtr;
                   1042: 
                   1043:        if ((helpFilePtr = fopen(_PATH_HELPFILE, "r")) == NULL) {
                   1044:            perror(_PATH_HELPFILE);
                   1045:            return;
                   1046:        } 
                   1047:        while ((c = getc(helpFilePtr)) != EOF) {
                   1048:            putchar((char) c);
                   1049:        }
                   1050:        fclose(helpFilePtr);
                   1051: }
                   1052: 
                   1053: /*
                   1054:  *******************************************************************************
                   1055:  *
                   1056:  * CvtAddrToPtr --
                   1057:  *
                   1058:  *     Convert a dotted-decimal Internet address into the standard
                   1059:  *     PTR format (reversed address with .in-arpa. suffix).
                   1060:  *
                   1061:  *     Assumes the argument buffer is large enougth to hold the result.
                   1062:  *
                   1063:  *******************************************************************************
                   1064:  */
                   1065: 
                   1066: static void
                   1067: CvtAddrToPtr(name)
                   1068:     char *name;
                   1069: {
                   1070:     char *p;
                   1071:     int ip[4];
                   1072:     struct in_addr addr;
                   1073: 
                   1074:     if (IsAddr(name, &addr.s_addr)) {
                   1075:        p = inet_ntoa(addr);
                   1076:        if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) {
                   1077:            sprintf(name, "%d.%d.%d.%d.in-addr.arpa.", 
                   1078:                ip[3], ip[2], ip[1], ip[0]);
                   1079:        }
                   1080:     }
                   1081: }
                   1082: 
                   1083: /*
                   1084:  *******************************************************************************
                   1085:  *
                   1086:  * ReadRC --
                   1087:  *
                   1088:  *     Use the contents of ~/.nslookuprc as options.
                   1089:  *
                   1090:  *******************************************************************************
                   1091:  */
                   1092: 
                   1093: static void
                   1094: ReadRC()
                   1095: {
                   1096:     register FILE *fp;
                   1097:     register char *cp;
                   1098:     char buf[NAME_LEN];
                   1099: 
                   1100:     if ((cp = getenv("HOME")) != NULL) {
                   1101:        (void) strcpy(buf, cp);
                   1102:        (void) strcat(buf, "/.nslookuprc");
                   1103: 
                   1104:        if ((fp = fopen(buf, "r")) != NULL) {
                   1105:            while (fgets(buf, sizeof(buf), fp) != NULL) {
                   1106:                if ((cp = strchr(buf, '\n')) != NULL) {
                   1107:                    *cp = '\0';
                   1108:                }
                   1109:                (void) SetOption(buf);
                   1110:            }
                   1111:            (void) fclose(fp);
                   1112:        }
                   1113:     }
                   1114: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.