1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)fingerd.c 5.9 (Berkeley) 07/12/92"; 16 #endif /* not lint */ 17 18 #include <errno.h> 19 #include <unistd.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <strings.h> 23 #include <syslog.h> 24 #include <netdb.h> 25 #include <sys/types.h> 26 #include <sys/socket.h> 27 #include <netinet/in.h> 28 #include <arpa/inet.h> 29 #include "pathnames.h" 30 31 void err __P((const char *, ...)); 32 33 int 34 main(int argc, char **argv) 35 { 36 register FILE *fp; 37 register int ch; 38 register char *lp; 39 int p[2]; 40 #define ENTRIES 50 41 char **ap, *av[ENTRIES + 1], **comp, line[1024]; 42 char *prog = _PATH_FINGER; 43 struct hostent *hp; 44 struct sockaddr_in sin; 45 int sval = sizeof(sin); 46 int secure=0, logging=0; 47 extern char *optarg; 48 49 openlog("fingerd", LOG_PID|LOG_CONS, LOG_DAEMON); 50 while ((ch=getopt(argc, argv, "slp:")) != EOF) 51 switch (ch) { 52 case 's': 53 secure++; 54 break; 55 case 'l': 56 logging++; 57 break; 58 case 'p': 59 prog = optarg; 60 break; 61 case '?': 62 default: 63 syslog(LOG_ERR, "unknown option: %c", ch); 64 } 65 66 if (logging) { 67 if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0) 68 err("getpeername: %s", strerror(errno)); 69 if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr, 70 sizeof(sin.sin_addr.s_addr), AF_INET)) 71 lp = hp->h_name; 72 else 73 lp = inet_ntoa(sin.sin_addr); 74 syslog(LOG_NOTICE, "query from %s", lp); 75 } 76 77 if (!fgets(line, sizeof(line), stdin)) 78 exit(1); 79 80 comp = &av[1]; 81 for (lp = line, ap = &av[2];;) { 82 *ap = strtok(lp, " \t\r\n"); 83 if (!*ap) { 84 if (secure && ap == &av[2]) { 85 puts("must provide username\r\n"); 86 exit(1); 87 } 88 break; 89 } 90 if (secure && strchr(*ap, '@')) { 91 puts("fowarding service denied\r\n"); 92 exit(1); 93 } 94 95 /* RFC742: "/[Ww]" == "-l" */ 96 if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) { 97 av[1] = "-l"; 98 comp = &av[0]; 99 } 100 else if (++ap == av + ENTRIES) 101 break; 102 lp = NULL; 103 } 104 105 if (lp = strrchr(prog, '/')) 106 *comp = ++lp; 107 else 108 *comp = prog; 109 if (pipe(p) < 0) 110 err("pipe: %s", strerror(errno)); 111 112 switch(vfork()) { 113 case 0: 114 (void)close(p[0]); 115 if (p[1] != 1) { 116 (void)dup2(p[1], 1); 117 (void)close(p[1]); 118 } 119 execv(prog, comp); 120 err("execv: %s: %s", prog, strerror(errno)); 121 _exit(1); 122 case -1: 123 err("fork: %s", strerror(errno)); 124 } 125 (void)close(p[1]); 126 if (!(fp = fdopen(p[0], "r"))) 127 err("fdopen: %s", strerror(errno)); 128 while ((ch = getc(fp)) != EOF) { 129 if (ch == '\n') 130 putchar('\r'); 131 putchar(ch); 132 } 133 exit(0); 134 } 135 136 #if __STDC__ 137 #include <stdarg.h> 138 #else 139 #include <varargs.h> 140 #endif 141 142 void 143 #if __STDC__ 144 err(const char *fmt, ...) 145 #else 146 err(fmt, va_alist) 147 char *fmt; 148 va_dcl 149 #endif 150 { 151 va_list ap; 152 #if __STDC__ 153 va_start(ap, fmt); 154 #else 155 va_start(ap); 156 #endif 157 (void)vsyslog(LOG_ERR, fmt, ap); 158 va_end(ap); 159 exit(1); 160 /* NOTREACHED */ 161 } 162