|
|
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.