📄 main.c
字号:
/* * ++Copyright++ 1985, 1989 * - * Copyright (c) 1985, 1989 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)main.c 5.42 (Berkeley) 3/3/91";static char rcsid[] = "$Id: main.c,v 4.9.1.3 1993/09/16 09:02:07 vixie Exp $";#endif /* not lint *//* ****************************************************************************** * * main.c -- * * Main routine and some action routines for the name server * lookup program. * * Andrew Cherenson * U.C. Berkeley Computer Science Div. * CS298-26, Fall 1985 * ****************************************************************************** */#include <sys/param.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <arpa/inet.h>#include <resolv.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>#include <stdio.h>#include <errno.h>#include <limits.h>#include "res.h"#include "pathnames.h"#include "../../conf/portability.h"/* * Name of a top-level name server. Can be changed with * the "set root" command. */#ifndef ROOT_SERVER#define ROOT_SERVER "ns.internic.net."#endifchar rootServerName[NAME_LEN] = ROOT_SERVER;/* * Import the state information from the resolver library. */extern struct __res_state _res;/* * Info about the most recently queried host. */HostInfo curHostInfo;int curHostValid = FALSE;/* * Info about the default name server. */HostInfo *defaultPtr = NULL;char defaultServer[NAME_LEN];struct in_addr defaultAddr;/* * Initial name server query type is Address. */int queryType = T_A;int queryClass = C_IN;/* * Stuff for Interrupt (control-C) signal handler. */extern SIG_FN IntrHandler();FILE *filePtr;jmp_buf env;/* * Browser command for help and view. */char *pager;static void CvtAddrToPtr();static void ReadRC();/* ****************************************************************************** * * main -- * * Initializes the resolver library and determines the address * of the initial name server. The yylex routine is used to * read and perform commands. * ****************************************************************************** */main(argc, argv) int argc; char **argv;{ char *wantedHost = NULL; Boolean useLocalServer; int result; int i; struct hostent *hp; /* * Initialize the resolver library routines. */ if (res_init() == -1) { fprintf(stderr,"*** Can't initialize resolver.\n"); exit(1); } /* * Allocate space for the default server's host info and * find the server's address and name. If the resolver library * already has some addresses for a potential name server, * then use them. Otherwise, see if the current host has a server. * Command line arguments may override the choice of initial server. */ defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); /* * Parse the arguments: * no args = go into interactive mode, use default host as server * 1 arg = use as host name to be looked up, default host will be server * non-interactive mode * 2 args = 1st arg: * if it is '-', then * ignore but go into interactive mode * else * use as host name to be looked up, * go into non-interactive mode * 2nd arg: name or inet address of server * * "Set" options are specified with a leading - and must come before * any arguments. For example, to find the well-known services for * a host, type "nslookup -query=wks host" */ ReadRC(); /* look for options file */ ++argv; --argc; /* skip prog name */ while (argc && *argv[0] == '-' && argv[0][1]) { (void) SetOption (&(argv[0][1])); ++argv; --argc; } if (argc > 2) { Usage(); } if (argc && *argv[0] != '-') { wantedHost = *argv; /* name of host to be looked up */ } useLocalServer = FALSE; if (argc == 2) { struct in_addr addr; /* * Use an explicit name server. If the hostname lookup fails, * default to the server(s) in resolv.conf. */ if (inet_aton(*++argv, &addr)) { _res.nscount = 1; _res.nsaddr.sin_addr = addr; } else { hp = gethostbyname(*argv); if (hp == NULL) { fprintf(stderr, "*** Can't find server address for '%s': ", *argv); herror((char *)NULL); fputc('\n', stderr); } else { for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) { bcopy(hp->h_addr_list[i], (char *)&_res.nsaddr_list[i].sin_addr, hp->h_length); } _res.nscount = i; } } } if (_res.nscount == 0 || useLocalServer) { LocalServer(defaultPtr); } else { for (i = 0; i < _res.nscount; i++) { if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { LocalServer(defaultPtr); break; } else { result = GetHostInfoByAddr(&(_res.nsaddr_list[i].sin_addr), &(_res.nsaddr_list[i].sin_addr), defaultPtr); if (result != SUCCESS) { fprintf(stderr, "*** Can't find server name for address %s: %s\n", inet_ntoa(_res.nsaddr_list[i].sin_addr), DecodeError(result)); } else { defaultAddr = _res.nsaddr_list[i].sin_addr; break; } } } /* * If we have exhausted the list, tell the user about the * command line argument to specify an address. */ if (i == _res.nscount) { fprintf(stderr, "*** Default servers are not available\n"); exit(1); } } strcpy(defaultServer, defaultPtr->name);#ifdef DEBUG#ifdef DEBUG2 _res.options |= RES_DEBUG2;#endif _res.options |= RES_DEBUG; _res.retry = 2;#endif /* DEBUG */ /* * If we're in non-interactive mode, look up the wanted host and quit. * Otherwise, print the initial server's name and continue with * the initialization. */ if (wantedHost != (char *) NULL) { LookupHost(wantedHost, 0); } else { PrintHostInfo(stdout, "Default Server:", defaultPtr); pager = getenv("PAGER"); if (pager == NULL) { pager = _PATH_PAGERCMD; } /* * Setup the environment to allow the interrupt handler to return here. */ (void) setjmp(env); /* * Return here after a longjmp. */ signal(SIGINT, IntrHandler); signal(SIGPIPE, SIG_IGN); /* * Read and evaluate commands. The commands are described in commands.l * Yylex returns 0 when ^D or 'exit' is typed. */ printf("> "); fflush(stdout); while(yylex()) { printf("> "); fflush(stdout); } } exit(0);}LocalServer(defaultPtr) HostInfo *defaultPtr;{ char hostName[NAME_LEN]; (void) gethostname(hostName, sizeof(hostName)); defaultAddr.s_addr = htonl(INADDR_ANY); (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1); free(defaultPtr->name); defaultPtr->name = Calloc(1, sizeof(hostName)+1); strcpy(defaultPtr->name, hostName);}/* ****************************************************************************** * * Usage -- * * Lists the proper methods to run the program and exits. * ****************************************************************************** */Usage(){ fprintf(stderr, "Usage:\n"); fprintf(stderr," nslookup [-opt ...] # interactive mode using default server\n"); fprintf(stderr," nslookup [-opt ...] - server # interactive mode using 'server'\n"); fprintf(stderr," nslookup [-opt ...] host # just look up 'host' using default server\n"); fprintf(stderr," nslookup [-opt ...] host server # just look up 'host' using 'server'\n"); exit(1);}/* ****************************************************************************** * * IsAddr -- * * Returns TRUE if the string looks like an Internet address. * A string with a trailing dot is not an address, even if it looks * like one. * ****************************************************************************** */BooleanIsAddr(host, addrPtr) char *host; struct in_addr *addrPtr; /* If return TRUE, contains IP address */{ register char *cp; if (isdigit(host[0])) { /* Make sure it has only digits and dots. */ for (cp = host; *cp; ++cp) { if (!isdigit(*cp) && *cp != '.') return FALSE; } /* If it has a trailing dot, don't treat it as an address. */ if (*--cp != '.') { return inet_aton(host, addrPtr); } } return FALSE;}/* ****************************************************************************** * * SetDefaultServer -- * * Changes the default name server to the one specified by * the first argument. The command "server name" uses the current * default server to lookup the info for "name". The command * "lserver name" uses the original server to lookup "name". * * Side effects: * This routine will cause a core dump if the allocation requests fail. * * Results: * SUCCESS The default server was changed successfully. * NONAUTH The server was changed but addresses of * other servers who know about the requested server * were returned. * Errors No info about the new server was found or * requests to the current server timed-out. * ****************************************************************************** */intSetDefaultServer(string, local) char *string; Boolean local;{ register HostInfo *newDefPtr; struct in_addr *servAddrPtr; struct in_addr addr; char newServer[NAME_LEN]; int result; int i; /* * Parse the command line. It maybe of the form "server name", * "lserver name" or just "name". */ if (local) { i = sscanf(string, " lserver %s", newServer); } else { i = sscanf(string, " server %s", newServer); } if (i != 1) { i = sscanf(string, " %s", newServer); if (i != 1) { fprintf(stderr,"SetDefaultServer: invalid name: %s\n", string); return(ERROR); } } /* * Allocate space for a HostInfo variable for the new server. Don't * overwrite the old HostInfo struct because info about the new server * might not be found and we need to have valid default server info. */ newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); /* * A 'local' lookup uses the original server that the program was * initialized with. * * Check to see if we have the address of the server or the * address of a server who knows about this domain. * XXX For now, just use the first address in the list. */ if (local) { servAddrPtr = &defaultAddr; } else if (defaultPtr->addrList != NULL) { servAddrPtr = (struct in_addr *) defaultPtr->addrList[0]; } else { servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0]; } result = ERROR; if (IsAddr(newServer, &addr)) { result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr); /* If we can't get the name, fall through... */ } if (result != SUCCESS && result != NONAUTH) { result = GetHostInfoByName(servAddrPtr, C_IN, T_A, newServer, newDefPtr, 1); } if (result == SUCCESS || result == NONAUTH) { /* * Found info about the new server. Free the resources for * the old server. */ FreeHostInfoPtr(defaultPtr); free((char *)defaultPtr); defaultPtr = newDefPtr; strcpy(defaultServer, defaultPtr->name); PrintHostInfo(stdout, "Default Server:", defaultPtr); return(SUCCESS); } else { fprintf(stderr, "*** Can't find address for server %s: %s\n", newServer, DecodeError(result)); free((char *)newDefPtr); return(result); }}/* ****************************************************************************** * * DoLoookup -- * * Common subroutine for LookupHost and LookupHostWithServer. * * Results: * SUCCESS - the lookup was successful. * Misc. Errors - an error message is printed if the lookup failed. * ****************************************************************************** */static intDoLookup(host, servPtr, serverName) char *host; HostInfo *servPtr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -