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: }