1: /*
   2:  *******************************************************************************
   3:  *
   4:  *  list.c --
   5:  *
   6:  *	Routines to obtain info from name and finger servers.
   7:  *
   8:  *	Adapted from 4.3BSD BIND ns_init.c and from /usr/src/ucb/finger.c
   9:  *
  10:  *	Copyright (c) 1985 Regents of the University of California.
  11:  *	All rights reserved.  The Berkeley software License Agreement
  12:  *	specifies the terms and conditions for redistribution.
  13:  *
  14:  *******************************************************************************
  15:  */
  16: 
  17: #ifndef lint
  18: static char sccsid[] = "@(#)list.c	5.4 (Berkeley) 4/10/86";
  19: #endif not lint
  20: 
  21: #include <sys/types.h>
  22: #include <sys/socket.h>
  23: #include <netinet/in.h>
  24: #include <netdb.h>
  25: #include <stdio.h>
  26: #include <strings.h>
  27: #include <ctype.h>
  28: #include <arpa/nameser.h>
  29: #include <resolv.h>
  30: #include "res.h"
  31: 
  32: /*
  33:  *  Imported from res_debug.c
  34:  */
  35: extern char *rcodes[];
  36: 
  37: typedef union {
  38:     HEADER qb1;
  39:     char qb2[PACKETSZ];
  40: } querybuf;
  41: 
  42: extern u_long       inet_addr();
  43: extern HostInfo     *defaultPtr;
  44: extern HostInfo     curHostInfo;
  45: extern int      curHostValid;
  46: 
  47: /*
  48:  *  During a listing to a file, hash marks are printed
  49:  *  every HASH_SIZE records.
  50:  */
  51: 
  52: #define HASH_SIZE 50
  53: 
  54: 
  55: /*
  56:  *******************************************************************************
  57:  *
  58:  *  ListHosts --
  59:  *
  60:  *	Requests the name server to do a zone transfer so we
  61:  *	find out what hosts it knows about.
  62:  *
  63:  *	There are three types of output:
  64:  *	- internet addresses (default)
  65:  *	- cpu type and operating system (-h option)
  66:  *	- canonical and alias names  (-a option)
  67:  *
  68:  *	To see all three types of information in sorted order,
  69:  *	do the following:
  70:  *	  ls domain.edu > file
  71:  *	  ls -a domain.edu >> file
  72:  *	  ls -h domain.edu >> file
  73:  *	  view file
  74:  *
  75:  *  Results:
  76:  *	SUCCESS		the listing was successful.
  77:  *	ERROR		the server could not be contacted because
  78:  *			a socket could not be obtained or an error
  79:  *			occured while receiving, or the output file
  80:  *			could not be opened.
  81:  *
  82:  *******************************************************************************
  83:  */
  84: 
  85: int
  86: ListHosts(string, putToFile)
  87:     char *string;
  88:     int  putToFile;
  89: {
  90:     querybuf        buf;
  91:     struct sockaddr_in  sin;
  92:     HEADER          *headerPtr;
  93:     int             queryType;
  94:     int             msglen;
  95:     int             amtToRead;
  96:     int             numRead;
  97:     int             i;
  98:     int             numAnswers = 0;
  99:     int             result;
 100:     int             soacnt = 0;
 101:     u_short         len;
 102:     char            *cp;
 103:     char            name[NAME_LEN];
 104:     char            option[NAME_LEN];
 105:     char            file[NAME_LEN];
 106:     char            *namePtr;
 107:     enum {
 108:         NO_ERRORS,
 109:         ERR_READING_LEN,
 110:         ERR_READING_MSG,
 111:         ERR_PRINTING,
 112:     } error = NO_ERRORS;
 113: 
 114: 
 115:     /*
 116: 	 *
 117:     /*
 118:      *  Parse the command line. It maybe of the form "ls domain",
 119:      *  "ls -a domain" or "ls -h domain".
 120:      */
 121:     i = sscanf(string, " ls %s %s", option, name);
 122:     if (putToFile && i == 2 && name[0] == '>') {
 123:         i--;
 124:     }
 125:     if (i == 2) {
 126:         if (strcmp("-a", option) == 0) {
 127:         queryType = T_CNAME;
 128:         } else if (strcmp("-h", option) == 0) {
 129:         queryType = T_HINFO;
 130:         } else if (strcmp("-m", option) == 0) {
 131:         queryType = T_MX;
 132:         } else {
 133:         queryType = T_A;
 134:         }
 135:         namePtr = name;
 136:     } else if (i == 1) {
 137:         namePtr = option;
 138:         queryType = T_A;
 139:     } else {
 140:         fprintf(stderr, "ListHosts: invalid request %s\n",string);
 141:         return(ERROR);
 142:     }
 143: 
 144: 
 145:     /*
 146: 	 *  Create a query packet for the requested domain name.
 147: 	 *
 148: 	 */
 149:     msglen = res_mkquery(QUERY, namePtr, C_IN, T_AXFR,
 150:                 (char *)0, 0, (char *)0,
 151:                 (char *) &buf, sizeof(buf));
 152:     if (msglen < 0) {
 153:         if (_res.options & RES_DEBUG) {
 154:         fprintf(stderr, "ListHosts: Res_mkquery failed\n");
 155:         }
 156:         return (ERROR);
 157:     }
 158: 
 159:     bzero((char *)&sin, sizeof(sin));
 160:     sin.sin_family  = AF_INET;
 161:     sin.sin_port    =  htons(NAMESERVER_PORT);
 162: 
 163:     /*
 164: 	 *  Check to see if we have the address of the server or the
 165: 	 *  address of a server who knows about this domain.
 166: 	 *
 167: 	 *  For now, just use the first address in the list.
 168: 	 */
 169: 
 170:     if (defaultPtr->addrList != NULL) {
 171:       sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
 172:     } else {
 173:       sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
 174:     }
 175: 
 176:     /*
 177: 	 *  Set up a virtual circuit to the server.
 178: 	 */
 179:     if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 180:         perror("ListHosts");
 181:         return(ERROR);
 182:     }
 183:     if (connect(sockFD, &sin, sizeof(sin)) < 0) {
 184:         perror("ListHosts");
 185:         (void) close(sockFD);
 186:         sockFD = -1;
 187:         return(ERROR);
 188:     }
 189: 
 190:     /*
 191: 	 * Send length & message for zone transfer
 192: 	 */
 193: 
 194:         len = htons(msglen);
 195: 
 196:         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
 197:             write(sockFD, (char *) &buf, msglen) != msglen) {
 198:         perror("ListHosts");
 199:         (void) close(sockFD);
 200:         sockFD = -1;
 201:         return(ERROR);
 202:     }
 203: 
 204:     fprintf(stdout,"[%s]\n",
 205:         (defaultPtr->addrList != NULL) ? defaultPtr->name :
 206:          defaultPtr->servers[0]->name);
 207: 
 208:     if (!putToFile) {
 209:         filePtr = stdout;
 210:     } else {
 211:         filePtr = OpenFile(string, file);
 212:             if (filePtr == NULL) {
 213:                 fprintf(stderr, "*** Can't open %s for writing\n", file);
 214:         (void) close(sockFD);
 215:         sockFD = -1;
 216:                 return(ERROR);
 217:             }
 218:         fprintf(filePtr, "> %s\n", string);
 219:         fprintf(filePtr,"[%s]\n",
 220:         (defaultPtr->addrList != NULL) ? defaultPtr->name :
 221:          defaultPtr->servers[0]->name);
 222:     }
 223: 
 224:     fprintf(filePtr, "%-30s", "Host or domain name");
 225:     switch(queryType) {
 226:         case T_A:
 227:             fprintf(filePtr, " %-30s\n", "Internet address");
 228:             break;
 229:         case T_HINFO:
 230:             fprintf(filePtr, " %-20s %s\n", "CPU", "OS");
 231:             break;
 232:         case T_CNAME:
 233:             fprintf(filePtr, " %-30s\n", "Alias");
 234:             break;
 235:         case T_MX:
 236:             fprintf(filePtr, " %10s %s\n", "Metric", "Host");
 237:     }
 238: 
 239: 
 240:     while (1) {
 241: 
 242:         /*
 243: 	     * Read the length of the response.
 244: 	     */
 245: 
 246:         cp = (char *) &buf;
 247:         amtToRead = sizeof(u_short);
 248:         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
 249:         cp    += numRead;
 250:         amtToRead -= numRead;
 251:         }
 252:         if (numRead <= 0) {
 253:         error = ERR_READING_LEN;
 254:         break;
 255:         }
 256: 
 257:         if ((len = htons(*(u_short *)&buf)) == 0) {
 258:         break;  /* nothing left to read */
 259:         }
 260: 
 261:         /*
 262: 	     * Read the response.
 263: 	     */
 264: 
 265:         amtToRead = len;
 266:         cp = (char *) &buf;
 267:         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
 268:         cp += numRead;
 269:         amtToRead -= numRead;
 270:         }
 271:         if (numRead <= 0) {
 272:         error = ERR_READING_MSG;
 273:         break;
 274:         }
 275: 
 276:         result = PrintListInfo(filePtr, (char *) &buf, cp, queryType);
 277:         if (result != SUCCESS) {
 278:         error = ERR_PRINTING;
 279:         break;
 280:         }
 281: 
 282:         numAnswers++;
 283:         if (putToFile && ((numAnswers % HASH_SIZE) == 0)) {
 284:         fprintf(stdout, "#");
 285:         fflush(stdout);
 286:         }
 287:         cp = buf.qb2 + sizeof(HEADER);
 288:         cp += dn_skip(cp) + QFIXEDSZ;
 289:         cp += dn_skip(cp);
 290:         if ((getshort(cp) == T_SOA)) {
 291:             if (soacnt)
 292:             break;
 293:         else
 294:             soacnt++;
 295:         }
 296:     }
 297: 
 298:     if (putToFile) {
 299:         fprintf(stdout, "%sReceived %d record%s.\n",
 300:         (numAnswers >= HASH_SIZE) ? "\n" : "",
 301:         numAnswers,
 302:         (numAnswers > 1) ? "s" : "");
 303:     }
 304: 
 305:     (void) close(sockFD);
 306:     sockFD = -1;
 307:     if (putToFile) {
 308:         fclose(filePtr);
 309:         filePtr = NULL;
 310:     }
 311: 
 312:     switch (error) {
 313:         case NO_ERRORS:
 314:         return (SUCCESS);
 315: 
 316:         case ERR_READING_LEN:
 317:         return(ERROR);
 318: 
 319:         case ERR_PRINTING:
 320:         fprintf(stderr,"*** Error during listing of %s: %s\n",
 321:                 namePtr, DecodeError(result));
 322:         return(result);
 323: 
 324:         case ERR_READING_MSG:
 325:         headerPtr = (HEADER *) &buf;
 326:         fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
 327:         fprintf(stderr,
 328:            "  result: %s, answers = %d, authority = %d, additional = %d\n",
 329:                 rcodes[headerPtr->rcode],
 330:                 ntohs(headerPtr->ancount), ntohs(headerPtr->nscount),
 331:             ntohs(headerPtr->arcount));
 332:         return(ERROR);
 333:         default:
 334:         return(ERROR);
 335:     }
 336: }
 337: 
 338: 
 339: /*
 340:  *******************************************************************************
 341:  *
 342:  *  PrintListInfo --
 343:  *
 344:  * 	Used by the ListInfo routine to print the answer
 345:  *	received from the name server. Only the desired
 346:  *	information is printed.
 347:  *
 348:  *  Results:
 349:  *	SUCCESS		the answer was printed without a problem.
 350:  *	NO_INFO		the answer packet did not contain an answer.
 351:  *	ERROR		the answer was malformed.
 352:  *      Misc. errors	returned in the packet header.
 353:  *
 354:  *******************************************************************************
 355:  */
 356: 
 357: #define NAME_FORMAT " %-30s"
 358: #define STRIP_DOMAIN(string) if((dot = index(string, '.')) != NULL) *dot = '\0'
 359: 
 360: 
 361: PrintListInfo(file, msg, eom, queryType)
 362:     FILE    *file;
 363:     char    *msg, *eom;
 364:     int     queryType;
 365: {
 366:     register char   *cp;
 367:     HEADER      *headerPtr;
 368:     int         type, class, dlen, nameLen;
 369:     int         n;
 370:     struct in_addr  inaddr;
 371:     char        name[NAME_LEN];
 372:     char        name2[NAME_LEN];
 373:     char        *dot;
 374: 
 375:     /*
 376:      * Read the header fields.
 377:      */
 378:     headerPtr = (HEADER *)msg;
 379:     cp = msg + sizeof(HEADER);
 380:     if (headerPtr->rcode != NOERROR) {
 381:     return(headerPtr->rcode);
 382:     }
 383: 
 384:     /*
 385:      *  We are looking for info from answer resource records.
 386:      *  If there aren't any, return with an error. We assume
 387:      *  there aren't any question records.
 388:      */
 389: 
 390:     if (ntohs(headerPtr->ancount) == 0) {
 391:     return(NO_INFO);
 392:     } else {
 393:     if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) {
 394:         return (ERROR);
 395:     }
 396:     cp += nameLen;
 397:     type = getshort(cp);
 398:     cp += sizeof(u_short);
 399:     class = getshort(cp);
 400:     cp += sizeof(u_short) + sizeof(u_long);
 401:     dlen = getshort(cp);
 402:     cp += sizeof(u_short);
 403: 
 404:     /*
 405: 	 * QueryType is used to specify the type of desired information.
 406: 	 *  T_A   	- internet address
 407: 	 *  T_CNAME 	- aliases
 408: 	 *  T_HINFO	- cpu, OS type
 409: 	 *  T_MX	- mail routing
 410: 	 *
 411: 
 412: 	 */
 413:     switch (type) {
 414: 
 415:         case T_A:
 416:         if (queryType != T_A)
 417:             break;
 418: 
 419:         if (class == C_IN) {
 420:             STRIP_DOMAIN(name);
 421:             fprintf(file, NAME_FORMAT, name);
 422:             bcopy(cp, (char *)&inaddr, sizeof(inaddr));
 423:             if (dlen == 4) {
 424:             fprintf(file," %s\n", inet_ntoa(inaddr));
 425:             } else if (dlen == 7) {
 426:             fprintf(file," %s", inet_ntoa(inaddr));
 427:             fprintf(file," (%d, %d)\n", cp[4],(cp[5] << 8) + cp[6]);
 428:             }
 429:         }
 430:         break;
 431: 
 432:         case T_CNAME:
 433:         if (queryType != T_CNAME)
 434:             break;
 435: 
 436:         STRIP_DOMAIN(name);
 437:         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 438:             return (ERROR);
 439:         }
 440:         /*
 441: 		 * a bug -- cnames need not be in same domain!
 442: 		 * STRIP_DOMAIN(name2);
 443: 		 */
 444: 
 445:         fprintf(file, NAME_FORMAT, name2);
 446:         fprintf(file, " %s\n", name);
 447:         break;
 448: 
 449:         case T_HINFO:
 450:         if (queryType != T_HINFO)
 451:             break;
 452: 
 453:         STRIP_DOMAIN(name);
 454:         fprintf(file, NAME_FORMAT, name);
 455:         if (n = *cp++) {
 456:             sprintf(name,"%.*s", n, cp);
 457:             fprintf(file," %-20s", name);
 458:             cp += n;
 459:         } else {
 460:             fprintf(file," %-20s", " ");
 461:         }
 462:         if (n = *cp++) {
 463:             fprintf(file," %.*s\n", n, cp);
 464:             cp += n;
 465:         }
 466:         break;
 467: 
 468:         case T_MX:
 469:         if (queryType != T_MX)
 470:             break;
 471: 
 472:         STRIP_DOMAIN(name);
 473:         fprintf(file, NAME_FORMAT, name);
 474: 
 475:         {
 476:             short pref;
 477: 
 478:             pref = getshort(cp);
 479:             cp += sizeof(u_short);
 480:             fprintf(file,"%10d",pref);
 481:         }
 482:         if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 483:             return (ERROR);
 484:         }
 485:         fprintf(file, " %s\n", name2);
 486: 
 487:         break;
 488: 
 489: 
 490:         case T_NS:
 491:         case T_PTR:
 492:         if (queryType != T_A)
 493:             break;
 494:         /*
 495: 		 *  Found a name server or pointer record.
 496: 		 */
 497:         fprintf(file, NAME_FORMAT, name);
 498:         fprintf(file," server = ");
 499:         cp = Print_cdname2(cp, msg, eom, file);
 500:         fprintf(file,"\n");
 501:         break;
 502: 
 503:         default:
 504:         /*
 505: 		 * Unwanted answer type -- ignore it.
 506: 		 */
 507:          break;
 508:     }
 509:     }
 510:     return(SUCCESS);
 511: }
 512: 
 513: 
 514: /*
 515:  *******************************************************************************
 516:  *
 517:  *  ViewList --
 518:  *
 519:  *	A hack to view the output of the ls command in sorted
 520:  *	order using more.
 521:  *
 522:  *******************************************************************************
 523:  */
 524: 
 525: ViewList(string)
 526:     char *string;
 527: {
 528:     char file[NAME_LEN];
 529:     char command[NAME_LEN];
 530: 
 531:     sscanf(string, " view %s", file);
 532:     sprintf(command, "grep \"^ \" %s | sort | more", file);
 533:     system(command);
 534: }
 535: 
 536: /*
 537:  *******************************************************************************
 538:  *
 539:  *   Finger --
 540:  *
 541:  *	Connects with the finger server for the current host
 542:  *	to request info on the specified person (long form)
 543:  *	who is on the system (short form).
 544:  *
 545:  *  Results:
 546:  *	SUCCESS		the finger server was contacted.
 547:  *	ERROR		the server could not be contacted because
 548:  *			a socket could not be obtained or connected
 549:  *			to or the service could not be found.
 550:  *
 551:  *******************************************************************************
 552:  */
 553: 
 554: Finger(string, putToFile)
 555:     char *string;
 556:     int  putToFile;
 557: {
 558:     struct servent      *sp;
 559:     struct sockaddr_in  sin;
 560:     register FILE       *f;
 561:     register int        c;
 562:     register int        lastc;
 563:     char            name[NAME_LEN];
 564:     char            file[NAME_LEN];
 565: 
 566:     /*
 567: 	 *  We need a valid current host info to get an inet address.
 568: 	 */
 569:     if (!curHostValid) {
 570:         fprintf(stderr, "Finger: no current host defined.\n");
 571:         return (ERROR);
 572:     }
 573: 
 574:     if (sscanf(string, " finger %s", name) == 1) {
 575:         if (putToFile && (name[0] == '>')) {
 576:         name[0] = '\0';
 577:         }
 578:     } else {
 579:         name[0] = '\0';
 580:     }
 581: 
 582:     sp = getservbyname("finger", "tcp");
 583:     if (sp == 0) {
 584:         fprintf(stderr, "Finger: unknown service\n");
 585:         return (ERROR);
 586:     }
 587: 
 588:     bzero((char *)&sin, sizeof(sin));
 589:     sin.sin_family  = curHostInfo.addrType;
 590:     sin.sin_port    = sp->s_port;
 591:     bcopy(curHostInfo.addrList[0], (char *)&sin.sin_addr,
 592:         curHostInfo.addrLen);
 593: 
 594:     /*
 595: 	 *  Set up a virtual circuit to the host.
 596: 	 */
 597: 
 598:     sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0);
 599:     if (sockFD < 0) {
 600:         fflush(stdout);
 601:         perror("Finger");
 602:         return (ERROR);
 603:     }
 604: 
 605:     if (connect(sockFD, (char *)&sin, sizeof (sin)) < 0) {
 606:         fflush(stdout);
 607:         perror("Finger");
 608:         close(sockFD);
 609:         sockFD = -1;
 610:         return (ERROR);
 611:     }
 612: 
 613:     if (!putToFile) {
 614:         filePtr = stdout;
 615:     } else {
 616:         filePtr = OpenFile(string, file);
 617:         if (filePtr == NULL) {
 618:         fprintf(stderr, "*** Can't open %s for writing\n", file);
 619:         close(sockFD);
 620:         sockFD = -1;
 621:         return(ERROR);
 622:         }
 623:         fprintf(filePtr,"> %s\n", string);
 624:     }
 625:     fprintf(filePtr, "[%s]\n", curHostInfo.name);
 626: 
 627:     if (name[0] != '\0') {
 628:         write(sockFD, "/W ", 3);
 629:     }
 630:     write(sockFD, name, strlen(name));
 631:     write(sockFD, "\r\n", 2);
 632:     f = fdopen(sockFD, "r");
 633:     while ((c = getc(f)) != EOF) {
 634:         switch(c) {
 635:         case 0210:
 636:         case 0211:
 637:         case 0212:
 638:         case 0214:
 639:             c -= 0200;
 640:             break;
 641:         case 0215:
 642:             c = '\n';
 643:             break;
 644:         }
 645:         putc(lastc = c, filePtr);
 646:     }
 647:     if (lastc != '\n') {
 648:         putc('\n', filePtr);
 649:     }
 650:     putc('\n', filePtr);
 651: 
 652:     close(sockFD);
 653:     sockFD = -1;
 654: 
 655:     if (putToFile) {
 656:         fclose(filePtr);
 657:         filePtr = NULL;
 658:     }
 659:     return (SUCCESS);
 660: }

Defined functions

Finger defined in line 554; never used
ListHosts defined in line 85; never used
PrintListInfo defined in line 361; used 1 times
ViewList defined in line 525; never used

Defined variables

sccsid defined in line 18; never used

Defined macros

HASH_SIZE defined in line 52; used 2 times
NAME_FORMAT defined in line 357; used 5 times
STRIP_DOMAIN defined in line 358; used 4 times
Last modified: 1986-04-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1862
Valid CSS Valid XHTML 1.0 Strict