# 2.11BSD#431 - /usr/src/usr.sbin/named/tools/nslookup/main.c

##### Functions

    IsAddr            X
    LocalServer       X
    LookupHost        X
    LookupHostWithServerX
    PrintHelp         X
    SetDefaultServer  X
    SetOption         X
    ShowOptions       X
    Usage             X
    main              X
    res_dnsrch        X
    res_re_init       X

##### Variables

    copyright         X
    curHostValid      X
    defaultAddr       X
    defaultServer     X
    env               X
    queryClass        X
    queryType         X
    rootServerName    X

##### Macros

    LOCALHOST         X
    ROOT_SERVER       X
    SRCHLIST_SEP      X

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

#### Defined functions

CvtAddrToPtr defined in line 1063; used 2 times

- in line 121, 583

DoLookup defined in line 545; used 2 times

- in line 679, 750

IsAddr defined in line 390; used 5 times

- in line 501, 579, 1071
- in /usr/src/usr.sbin/named/tools/nslookup/getinfo.c line 528
- in /usr/src/usr.sbin/named/tools/nslookup/res.h line 124

LocalServer defined in line 322; used 2 times

- in line 238-242(2)

LookupHost defined in line 643; used 1 times

- in line 289

LookupHostWithServer defined in line 713; never used
PrintHelp defined in line 1034; never used
ReadRC defined in line 1090; used 2 times

- in line 122, 185

SetDefaultServer defined in line 444; never used
SetOption defined in line 800; used 2 times

- in line 190, 1106

ShowOptions defined in line 984; used 3 times

- in line 820-822(2)
- in /usr/src/usr.sbin/named/tools/nslookup/res.h line 136

Usage defined in line 362; used 1 times

- in line 194

main defined in line 137; never used
res_dnsrch defined in line 941; used 1 times

- in line 894

res_re_init defined in line 919; used 1 times

- in line 836

#### Defined variables

copyright defined in line 21; never used
curHostValid defined in line 90; used 5 times

- in line 598, 657, 724, 990
- in /usr/src/usr.sbin/named/tools/nslookup/list.c line 828

defaultAddr defined in line 99; used 6 times

- in line 254, 333-334(2), 343-344(2), 493

defaultServer defined in line 98; used 4 times

- in line 271, 339, 519, 679

env defined in line 119; used 1 times

- in line 297

queryClass defined in line 107; used 6 times

- in line 585, 868(2), 1006
- in /usr/src/usr.sbin/named/tools/nslookup/list.c line 224, 600

queryType defined in line 106; used 10 times

- in line 579-585(3), 597, 613(2), 862(2), 1005
- in /usr/src/usr.sbin/named/tools/nslookup/list.c line 136

rootServerName defined in line 75; used 2 times

- in line 885, 1009

sccsid defined in line 25; never used

#### Defined macros

LOCALHOST defined in line 63; used 1 times

- in line 333

ROOT_SERVER defined in line 73; used 2 times

- in line 72-75(2)

SRCHLIST_SEP defined in line 939; used 4 times

- in line 958, 966, 1015, 1021

Last modified: 1993-04-26 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3216 |