|
|
1.1 root 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: #ifndef lint
21: static char sccsid[] = "@(#)list.c 5.20 (Berkeley) 6/1/90";
22: #endif /* not lint */
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.