|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.