xref: /original-bsd/libexec/fingerd/fingerd.c (revision 97411546)
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