Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!news.uoknor.edu!ns1.nodak.edu!netnews.nwnet.net!henson!reuter.cse.ogi.edu!uwm.edu!spool.mu.edu!howland.reston.ans.net!swrinde!sgiblab!sgigate.sgi.com!fido.asd.sgi.com!slovax!lm From: lm@slovax.engr.sgi.com (Larry McVoy) Newsgroups: comp.unix.bsd Subject: Fingerd revision Date: 13 Jan 1995 01:37:30 GMT Organization: Silicon Graphics Inc., Mountain View, CA Lines: 281 Message-ID: <3f4lgq$3u2@fido.asd.sgi.com> Reply-To: lm@slovax.engr.sgi.com NNTP-Posting-Host: slovax.engr.sgi.com X-Newsreader: TIN [version 1.2 PL2] I had to fix a bug in SGI's finger and I extended the fingerd protocol to allow remote sites to pass through options in a (some what) backwards compatible way. Trailing options will now get passed through as shown below. This is most useful for the widely implemented -m option which forces exact matches on names. The 4.4lite revised code is included below. The SGI code will be in a forthcoming IRIX 6.x release. Could NetBSD and FreeBSD and BSDI take a look at this? It would be nice if we all had it. By the way - the fingerd below works just fine on SunOS :-) telnet fubar finger Trying 150.166.75.39... Connected to fubar.engr.sgi.com. Escape character is '^]'. greg -m Login name: greg In real life: Greg Chesson Office: 9U-510, x3496 Directory: /usr/people/greg Shell: /bin/sh Mail to greg goes to greg@xtp.engr.sgi.com Never logged in. No Plan. Connection closed by foreign host. /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 6/4/93"; #endif /* not lint */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <unistd.h> #include <syslog.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #define _PATH_FINGER "/usr/ucb/finger" void err(const char *, ...); extern char *strtok(); extern char *strchr(); extern char *strrchr(); #define SUNOS #ifdef SUNOS extern char * sys_errlist[]; char * strerror(n) { return (sys_errlist[n]); } #endif int main(argc, argv) int argc; char *argv[]; { register FILE *fp; register int ch; register char *lp; struct hostent *hp; struct sockaddr_in sin; int p[2], logging, secure, sval; #define ENTRIES 50 char **ap, *av[ENTRIES + 1], line[1024], *prog; extern char *optarg; extern int opterr; prog = _PATH_FINGER; logging = secure = 0; openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON); opterr = 0; while ((ch = getopt(argc, argv, "slp:")) != EOF) { switch (ch) { case 'l': logging = 1; break; case 'p': prog = optarg; break; case 's': secure = 1; break; case '?': default: err("illegal option -- %c", ch); } } if (logging) { sval = sizeof(sin); if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0) err("getpeername: %s", strerror(errno)); if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr, sizeof(sin.sin_addr.s_addr), AF_INET)) lp = hp->h_name; else lp = inet_ntoa(sin.sin_addr); syslog(LOG_NOTICE, "query from %s", lp); } if (!fgets(line, sizeof(line), stdin)) exit(1); /* * SGI/McVoy extended finger protocol: * * [/W] user [user2 user3 user4] [-a [-b [-c [-d]]]] * * where user may be user@host and the options are intended * for the local finger. */ /* * Get rid of that /w, it complicates things. * We pick it up if it is there and translate to white space. */ av[argc = 1] = 0; for (lp = line; *lp && *lp != '/'; lp++) { if ((lp == line || isspace(lp[-1])) && (lp[1] == 'w' || lp[1] == 'W') && (lp[2] == 0 || isspace(lp[2]))) { av[argc++] = "-l"; lp[0] = lp[1] = ' '; } } /* * Pull options from the tail first. * * Careful to find an option that is not part of a user name. */ for (lp = &line[-1]; lp[1] && (lp = strchr(&lp[1], '-')); ) { /* * Options at the beginning or w/o a preceeding space are * not options. */ if ((lp == line) || !isspace(lp[-1])) continue; lp[-1] = 0; for (ap = &av[argc]; ; ) { *ap = strtok(lp, " \t\r\n"); if (!*ap || ++ap == av + ENTRIES) break; argc++; lp = NULL; } break; /* we wanted the first valid one only */ } /* * Snarf up the users. */ for (lp = line, ap = &av[argc];;) { *ap = strtok(lp, " \t\r\n"); if (!*ap) { if (secure && ap == &av[argc]) { puts("must provide username\r\n"); exit(1); } break; } if (secure && strchr(*ap, '@')) { puts("fowarding service denied\r\n"); exit(1); } if (++ap == av + ENTRIES) break; lp = NULL; } if (lp = strrchr(prog, '/')) av[0] = ++lp; else av[0] = prog; if (pipe(p) < 0) err("pipe: %s", strerror(errno)); switch(vfork()) { case 0: (void)close(p[0]); if (p[1] != 1) { (void)dup2(p[1], 1); (void)close(p[1]); } #if 1 write(0, "<<", 2); for (argc = 0; av[argc]; ++argc) { write(0, av[argc], strlen(av[argc])); if (av[argc+1]) write(0, " ", 1); } write(0, ">>\n\r", 4); #endif execv(prog, av); err("execv: %s: %s", prog, strerror(errno)); _exit(1); case -1: err("fork: %s", strerror(errno)); } (void)close(p[1]); if (!(fp = fdopen(p[0], "r"))) err("fdopen: %s", strerror(errno)); while ((ch = getc(fp)) != EOF) { if (ch == '\n') putchar('\r'); putchar(ch); } exit(0); } #if __STDC__ #include <stdarg.h> #else #include <varargs.h> #endif void #if __STDC__ err(const char *fmt, ...) #else err(fmt, va_alist) char *fmt; va_dcl #endif { va_list ap; #if __STDC__ va_start(ap, fmt); #else va_start(ap); #endif (void)vsyslog(LOG_ERR, fmt, ap); va_end(ap); exit(1); /* NOTREACHED */ }