📄 list.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 lintstatic char sccsid[] = "@(#)list.c 5.23 (Berkeley) 3/21/91";static char rcsid[] = "$Id: list.c,v 8.9 1996/11/26 10:11:26 vixie Exp $";#endif /* not lint *//* ******************************************************************************* * * list.c -- * * Routines to obtain info from name and finger servers. * * Adapted from 4.3BSD BIND ns_init.c and from finger.c. * ******************************************************************************* */#ifndef WINNT#include <sys/param.h>#include <sys/socket.h>#include <netinet/in.h>#endif#include <nameser.h>#include <inet.h>#include <resolv.h>#include <netdb.h>#include <stdio.h>#include <limits.h>#include <ctype.h>#include <errno.h>#include "res.h"#include "portability.h"extern char *_res_resultcodes[]; /* res_debug.c */extern char *pager;typedef union { HEADER qb1; u_char qb2[PACKETSZ];} querybuf;extern HostInfo *defaultPtr;extern HostInfo curHostInfo;extern int curHostValid;extern int queryType;extern int queryClass;char * inet_nsap_ntoa();const char * inet_ntop();/* * Forward references */intPrintListInfo(FILE *file, u_char *msg, u_char *eom, int qtype, char *domain);static int sockFD = -1;int ListSubr();/* * During a listing to a file, hash marks are printed * every HASH_SIZE records. */#define HASH_SIZE 50/* ******************************************************************************* * * ListHosts -- * ListHostsByType -- * * Requests the name server to do a zone transfer so we * find out what hosts it knows about. * * For ListHosts, there are five types of output: * - Internet addresses (default) * - cpu type and operating system (-h option) * - canonical and alias names (-a option) * - well-known service names (-s option) * - ALL records (-d option) * ListHostsByType prints records of the default type or of a speicific * type. * * To see all types of information sorted by name, do the following: * ls -d domain.edu > file * view file * * Results: * SUCCESS the listing was successful. * ERROR the server could not be contacted because * a socket could not be obtained or an error * occured while receiving, or the output file * could not be opened. * ******************************************************************************* */voidListHostsByType(string, putToFile) char *string; int putToFile;{ int i, qtype, result; char *namePtr; char name[NAME_LEN]; char option[NAME_LEN]; /* * Parse the command line. It maybe of the form "ls -t domain" * or "ls -t type domain". */ i = sscanf(string, " ls -t %s %s", option, name); if (putToFile && i == 2 && name[0] == '>') { i--; } if (i == 2) { qtype = StringToType(option, -1, stderr); if (qtype == -1) return; namePtr = name; } else if (i == 1) { namePtr = option; qtype = queryType; } else {#ifndef GUI fprintf(stderr, "*** ls: invalid request %s\n",string);#else fprintf(outputfile, "*** ls: invalid request %s\n",string);#endif return; } result = ListSubr(qtype, namePtr, putToFile ? string : NULL); if (result != SUCCESS)#ifndef GUI fprintf(stderr, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result));#else fprintf(outputfile, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result));#endif}voidListHosts(string, putToFile) char *string; int putToFile;{ int i, qtype, result; char *namePtr; char name[NAME_LEN]; char option[NAME_LEN]; /* * Parse the command line. It maybe of the form "ls domain", * "ls -X domain". */ i = sscanf(string, " ls %s %s", option, name); if (putToFile && i == 2 && name[0] == '>') { i--; } if (i == 2) { if (strcmp("-a", option) == 0) { qtype = T_CNAME; } else if (strcmp("-h", option) == 0) { qtype = T_HINFO; } else if (strcmp("-m", option) == 0) { qtype = T_MX; } else if (strcmp("-p", option) == 0) { qtype = T_PX; } else if (strcmp("-s", option) == 0) { qtype = T_WKS; } else if (strcmp("-d", option) == 0) { qtype = T_ANY; } else if (strcmp("-n", option) == 0) { qtype = T_NAPTR; } else { qtype = T_A; } namePtr = name; } else if (i == 1) { namePtr = option; qtype = T_A; } else {#ifndef GUI fprintf(stderr, "*** ls: invalid request %s\n",string);#else fprintf(outputfile, "*** ls: invalid request %s\n",string);#endif return; } result = ListSubr(qtype, namePtr, putToFile ? string : NULL); if (result != SUCCESS)#ifndef GUI fprintf(stderr, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result));#else fprintf(outputfile, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result));#endif}intListSubr(qtype, domain, cmd) int qtype; char *domain; char *cmd;{ querybuf buf; struct sockaddr_in sin; HEADER *headerPtr; int msglen; int amtToRead; int numRead, n; int numAnswers = 0; int numRecords = 0; int result; int soacnt = 0; int count, done; u_short len; u_char *cp; char dname[2][NAME_LEN]; char file[NAME_LEN]; static u_char *answer = NULL; static int answerLen = 0; enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } error = NO_ERRORS; /* * Create a query packet for the requested domain name. */ msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR, NULL, 0, 0, buf.qb2, sizeof buf); if (msglen < 0) { if (_res.options & RES_DEBUG) {#ifndef GUI fprintf(stderr, "*** ls: res_mkquery failed\n");#else fprintf(outputfile, "*** ls: res_mkquery failed\n");#endif } return (ERROR); } bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(nsport); /* * Check to see if we have the address of the server or the * address of a server who knows about this domain. * * For now, just use the first address in the list. */ if (defaultPtr->addrList != NULL) { sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0]; } else { sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0]; } /* * Set up a virtual circuit to the server. */ if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("ls: socket"); return(ERROR); } if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) < 0) { int e; if (errno == ECONNREFUSED) { e = NO_RESPONSE; } else { perror("ls: connect"); e = ERROR; } (void) close(sockFD); sockFD = -1; return e; } /* * Send length & message for zone transfer */ __putshort(msglen, (u_char *)&len); #ifndef WINNT if (write(sockFD, (char *)&len, INT16SZ) != INT16SZ || write(sockFD, (char *) &buf, msglen) != msglen) { #else if (send(sockFD,(const char *)&len,INT16SZ,0) != INT16SZ || send(sockFD,(const char *)&buf,msglen,0) != msglen) { #endif perror("ls: write"); (void) close(sockFD); sockFD = -1; return(ERROR); }#ifndef GUI fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name);#else fprintf(outputfile,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name);#endif if (cmd == NULL) {#ifndef GUI filePtr = stdout;#else filePtr = outputfile;#endif } else { filePtr = AppOpenFile(cmd, file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); (void) close(sockFD); sockFD = -1; return(ERROR); } fprintf(filePtr, "> %s\n", cmd); fprintf(filePtr,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name); } dname[0][0] = '\0'; for (done = 0; !done; NULL) { unsigned short tmp; /* * Read the length of the response. */ cp = (u_char *)&tmp; amtToRead = INT16SZ;#ifndef WINNT while ((numRead = read(sockFD, cp, amtToRead)) > 0) {#else while ((numRead = recv(sockFD, cp, amtToRead,0)) > 0) {#endif cp += numRead; if ((amtToRead -= numRead) <= 0) break; } if (numRead <= 0) { error = ERR_READING_LEN; break; } if ((len = _getshort((u_char*)&tmp)) == 0) { break; /* nothing left to read */ } /* * The server sent too much data to fit the existing buffer -- * allocate a new one. */ if (len > (u_int)answerLen) { if (answerLen != 0) { free(answer); } answerLen = len; answer = (u_char *)Malloc(answerLen); } /* * Read the response. */ amtToRead = len; cp = answer; #ifndef WINNT while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {#else while (amtToRead > 0 && (numRead=recv(sockFD, cp, amtToRead,0)) > 0) {#endif cp += numRead; amtToRead -= numRead; } if (numRead <= 0) { error = ERR_READING_MSG; break; } result = PrintListInfo(filePtr, answer, cp, qtype, dname[0]); if (result != SUCCESS) { error = ERR_PRINTING; break; } numRecords += htons((u_short)((HEADER *)answer)->ancount); numAnswers++; if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) { fprintf(stdout, "#"); fflush(stdout); } /* Header. */ cp = answer + HFIXEDSZ; /* Question. */ for (count = ntohs((u_short)((HEADER* )answer)->qdcount); count > 0; count--) cp += dn_skipname((u_char *)cp, (u_char *)answer + len) + QFIXEDSZ; /* Answer. */ for (count = ntohs((u_short)((HEADER* )answer)->ancount); count > 0; count--) { int type, class, rlen; n = dn_expand(answer, answer + len, cp, dname[soacnt], sizeof dname[0]); if (n < 0) { error = ERR_PRINTING; done++; break; } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); cp += INT32SZ; /* ttl */ GETSHORT(rlen, cp); cp += rlen; if (type == T_SOA && soacnt++ && !strcasecmp(dname[0], dname[1])) { done++; break; } } } if (cmd != NULL) { fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n", (numAnswers >= HASH_SIZE) ? "\n" : "", numAnswers, (numAnswers != 1) ? "s" : "", numRecords, (numRecords != 1) ? "s" : ""); } (void) close(sockFD); sockFD = -1; if (cmd != NULL && filePtr != NULL) { fclose(filePtr); filePtr = NULL; } switch (error) { case NO_ERRORS: return (SUCCESS); case ERR_READING_LEN: return(ERROR); case ERR_PRINTING: return(result); case ERR_READING_MSG: headerPtr = (HEADER *) answer;#ifndef GUI fprintf(stderr,"*** ls: error receiving zone transfer:\n"); fprintf(stderr, " result: %s, answers = %d, authority = %d, additional = %d\n", _res_resultcodes[headerPtr->rcode], ntohs( (u_short) headerPtr->ancount), ntohs( (u_short) headerPtr->nscount), ntohs( (u_short) headerPtr->arcount));#else fprintf(outputfile,"*** ls: error receiving zone transfer:\n"); fprintf(outputfile, " result: %s, answers = %d, authority = %d, additional = %d\n", _res_resultcodes[headerPtr->rcode], ntohs( (u_short) headerPtr->ancount), ntohs( (u_short) headerPtr->nscount), ntohs( (u_short) headerPtr->arcount));#endif return(ERROR); default: return(ERROR); }}/* ******************************************************************************* * * PrintListInfo -- * * Used by the ListInfo routine to print the answer * received from the name server. Only the desired * information is printed. * * Results: * SUCCESS the answer was printed without a problem. * NO_INFO the answer packet did not contain an answer. * ERROR the answer was malformed. * Misc. errors returned in the packet header. * ******************************************************************************* */#define NAME_FORMAT " %-30s"static Booleanstrip_domain(string, domain) char *string, *domain;{ register char *dot; if (*domain != '\0') { dot = string; while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot)) ; if (dot != NULL) { dot[-1] = '\0'; return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -