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: #if !defined(lint) && defined(DOSCCS)
  21: static char sccsid[] = "@(#)list.c	5.20 (Berkeley) 6/1/90";
  22: #endif
  23: 
  24: /*
  25:  *******************************************************************************
  26:  *
  27:  *  list.c --
  28:  *
  29:  *	Routines to obtain info from name and finger servers.
  30:  *
  31:  *	Adapted from 4.3BSD BIND ns_init.c and from finger.c.
  32:  *
  33:  *******************************************************************************
  34:  */
  35: 
  36: #include <sys/types.h>
  37: #include <sys/socket.h>
  38: #include <netinet/in.h>
  39: #include <netdb.h>
  40: #include <stdio.h>
  41: #include <string.h>
  42: #include <ctype.h>
  43: #include <errno.h>
  44: #include <arpa/nameser.h>
  45: #include <arpa/inet.h>
  46: #include <resolv.h>
  47: #include "res.h"
  48: 
  49: /*
  50:  *  Imported from res_debug.c
  51:  */
  52: extern char *_res_resultcodes[];
  53: 
  54: extern int errno;
  55: 
  56: typedef union {
  57:     HEADER qb1;
  58:     char qb2[PACKETSZ];
  59: } querybuf;
  60: 
  61: extern HostInfo *defaultPtr;
  62: extern HostInfo curHostInfo;
  63: extern int  curHostValid;
  64: extern int  queryType;
  65: extern int  queryClass;
  66: 
  67: static int sockFD = -1;
  68: static int ListSubr();
  69: 
  70: /*
  71:  *  During a listing to a file, hash marks are printed
  72:  *  every HASH_SIZE records.
  73:  */
  74: 
  75: #define HASH_SIZE 50
  76: 
  77: 
  78: /*
  79:  *******************************************************************************
  80:  *
  81:  *  ListHosts --
  82:  *  ListHostsByType --
  83:  *
  84:  *	Requests the name server to do a zone transfer so we
  85:  *	find out what hosts it knows about.
  86:  *
  87:  *	For ListHosts, there are five types of output:
  88:  *	- Internet addresses (default)
  89:  *	- cpu type and operating system (-h option)
  90:  *	- canonical and alias names  (-a option)
  91:  *	- well-known service names  (-s option)
  92:  *	- ALL records (-d option)
  93:  *	ListHostsByType prints records of the default type or of a speicific
  94:  *	type.
  95:  *
  96:  *	To see all types of information sorted by name, do the following:
  97:  *	  ls -d domain.edu > file
  98:  *	  view file
  99:  *
 100:  *  Results:
 101:  *	SUCCESS		the listing was successful.
 102:  *	ERROR		the server could not be contacted because
 103:  *			a socket could not be obtained or an error
 104:  *			occured while receiving, or the output file
 105:  *			could not be opened.
 106:  *
 107:  *******************************************************************************
 108:  */
 109: 
 110: void
 111: ListHostsByType(string, putToFile)
 112:     char *string;
 113:     int putToFile;
 114: {
 115:     int i, qtype, result;
 116:     char    *namePtr;
 117:     char    name[NAME_LEN];
 118:     char    option[NAME_LEN];
 119: 
 120:     /*
 121: 	 *  Parse the command line. It maybe of the form "ls -t domain"
 122: 	 *  or "ls -t type domain".
 123: 	 */
 124: 
 125:     i = sscanf(string, " ls -t %s %s", option, name);
 126:     if (putToFile && i == 2 && name[0] == '>') {
 127:         i--;
 128:     }
 129:     if (i == 2) {
 130:         qtype = StringToType(option, -1);
 131:         if (qtype == -1)
 132:         return;
 133:         namePtr = name;
 134:     } else if (i == 1) {
 135:         namePtr = option;
 136:         qtype = queryType;
 137:     } else {
 138:         fprintf(stderr, "*** ls: invalid request %s\n",string);
 139:         return;
 140:     }
 141:     result = ListSubr(qtype, namePtr, putToFile ? string : NULL);
 142:     if (result != SUCCESS)
 143:         fprintf(stderr, "*** Can't list domain %s: %s\n",
 144:             namePtr, DecodeError(result));
 145: }
 146: 
 147: void
 148: ListHosts(string, putToFile)
 149:     char *string;
 150:     int  putToFile;
 151: {
 152:     int i, qtype, result;
 153:     char    *namePtr;
 154:     char    name[NAME_LEN];
 155:     char    option[NAME_LEN];
 156: 
 157:     /*
 158: 	 *  Parse the command line. It maybe of the form "ls domain",
 159: 	 *  "ls -X domain".
 160: 	 */
 161:     i = sscanf(string, " ls %s %s", option, name);
 162:     if (putToFile && i == 2 && name[0] == '>') {
 163:         i--;
 164:     }
 165:     if (i == 2) {
 166:         if (strcmp("-a", option) == 0) {
 167:         qtype = T_CNAME;
 168:         } else if (strcmp("-h", option) == 0) {
 169:         qtype = T_HINFO;
 170:         } else if (strcmp("-m", option) == 0) {
 171:         qtype = T_MX;
 172:         } else if (strcmp("-s", option) == 0) {
 173:         qtype = T_WKS;
 174:         } else if (strcmp("-d", option) == 0) {
 175:         qtype = T_ANY;
 176:         } else {
 177:         qtype = T_A;
 178:         }
 179:         namePtr = name;
 180:     } else if (i == 1) {
 181:         namePtr = option;
 182:         qtype = T_A;
 183:     } else {
 184:         fprintf(stderr, "*** ls: invalid request %s\n",string);
 185:         return;
 186:     }
 187:     result = ListSubr(qtype, namePtr, putToFile ? string : NULL);
 188:     if (result != SUCCESS)
 189:         fprintf(stderr, "*** Can't list domain %s: %s\n",
 190:             namePtr, DecodeError(result));
 191: }
 192: 
 193: static int
 194: ListSubr(qtype, domain, cmd)
 195:     int qtype;
 196:     char *domain;
 197:     char *cmd;
 198: {
 199:     querybuf        buf;
 200:     struct sockaddr_in  sin;
 201:     HEADER          *headerPtr;
 202:     int         msglen;
 203:     int         amtToRead;
 204:     int         numRead;
 205:     int         numAnswers = 0;
 206:     int         result;
 207:     int         soacnt = 0;
 208:     u_short         len;
 209:     char            *cp, *nmp;
 210:     char            dname[2][NAME_LEN];
 211:     char            file[NAME_LEN];
 212:     static char     *answer = NULL;
 213:     static int      answerLen = 0;
 214:     enum {
 215:         NO_ERRORS,
 216:         ERR_READING_LEN,
 217:         ERR_READING_MSG,
 218:         ERR_PRINTING,
 219:     } error = NO_ERRORS;
 220: 
 221:     /*
 222: 	 *  Create a query packet for the requested domain name.
 223: 	 */
 224:     msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR,
 225:                 (char *)0, 0, (char *)0,
 226:                 (char *) &buf, sizeof(buf));
 227:     if (msglen < 0) {
 228:         if (_res.options & RES_DEBUG) {
 229:         fprintf(stderr, "*** ls: res_mkquery failed\n");
 230:         }
 231:         return (ERROR);
 232:     }
 233: 
 234:     bzero((char *)&sin, sizeof(sin));
 235:     sin.sin_family  = AF_INET;
 236:     sin.sin_port    = htons(nsport);
 237: 
 238:     /*
 239: 	 *  Check to see if we have the address of the server or the
 240: 	 *  address of a server who knows about this domain.
 241: 	 *
 242: 	 *  For now, just use the first address in the list.
 243: 	 */
 244: 
 245:     if (defaultPtr->addrList != NULL) {
 246:       sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
 247:     } else {
 248:       sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
 249:     }
 250: 
 251:     /*
 252: 	 *  Set up a virtual circuit to the server.
 253: 	 */
 254:     if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 255:         perror("ls: socket");
 256:         return(ERROR);
 257:     }
 258:     if (connect(sockFD, &sin, sizeof(sin)) < 0) {
 259:         int e;
 260:         if (errno == ECONNREFUSED) {
 261:         e = NO_RESPONSE;
 262:         } else {
 263:         perror("ls: connect");
 264:         e = ERROR;
 265:         }
 266:         (void) close(sockFD);
 267:         sockFD = -1;
 268:         return e;
 269:     }
 270: 
 271:     /*
 272: 	 * Send length & message for zone transfer
 273: 	 */
 274: 
 275:         len = htons(msglen);
 276: 
 277:         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
 278:             write(sockFD, (char *) &buf, msglen) != msglen) {
 279:         perror("ls: write");
 280:         (void) close(sockFD);
 281:         sockFD = -1;
 282:         return(ERROR);
 283:     }
 284: 
 285:     fprintf(stdout,"[%s]\n",
 286:         (defaultPtr->addrList != NULL) ? defaultPtr->name :
 287:          defaultPtr->servers[0]->name);
 288: 
 289:     if (cmd == NULL) {
 290:         filePtr = stdout;
 291:     } else {
 292:         filePtr = OpenFile(cmd, file);
 293:             if (filePtr == NULL) {
 294:                 fprintf(stderr, "*** Can't open %s for writing\n", file);
 295:         (void) close(sockFD);
 296:         sockFD = -1;
 297:                 return(ERROR);
 298:             }
 299:         fprintf(filePtr, "> %s\n", cmd);
 300:         fprintf(filePtr,"[%s]\n",
 301:         (defaultPtr->addrList != NULL) ? defaultPtr->name :
 302:          defaultPtr->servers[0]->name);
 303:     }
 304: 
 305: #if 0
 306:     if (qtype == T_CNAME) {
 307:         fprintf(filePtr, "%-30s", "Alias");
 308:     } else if (qtype == T_TXT) {
 309:         fprintf(filePtr, "%-30s", "Key");
 310:     } else {
 311:         fprintf(filePtr, "%-30s", "Host or domain name");
 312:     }
 313:     switch (qtype) {
 314:         case T_A:
 315:             fprintf(filePtr, " %-30s\n", "Internet Address");
 316:             break;
 317:         case T_HINFO:
 318:             fprintf(filePtr, " %-30s\n", "CPU & OS");
 319:             break;
 320:         case T_CNAME:
 321:             fprintf(filePtr, " %-30s\n", "Canonical Name");
 322:             break;
 323:         case T_MX:
 324:             fprintf(filePtr, " %-30s\n", "Metric & Host");
 325:             break;
 326:         case T_WKS:
 327:             fprintf(filePtr, " %-4s %s\n", "Protocol", "Services");
 328:             break;
 329:         case T_MB:
 330:             fprintf(filePtr, " %-30s\n", "Mailbox");
 331:             break;
 332:         case T_MG:
 333:             fprintf(filePtr, " %-30s\n", "Mail Group");
 334:             break;
 335:         case T_MR:
 336:             fprintf(filePtr, " %-30s\n", "Mail Rename");
 337:             break;
 338:         case T_MINFO:
 339:             fprintf(filePtr, " %-30s\n", "Mail List Requests & Errors");
 340:             break;
 341:         case T_UINFO:
 342:             fprintf(filePtr, " %-30s\n", "User Information");
 343:             break;
 344:         case T_UID:
 345:             fprintf(filePtr, " %-30s\n", "User ID");
 346:             break;
 347:         case T_GID:
 348:             fprintf(filePtr, " %-30s\n", "Group ID");
 349:             break;
 350:         case T_TXT:
 351:             fprintf(filePtr, " %-30s\n", "Text");
 352:             break;
 353:         case T_NS:
 354:             fprintf(filePtr, " %-30s\n", "Name Servers");
 355:             break;
 356:         case T_PTR:
 357:             fprintf(filePtr, " %-30s\n", "Pointers");
 358:             break;
 359:         case T_SOA:
 360:             fprintf(filePtr, " %-30s\n", "Start of Authority");
 361:             break;
 362:         case T_ANY:
 363:             fprintf(filePtr, " %-30s\n", "Resource Record Info.");
 364:             break;
 365:     }
 366: #endif
 367: 
 368: 
 369:     dname[0][0] = '\0';
 370:     while (1) {
 371:         unsigned short tmp;
 372: 
 373:         /*
 374: 	     * Read the length of the response.
 375: 	     */
 376: 
 377:         cp = (char *) &tmp;
 378:         amtToRead = sizeof(u_short);
 379:         while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
 380:         cp    += numRead;
 381:         amtToRead -= numRead;
 382:         }
 383:         if (numRead <= 0) {
 384:         error = ERR_READING_LEN;
 385:         break;
 386:         }
 387: 
 388:         if ((len = htons(tmp)) == 0) {
 389:         break;  /* nothing left to read */
 390:         }
 391: 
 392:         /*
 393: 	     * The server sent too much data to fit the existing buffer --
 394: 	     * allocate a new one.
 395: 	     */
 396:         if (len > answerLen) {
 397:         if (answerLen != 0) {
 398:             free(answer);
 399:         }
 400:         answerLen = len;
 401:         answer = Malloc(answerLen);
 402:         }
 403: 
 404:         /*
 405: 	     * Read the response.
 406: 	     */
 407: 
 408:         amtToRead = len;
 409:         cp = answer;
 410:         while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
 411:         cp += numRead;
 412:         amtToRead -= numRead;
 413:         }
 414:         if (numRead <= 0) {
 415:         error = ERR_READING_MSG;
 416:         break;
 417:         }
 418: 
 419:         result = PrintListInfo(filePtr, answer, cp, qtype, dname[0]);
 420:         if (result != SUCCESS) {
 421:         error = ERR_PRINTING;
 422:         break;
 423:         }
 424: 
 425:         numAnswers++;
 426:         if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) {
 427:         fprintf(stdout, "#");
 428:         fflush(stdout);
 429:         }
 430:         cp = answer + sizeof(HEADER);
 431:         if (ntohs(((HEADER* )answer)->qdcount) > 0)
 432:         cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
 433:         nmp = cp;
 434:         cp += dn_skipname(cp, (u_char *)answer + len);
 435:         if ((_getshort(cp) == T_SOA)) {
 436:         dn_expand(answer, answer + len, nmp, dname[soacnt],
 437:             sizeof(dname[0]));
 438:             if (soacnt) {
 439:             if (strcmp(dname[0], dname[1]) == 0)
 440:             break;
 441:         } else
 442:             soacnt++;
 443:         }
 444:     }
 445: 
 446:     if (cmd != NULL) {
 447:         fprintf(stdout, "%sReceived %d record%s.\n",
 448:         (numAnswers >= HASH_SIZE) ? "\n" : "",
 449:         numAnswers,
 450:         (numAnswers != 1) ? "s" : "");
 451:     }
 452: 
 453:     (void) close(sockFD);
 454:     sockFD = -1;
 455:     if (cmd != NULL && filePtr != NULL) {
 456:         fclose(filePtr);
 457:         filePtr = NULL;
 458:     }
 459: 
 460:     switch (error) {
 461:         case NO_ERRORS:
 462:         return (SUCCESS);
 463: 
 464:         case ERR_READING_LEN:
 465:         return(ERROR);
 466: 
 467:         case ERR_PRINTING:
 468:         return(result);
 469: 
 470:         case ERR_READING_MSG:
 471:         headerPtr = (HEADER *) answer;
 472:         fprintf(stderr,"*** ls: error receiving zone transfer:\n");
 473:         fprintf(stderr,
 474:            "  result: %s, answers = %d, authority = %d, additional = %d\n",
 475:             _res_resultcodes[headerPtr->rcode],
 476:             ntohs(headerPtr->ancount), ntohs(headerPtr->nscount),
 477:             ntohs(headerPtr->arcount));
 478:         return(ERROR);
 479:         default:
 480:         return(ERROR);
 481:     }
 482: }
 483: 
 484: 
 485: /*
 486:  *******************************************************************************
 487:  *
 488:  *  PrintListInfo --
 489:  *
 490:  *	Used by the ListInfo routine to print the answer
 491:  *	received from the name server. Only the desired
 492:  *	information is printed.
 493:  *
 494:  *  Results:
 495:  *	SUCCESS		the answer was printed without a problem.
 496:  *	NO_INFO		the answer packet did not contain an answer.
 497:  *	ERROR		the answer was malformed.
 498:  *      Misc. errors	returned in the packet header.
 499:  *
 500:  *******************************************************************************
 501:  */
 502: 
 503: #define NAME_FORMAT " %-30s"
 504: 
 505: static Boolean
 506: strip_domain(string, domain)
 507:     char *string, *domain;
 508: {
 509:     register char *dot;
 510: 
 511:     if (*domain != '\0') {
 512:     dot = string;
 513:     while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot))
 514:         ;
 515:     if (dot != NULL) {
 516:         dot[-1] = '\0';
 517:         return TRUE;
 518:     }
 519:     }
 520:     return FALSE;
 521: }
 522: 
 523: 
 524: PrintListInfo(file, msg, eom, qtype, domain)
 525:     FILE    *file;
 526:     char    *msg, *eom;
 527:     int     qtype;
 528:     char    *domain;
 529: {
 530:     register char   *cp;
 531:     HEADER      *headerPtr;
 532:     int         type, class, dlen, nameLen;
 533:     u_long      ttl;
 534:     int         n, pref;
 535:     struct in_addr  inaddr;
 536:     char        name[NAME_LEN];
 537:     char        name2[NAME_LEN];
 538:     Boolean     stripped;
 539: 
 540:     /*
 541:      * Read the header fields.
 542:      */
 543:     headerPtr = (HEADER *)msg;
 544:     cp = msg + sizeof(HEADER);
 545:     if (headerPtr->rcode != NOERROR) {
 546:     return(headerPtr->rcode);
 547:     }
 548: 
 549:     /*
 550:      *  We are looking for info from answer resource records.
 551:      *  If there aren't any, return with an error. We assume
 552:      *  there aren't any question records.
 553:      */
 554: 
 555:     if (ntohs(headerPtr->ancount) == 0) {
 556:     return(NO_INFO);
 557:     } else {
 558:     if (ntohs(headerPtr->qdcount) > 0) {
 559:         nameLen = dn_skipname(cp, eom);
 560:         if (nameLen < 0)
 561:         return (ERROR);
 562:         cp += nameLen + QFIXEDSZ;
 563:     }
 564:     if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0)
 565:         return (ERROR);
 566:     cp += nameLen;
 567: 
 568:     type = _getshort(cp);
 569:     cp += sizeof(u_short);
 570: 
 571:     if (!(type == qtype || qtype == T_ANY) &&
 572:         !((type == T_NS || type == T_PTR) && qtype == T_A))
 573:         return(SUCCESS);
 574: 
 575:     class = _getshort(cp);
 576:     cp += sizeof(u_short);
 577:     ttl = _getlong(cp);
 578:     cp += sizeof(u_long);
 579:     dlen = _getshort(cp);
 580:     cp += sizeof(u_short);
 581: 
 582:     if (name[0] == 0)
 583:         strcpy(name, "(root)");
 584: 
 585:     /* Strip the domain name from the data, if desired. */
 586:     stripped = FALSE;
 587:     if ((_res.options & RES_DEBUG) == 0) {
 588:         if (type != T_SOA) {
 589:         stripped = strip_domain(name, domain);
 590:         }
 591:     }
 592:     if (!stripped && nameLen < sizeof(name)-1) {
 593:         strcat(name, ".");
 594:     }
 595: 
 596:     fprintf(file, NAME_FORMAT, name);
 597: 
 598:     if (qtype == T_ANY) {
 599:         if (_res.options & RES_DEBUG) {
 600:         fprintf(file,"\t%lu %-5s", ttl, p_class(queryClass));
 601:         }
 602:         fprintf(file," %-5s", p_type(type));
 603:     }
 604: 
 605:     /* XXX merge this into debug.c's print routines */
 606: 
 607:     switch (type) {
 608:         case T_A:
 609:         if (class == C_IN) {
 610:             bcopy(cp, (char *)&inaddr, sizeof(inaddr));
 611:             if (dlen == 4) {
 612:             fprintf(file," %s", inet_ntoa(inaddr));
 613:             } else if (dlen == 7) {
 614:             fprintf(file," %s", inet_ntoa(inaddr));
 615:             fprintf(file," (%d, %d)", cp[4],(cp[5] << 8) + cp[6]);
 616:             } else
 617:             fprintf(file, " (dlen = %d?)", dlen);
 618:         }
 619:         break;
 620: 
 621:         case T_CNAME:
 622:         case T_MB:
 623:         case T_MG:
 624:         case T_MR:
 625:         if ((nameLen =
 626:             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 627:             fprintf(file, " ***\n");
 628:             return (ERROR);
 629:         }
 630:         fprintf(file, " %s", name2);
 631:         break;
 632: 
 633:         case T_NS:
 634:         case T_PTR:
 635:         putc(' ', file);
 636:         if (qtype != T_ANY)
 637:             fprintf(file,"%s = ", type == T_PTR ? "host" : "server");
 638:         cp = Print_cdname2(cp, msg, eom, file);
 639:         break;
 640: 
 641:         case T_HINFO:
 642:         if (n = *cp++) {
 643:             (void)sprintf(name,"%.*s", n, cp);
 644:             fprintf(file," %-10s", name);
 645:             cp += n;
 646:         } else {
 647:             fprintf(file," %-10s", " ");
 648:         }
 649:         if (n = *cp++) {
 650:             fprintf(file,"  %.*s", n, cp);
 651:             cp += n;
 652:         }
 653:         break;
 654: 
 655:         case T_SOA:
 656:         if ((nameLen =
 657:             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 658:             fprintf(file, " ***\n");
 659:             return (ERROR);
 660:         }
 661:         cp += nameLen;
 662:         fprintf(file, " %s", name2);
 663:         if ((nameLen =
 664:             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 665:             fprintf(file, " ***\n");
 666:             return (ERROR);
 667:         }
 668:         cp += nameLen;
 669:         fprintf(file, " %s. (", name2);
 670:         for (n = 0; n < 5; n++) {
 671:             u_long u;
 672: 
 673:             u = _getlong(cp);
 674:             cp += sizeof(u_long);
 675:             fprintf(file,"%s%lu", n? " " : "", u);
 676:         }
 677:         fprintf(file, ")");
 678:         break;
 679: 
 680:         case T_MX:
 681:         pref = _getshort(cp);
 682:         cp += sizeof(u_short);
 683:         fprintf(file," %-3d ",pref);
 684:         if ((nameLen =
 685:             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
 686:             fprintf(file, " ***\n");
 687:             return (ERROR);
 688:         }
 689:         fprintf(file, " %s", name2);
 690:         break;
 691: 
 692:         case T_TXT:
 693:         {
 694:             char *cp2 = cp + dlen;
 695:             int c;
 696: 
 697:             (void) fputs(" \"", file);
 698:             while (cp < cp2) {
 699:                 if (n = (unsigned char) *cp++) {
 700:                     for (c = n; c > 0 && cp < cp2; c--)
 701:                         if (*cp == '\n') {
 702:                         (void) putc('\\', file);
 703:                         (void) putc(*cp++, file);
 704:                         } else
 705:                         (void) putc(*cp++, file);
 706:                 }
 707:             }
 708:             (void) putc('"', file);
 709:         }
 710:         break;
 711: 
 712:         case T_MINFO:
 713:         (void) putc(' ', file);
 714:         cp = Print_cdname(cp, msg, eom, file);
 715:         fprintf(file, "  ");
 716:         cp = Print_cdname(cp, msg, eom, file);
 717:         break;
 718: 
 719:         case T_UINFO:
 720:         fprintf(file, " %s", cp);
 721:         break;
 722: 
 723:         case T_UID:
 724:         case T_GID:
 725:         fprintf(file, " %lu", _getlong(cp));
 726:         break;
 727: 
 728:         case T_WKS:
 729:         if (class == C_IN) {
 730:             struct protoent *pp;
 731:             struct servent *ss;
 732:             u_short port;
 733: 
 734:             cp += 4;    /* skip inet address */
 735:             dlen -= 4;
 736: 
 737:             setprotoent(1);
 738:             setservent(1);
 739:             n = *cp & 0377;
 740:             pp = getprotobynumber(n);
 741:             if (pp == 0)
 742:             fprintf(file," %-3d ", n);
 743:             else
 744:             fprintf(file," %-3s ", pp->p_name);
 745:             cp++; dlen--;
 746: 
 747:             port = 0;
 748:             while (dlen-- > 0) {
 749:             n = *cp++;
 750:             do {
 751:                 if (n & 0200) {
 752:                 ss = getservbyport((int)htons(port),
 753:                         pp->p_name);
 754:                 if (ss == 0)
 755:                     fprintf(file," %u", port);
 756:                 else
 757:                     fprintf(file," %s", ss->s_name);
 758:                 }
 759:                 n <<= 1;
 760:             } while (++port & 07);
 761:             }
 762:             endprotoent();
 763:             endservent();
 764:         }
 765:         break;
 766:     }
 767:     fprintf(file,"\n");
 768:     }
 769:     return(SUCCESS);
 770: }
 771: 
 772: 
 773: /*
 774:  *******************************************************************************
 775:  *
 776:  *  ViewList --
 777:  *
 778:  *	A hack to view the output of the ls command in sorted
 779:  *	order using more.
 780:  *
 781:  *******************************************************************************
 782:  */
 783: 
 784: ViewList(string)
 785:     char *string;
 786: {
 787:     char file[NAME_LEN];
 788:     char command[NAME_LEN];
 789: 
 790:     sscanf(string, " view %s", file);
 791:     (void)sprintf(command, "grep \"^ \" %s | sort | more", file);
 792:     system(command);
 793: }
 794: 
 795: /*
 796:  *******************************************************************************
 797:  *
 798:  *   Finger --
 799:  *
 800:  *	Connects with the finger server for the current host
 801:  *	to request info on the specified person (long form)
 802:  *	who is on the system (short form).
 803:  *
 804:  *  Results:
 805:  *	SUCCESS		the finger server was contacted.
 806:  *	ERROR		the server could not be contacted because
 807:  *			a socket could not be obtained or connected
 808:  *			to or the service could not be found.
 809:  *
 810:  *******************************************************************************
 811:  */
 812: 
 813: Finger(string, putToFile)
 814:     char *string;
 815:     int  putToFile;
 816: {
 817:     struct servent      *sp;
 818:     struct sockaddr_in  sin;
 819:     register FILE       *f;
 820:     register int        c;
 821:     register int        lastc;
 822:     char            name[NAME_LEN];
 823:     char            file[NAME_LEN];
 824: 
 825:     /*
 826: 	 *  We need a valid current host info to get an inet address.
 827: 	 */
 828:     if (!curHostValid) {
 829:         fprintf(stderr, "Finger: no current host defined.\n");
 830:         return (ERROR);
 831:     }
 832: 
 833:     if (sscanf(string, " finger %s", name) == 1) {
 834:         if (putToFile && (name[0] == '>')) {
 835:         name[0] = '\0';
 836:         }
 837:     } else {
 838:         name[0] = '\0';
 839:     }
 840: 
 841:     sp = getservbyname("finger", "tcp");
 842:     if (sp == 0) {
 843:         fprintf(stderr, "Finger: unknown service\n");
 844:         return (ERROR);
 845:     }
 846: 
 847:     bzero((char *)&sin, sizeof(sin));
 848:     sin.sin_family  = curHostInfo.addrType;
 849:     sin.sin_port    = sp->s_port;
 850:     bcopy(curHostInfo.addrList[0], (char *)&sin.sin_addr,
 851:         curHostInfo.addrLen);
 852: 
 853:     /*
 854: 	 *  Set up a virtual circuit to the host.
 855: 	 */
 856: 
 857:     sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0);
 858:     if (sockFD < 0) {
 859:         fflush(stdout);
 860:         perror("finger: socket");
 861:         return (ERROR);
 862:     }
 863: 
 864:     if (connect(sockFD, (char *)&sin, sizeof (sin)) < 0) {
 865:         fflush(stdout);
 866:         perror("finger: connect");
 867:         close(sockFD);
 868:         sockFD = -1;
 869:         return (ERROR);
 870:     }
 871: 
 872:     if (!putToFile) {
 873:         filePtr = stdout;
 874:     } else {
 875:         filePtr = OpenFile(string, file);
 876:         if (filePtr == NULL) {
 877:         fprintf(stderr, "*** Can't open %s for writing\n", file);
 878:         close(sockFD);
 879:         sockFD = -1;
 880:         return(ERROR);
 881:         }
 882:         fprintf(filePtr,"> %s\n", string);
 883:     }
 884:     fprintf(filePtr, "[%s]\n", curHostInfo.name);
 885: 
 886:     if (name[0] != '\0') {
 887:         write(sockFD, "/W ", 3);
 888:     }
 889:     write(sockFD, name, strlen(name));
 890:     write(sockFD, "\r\n", 2);
 891:     f = fdopen(sockFD, "r");
 892:     while ((c = getc(f)) != EOF) {
 893:         switch (c) {
 894:         case 0210:
 895:         case 0211:
 896:         case 0212:
 897:         case 0214:
 898:             c -= 0200;
 899:             break;
 900:         case 0215:
 901:             c = '\n';
 902:             break;
 903:         }
 904:         putc(lastc = c, filePtr);
 905:     }
 906:     if (lastc != '\n') {
 907:         putc('\n', filePtr);
 908:     }
 909:     putc('\n', filePtr);
 910: 
 911:     close(sockFD);
 912:     sockFD = -1;
 913: 
 914:     if (putToFile) {
 915:         fclose(filePtr);
 916:         filePtr = NULL;
 917:     }
 918:     return (SUCCESS);
 919: }
 920: 
 921: ListHost_close()
 922: {
 923:     if (sockFD != -1) {
 924:     (void) close(sockFD);
 925:     sockFD = -1;
 926:     }
 927: }

Defined functions

Finger defined in line 813; never used
ListHosts defined in line 147; never used
ListHostsByType defined in line 110; never used
ListSubr defined in line 193; used 3 times
PrintListInfo defined in line 524; used 1 times
ViewList defined in line 784; never used
strip_domain defined in line 505; used 1 times

Defined variables

sccsid defined in line 21; never used
sockFD defined in line 67; used 30 times

Defined macros

HASH_SIZE defined in line 75; used 2 times
NAME_FORMAT defined in line 503; used 1 times
Last modified: 1993-04-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4743
Valid CSS Valid XHTML 1.0 Strict