122492Sdist /*
2*61423Sbostic * Copyright (c) 1983, 1993
3*61423Sbostic * The Regents of the University of California. All rights reserved.
435556Sbostic *
542664Sbostic * %sccs.include.redist.c%
622492Sdist */
722492Sdist
816471Ssam #ifndef lint
9*61423Sbostic static char copyright[] =
10*61423Sbostic "@(#) Copyright (c) 1983, 1993\n\
11*61423Sbostic The Regents of the University of California. All rights reserved.\n";
1235556Sbostic #endif /* not lint */
1316471Ssam
1422492Sdist #ifndef lint
15*61423Sbostic static char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 06/04/93";
1635556Sbostic #endif /* not lint */
1722492Sdist
1855235Sbostic #include <sys/types.h>
1955235Sbostic #include <sys/socket.h>
2055235Sbostic #include <netinet/in.h>
2155235Sbostic #include <arpa/inet.h>
2252435Sbostic #include <errno.h>
2355235Sbostic
2452435Sbostic #include <unistd.h>
2555235Sbostic #include <syslog.h>
2655235Sbostic #include <netdb.h>
2716471Ssam #include <stdio.h>
2852435Sbostic #include <stdlib.h>
2952435Sbostic #include <strings.h>
3037269Sbostic #include "pathnames.h"
3116471Ssam
3252435Sbostic void err __P((const char *, ...));
3352435Sbostic
3452435Sbostic int
main(argc,argv)3555235Sbostic main(argc, argv)
3655235Sbostic int argc;
3755235Sbostic char *argv[];
3816471Ssam {
3936261Sbostic register FILE *fp;
4036261Sbostic register int ch;
4136261Sbostic register char *lp;
4255083Stef struct hostent *hp;
4316471Ssam struct sockaddr_in sin;
4455235Sbostic int p[2], logging, secure, sval;
4555235Sbostic #define ENTRIES 50
4655235Sbostic char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog;
4716471Ssam
4855235Sbostic prog = _PATH_FINGER;
4955235Sbostic logging = secure = 0;
5055235Sbostic openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON);
5155235Sbostic opterr = 0;
5255235Sbostic while ((ch = getopt(argc, argv, "slp:")) != EOF)
5355083Stef switch (ch) {
5455083Stef case 'l':
5555235Sbostic logging = 1;
5655083Stef break;
5755083Stef case 'p':
5855083Stef prog = optarg;
5955083Stef break;
6055235Sbostic case 's':
6155235Sbostic secure = 1;
6255235Sbostic break;
6355083Stef case '?':
6455083Stef default:
6555235Sbostic err("illegal option -- %c", ch);
6655083Stef }
6736261Sbostic
6855083Stef if (logging) {
6955235Sbostic sval = sizeof(sin);
7055083Stef if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0)
7155083Stef err("getpeername: %s", strerror(errno));
7255083Stef if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr,
7355235Sbostic sizeof(sin.sin_addr.s_addr), AF_INET))
7455083Stef lp = hp->h_name;
7555083Stef else
7655083Stef lp = inet_ntoa(sin.sin_addr);
7755083Stef syslog(LOG_NOTICE, "query from %s", lp);
7855083Stef }
7955083Stef
8036261Sbostic if (!fgets(line, sizeof(line), stdin))
8136199Sbostic exit(1);
8252435Sbostic
8352435Sbostic comp = &av[1];
8452435Sbostic for (lp = line, ap = &av[2];;) {
8536261Sbostic *ap = strtok(lp, " \t\r\n");
8655083Stef if (!*ap) {
8755083Stef if (secure && ap == &av[2]) {
8855083Stef puts("must provide username\r\n");
8955083Stef exit(1);
9055083Stef }
9116471Ssam break;
9255083Stef }
9355083Stef if (secure && strchr(*ap, '@')) {
9455083Stef puts("fowarding service denied\r\n");
9555083Stef exit(1);
9655083Stef }
9755083Stef
9836261Sbostic /* RFC742: "/[Ww]" == "-l" */
9952446Sbostic if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
10052446Sbostic av[1] = "-l";
10152446Sbostic comp = &av[0];
10252446Sbostic }
10352435Sbostic else if (++ap == av + ENTRIES)
10436261Sbostic break;
10536261Sbostic lp = NULL;
10616471Ssam }
10736261Sbostic
10855083Stef if (lp = strrchr(prog, '/'))
10955083Stef *comp = ++lp;
11055083Stef else
11155083Stef *comp = prog;
11216770Sralph if (pipe(p) < 0)
11352435Sbostic err("pipe: %s", strerror(errno));
11436261Sbostic
11552435Sbostic switch(vfork()) {
11636261Sbostic case 0:
11736261Sbostic (void)close(p[0]);
11816770Sralph if (p[1] != 1) {
11936261Sbostic (void)dup2(p[1], 1);
12036261Sbostic (void)close(p[1]);
12116770Sralph }
12255083Stef execv(prog, comp);
12355083Stef err("execv: %s: %s", prog, strerror(errno));
12416770Sralph _exit(1);
12536261Sbostic case -1:
12652435Sbostic err("fork: %s", strerror(errno));
12716770Sralph }
12836261Sbostic (void)close(p[1]);
12936261Sbostic if (!(fp = fdopen(p[0], "r")))
13052435Sbostic err("fdopen: %s", strerror(errno));
13136261Sbostic while ((ch = getc(fp)) != EOF) {
13236261Sbostic if (ch == '\n')
13316595Sralph putchar('\r');
13436261Sbostic putchar(ch);
13516595Sralph }
13636261Sbostic exit(0);
13716471Ssam }
13816471Ssam
13952435Sbostic #if __STDC__
14052435Sbostic #include <stdarg.h>
14152435Sbostic #else
14252435Sbostic #include <varargs.h>
14352435Sbostic #endif
14452435Sbostic
14552435Sbostic void
14652435Sbostic #if __STDC__
err(const char * fmt,...)14752435Sbostic err(const char *fmt, ...)
14852435Sbostic #else
14952435Sbostic err(fmt, va_alist)
15052435Sbostic char *fmt;
15152435Sbostic va_dcl
15252435Sbostic #endif
15316471Ssam {
15452435Sbostic va_list ap;
15552435Sbostic #if __STDC__
15652435Sbostic va_start(ap, fmt);
15752435Sbostic #else
15852435Sbostic va_start(ap);
15952435Sbostic #endif
16055083Stef (void)vsyslog(LOG_ERR, fmt, ap);
16152435Sbostic va_end(ap);
16216471Ssam exit(1);
16352435Sbostic /* NOTREACHED */
16416471Ssam }
165