home *** CD-ROM | disk | FTP | other *** search
- /*
- * fingerd.c - finger server
- * Barry Shein/Phil Budne, Boston University
- *
- * Should conform to RFC742 (which is a pretty vague thing)
- *
- * Copyright (c) 1986, 1990 Barry Z. Shein & Philip L. Budne
- */
-
- # ifndef lint
- static char *rcsid = "$Id: fingerd.c,v 3.0 90/07/06 13:10:44 budd Rel $";
- # endif /* lint not defined */
-
- # include "finger.h"
-
- # include <stdio.h>
- # include <sys/types.h>
- # include <netinet/in.h> /* sockaddr_in, IPPORT_FINGER */
- # include <sys/socket.h> /* AF_... */
- # include <strings.h> /* index */
- # include <errno.h> /* EINTR */
- # include <pwd.h> /* lookup nobody */
-
- # ifndef INETD
- # include <sys/ioctl.h> /* TIOCNOTTY */
- # include <signal.h> /* SIGCHLD */
- # ifndef NO_WAIT_H
- # include <sys/wait.h> /* WNOHANG... */
- # endif /* NO_WAIT_H not defined */
-
- FORWARD LOCAL void fireman();
- # endif /* INETD not defined */
-
- /*
- * BZS - optional SYSLOG'ing of connections
- */
- # ifdef SYSLOG
- # include <syslog.h> /* LOG_... */
- # include <netdb.h> /* gethostbyaddr */
-
- FORWARD LOCAL void logit();
- # endif /* SYSLOG defined */
-
- # ifdef USG
- # define vfork fork
- # endif /* USG defined */
-
- # ifndef MONNAME /* ie SYSTEM:MONNAM.TXT */
- # define MONNAME "/etc/monnam" /* System name */
- # endif /* MONNAME not defined */
-
- # ifndef NOLOGIN
- # define NOLOGIN "/etc/nologin"
- # endif /* NOLOGIN not defined */
-
- # define SERVICE "finger" /* for getservent */
- # define PROTOCOL "tcp"
-
- # ifndef IPPORT_FINGER /* if services deficient */
- # define IPPORT_FINGER 79 /* usually in netinet/in.h */
- # endif /* IPPORT_FINGER not defined */
-
- # ifndef UID_NOBODY
- # define UID_NOBODY -2
- # endif /* UID_NOBODY not defined */
-
- # ifndef USER_NOBODY
- # define USER_NOBODY "nobody"
- # endif /* USER_NOBODY not defined */
-
-
- # define BACKLOG 5 /* max under 4.2 */
-
- /*
- * Arbitrary...
- */
- # define MAXNAMES 100
- # define MAXHERALD 100
-
- /****************************************************************/
-
- # ifdef UTSNAME
- # include <sys/utsname.h>
- # else /* UTSNAME not defined */
-
- /* perhaps ARCHITECTURE should be split into MFGR and MACHINE? */
-
- # ifdef sun
- # ifdef mc68010
- # define ARCHITECTURE "Sun-2"
- # endif /* mc68010 defined */
- # ifdef mc68020
- # define ARCHITECTURE "Sun-3"
- # endif /* mc68020 defined */
- # ifdef sparc
- # define ARCHITECTURE "Sun-4"
- # endif /* sparc defined */
- # ifdef i386
- # define ARCHITECTURE "Sun 386i" /* "Road Runner"? */
- # endif /* i386 defined */
- # ifndef ARCHITECTURE
- # define ARCHITECTURE "Sun"
- # endif /* ARCHITECTURE not defined */
- # endif /* sun defined */
-
- # ifdef ibm032
- # define ARCHITECTURE "IBM ROMP"
- # endif /* ibm032 defined */
-
- # ifdef u3b
- # define ARCHITECTURE "AT&T 3B"
- # endif /* u3b defined */
-
- # ifdef u370
- # define ARCHITECTURE "IBM S/370"
- # endif /* u370 defined */
-
- # ifdef pdp11
- # define ARCHITECTURE "PDP-11"
- # endif /* pdp11 defined */
-
- # ifdef accel
- # define ARCHITECTURE "Celerity Accel"
- # endif /* accel defined */
-
- # ifndef ARCHITECTURE
-
- # ifdef vax
- # define ARCHITECTURE "VAX"
- # endif /* vax defined */
-
- # if defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332)
- # define ARCHITECTURE "NS32k"
- # endif /* defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332) */
-
- # ifdef mips
- # define ARCHITECTURE "MIPS"
- # endif /* mips defined */
-
- # ifdef sparc
- # define ARCHITECTURE "SPARC"
- # endif /* sparc defined */
-
- # if defined(mc68000) || defined(mc68020)
- # define ARCHITECTURE "MC68k"
- # endif /* defined(mc68000) || defined(mc68020) */
-
- # ifdef i386
- # define ARCHITECTURE "i386"
- # endif /* i386 defined */
-
- # endif /* ARCHITECTURE not defined */
-
- /****************************************************************/
-
- # ifdef bsd4_3
- # define DEFHERALD "4.3 BSD"
- # endif /* bsd4_3 defined */
-
- # if SunOS >= 400
- # define DEFHERALD "SunOS 4.0" /* 4.1 has uname(2) */
- # endif /* SunOS >= 400 */
-
- # ifdef USG
- # define DEFHERALD "USG"
- # endif /* USG defined */
-
- # ifdef sequent
- # define DEFHERALD "Sequent Dynix"
- # endif /* sequent defined */
-
- # if Umax == 42
- # define DEFHERALD "Encore Umax 4.2"
- # endif /* Umax == 42 */
-
- # if Umax == 43
- # define DEFHERALD "Encore Umax 4.3"
- # endif /* Umax == 43 */
-
- # ifdef ultrix /* Digital's big ideas */
-
- # define DEFHERALD "Ultrix" /* Ultrix has uname(2) */
- # endif /* ultrix defined */
-
- # ifdef sony_news
- # define DEFHERALD "Sony NewsOS"
- # endif /* sony_news defined */
-
- # ifndef DEFHERALD /* the default default herald!! */
- # define DEFHERALD "4.2 BSD"
- # endif /* DEFHERALD not defined */
-
- # endif /* UTSNAME not defined */
-
- char herald[MAXHERALD];
- extern int errno, sys_nerr;
- char *sys_errlist[];
-
- /*
- * Program we will fork to actually do the lookups
- */
- char *fingerpaths[] = {
- # ifdef FINGERPATHS
- FINGERPATHS , /* alternate finger paths */
- # endif /* FINGERPATHS defined */
- "/usr/local/bin/finger",
- "/usr/local/finger",
- "/usr/bin/finger",
- "/usr/ucb/finger",
-
- "/usr/local/bin/xf",
- "/usr/local/xf",
- "/usr/bin/xf",
- "/usr/ucb/xf",
-
- "/usr/ucb/w",
- "/bin/who",
- NULL
- };
-
- /* argv[0] for above
- # ifndef FINGER0
- # define FINGER0 "finger"
- # endif /* FINGER0 not defined */
-
- /*
- * Program to print pretty hello message
- */
-
- # ifndef UPTIME
- # define UPTIME "/usr/ucb/uptime" /* define this to print ldav, uptime */
- # endif /* UPTIME not defined */
-
- # ifndef UPTIME0
- # define UPTIME0 "uptime"
- # endif /* UPTIME0 not defined */
-
- int debug;
-
- FORWARD LOCAL void Perror(), fperror(), iniherald(), doit(), pherald();
-
- int main( argc, argv )
- int argc;
- char *argv[];
- {
- # ifdef INETD
- iniherald();
- doit( 0 );
- exit( 0 );
- # else /* INETD not defined */
- int i, f;
-
- iniherald();
- /*
- * skip detaching the tty if first arg '-d'
- */
- if( (argc > 1) && (argv[1][0] == '-') && (argv[1][1] == 'd'))
- debug = 1;
- else
- debug = 0;
-
- /*
- * After forking, child detaches controlling
- * terminal, parent exits, we are free
- */
- if( !debug ) {
- switch( fork() ) {
- case 0: /* parent */
- exit( 0 );
-
- case -1:
- Perror( "fork1" );
- } /* switch */
-
- # ifdef USG
- f = 32; /* FIXME! */
- # else /* USG not defined */
- f = getdtablesize();
- # endif /* USG not defined */
- for( i = 0; i < f; i++ )
- (void) close( i );
-
- /*
- * No one can hear you scream in space....
- */
- (void) open("/", 1);
- # ifdef USG /* FIXME! */
- (void) dup( 0 );
- (void) dup( 0 );
- # else /* USG not defined */
- (void) dup2(0, 1);
- (void) dup2(0, 2);
- # endif /* USG not defined */
-
- # ifdef TIOCNOTTY
- if( (i = open("/dev/tty",2)) >= 0 ) {
- (void) ioctl(i,TIOCNOTTY,0);
- (void) close(i);
- } /* tty open */
- # endif /* TIOCNOTTY defined */
- # ifdef USG
- setpgrp();
- # endif /* USG defined */
- } /* not debug */
-
- signal(SIGCHLD, fireman);
- f = getsocket();
- listen(f,BACKLOG);
- for( ; ; ) {
- int g, szfrom;
- struct sockaddr_in from;
-
- szfrom = sizeof( from );
- if( (g = accept(f, &from, &szfrom)) < 0 ) {
- if(errno != EINTR)
- Perror("accept");
- continue;
- } /* accept */
- switch( fork() ) {
- case 0:
- (void) close( f );
- doit( g );
- exit( 1 ); /* SHOULDNT HAPPEN */
-
- case -1:
- Perror( "fork2" );
- break;
- } /* fork switch */
- (void) close(g);
- } /* for ever */
- /*NOTREACHED*/
- # endif /* INETD not defined */
- return( 0 ); /* be ANSI, keep gcc quiet! */
- } /* main */
-
- /*
- * doit -- forked to actually satisfy request
- */
- LOCAL void doit( s )
- int s;
- {
- char buf[BUFSIZ+1];
- char *av[MAXNAMES+2], *ep[1];
- register int i;
- register char *bp, **pp;
- int uid = UID_NOBODY;
- # ifdef USER_NOBODY
- struct passwd *pw;
- # endif /* USER_NOBODY defined */
-
- (void) dup2( s, 1 ); /* dup socket onto stdout */
- (void) dup2( s, 2 ); /* and stderr */
- pherald();
-
- /*
- * Note: this assumes request is sent in one shot
- * which is consistent with RFC742.
- *
- * Never used gets() so never had worm hole!!
- */
- if( (i = read( s, buf, BUFSIZ)) < 0 )
- fperror("could not read request");
- buf[i] = EOS; /* tie off buf */
-
- /*
- * Make an argv list breaking at any space or ctrl chars
- * This is slightly more liberal than RFC742:
- * name,name,name is ok (RFC742)
- * so is
- * name name name
- * and by default things like:
- * name\nname\n
- * name\r\nname\r\n
- */
- i = 1;
- bp = buf;
- while( *bp != EOS ) {
- while( (*bp <= ' ') || (*bp == ',') ) {
- if(*bp == EOS)
- break;
- else
- *bp = EOS;
- bp++;
- } /* while non print or comma */
- if(*bp == EOS)
- break;
- av[i++] = bp;
- if(i == MAXNAMES)
- break;
- while((*bp > ' ') && (*bp != ','))
- bp++;
- } /* while bp */
- av[i] = NULL; /* tie off argv */
- ep[0] = NULL; /* null environment */
-
- # ifdef SYSLOG
- logit( s, av);
- # endif /* SYSLOG defined */
-
- # ifdef USER_NOBODY
- if( (pw = getpwnam( USER_NOBODY )) != NULL )
- uid = pw->pw_uid;
- # endif /* USER_NOBODY defined */
- setuid( uid ); /* become noone -- so we are under */
- /* control of maxuprc */
-
- for( pp = fingerpaths; *pp != NULL; pp++ ) {
- av[0] = *pp;
- execv(*pp, av);
- } /* for fingerpaths */
- /*
- * ERROR
- */
- puts("Could not find local finger program.");
- fflush( stdout );
- # ifdef SYSLOG
- syslog( LOG_ERR, "Could not find local finger program" );
- # endif /* SYSLOG defined */
- _exit( 1 );
- } /* doit */
-
- LOCAL void pherald() { /* print herald */
- int fk;
- FILE *fd;
- char *ep[1];
-
- ep[0] = NULL;
- printf( "%s\r\n", herald );
- fflush( stdout );
-
- # ifdef UPTIME
- if( (fk = vfork()) == 0 ) {
- execl(UPTIME, UPTIME0, 0 );
- fperror(UPTIME);
- }
- else if( fk != -1 ) {
- int wf;
- while( (wf = wait(0)) != -1 && (wf != fk) )
- ;
- putchar( '\r' ); /* assume last char was \n */
- }
- else
- Perror("fork3");
- # endif /* UPTIME defined */
-
- # ifdef NOLOGIN
- if( (fd = fopen(NOLOGIN, "r")) != NULL ) {
- register c, lc;
-
- fputs( "\r\nNo Logins:\r\n", stdout );
-
- lc = -1; /* zap last char */
- while( (c = getc( fd )) != EOF ) {
- if( c == '\n' )
- putchar( '\r' );
- putchar( c ); /* output char */
- lc = c; /* save it */
- } /* while */
- fclose( fd ); /* close file */
-
- if( lc != '\n' ) { /* was last a newline? */
- putchar( '\r' );
- putchar( '\n' ); /* no, output one now */
- }
-
- /* WISH: perhaps print /etc/motd here too? */
- } /* opened NOLOGIN */
- # endif /* NOLOGIN defined */
-
- putchar( '\r' );
- putchar( '\n' ); /* blank line */
- fflush( stdout );
- } /* pherald */
-
- LOCAL void iniherald() { /* create herald string once */
- int f;
- char namebuf[200];
- # ifdef UTSNAME
- struct utsname uts;
-
- uname( &uts );
- strcpy( herald, uts.nodename );
- # else /* UTSNAME not defined */
- char myname[MAXHOSTLEN];
-
- gethostname(myname, sizeof( myname ) );
- strcpy(herald, myname );
- # endif /* UTSNAME not defined */
- strcat(herald, " -- ");
-
- if( (f = open(MONNAME, 0)) >= 0 &&
- read(f, namebuf, sizeof( namebuf) -1 ) > 0 ) {
- char *cp;
-
- if( (cp = index(namebuf, '\n')) != NULL )
- *cp = EOS;
-
- strcat(herald, namebuf);
- close( f );
- } /* got MONNAME */
- else {
- # ifdef UTSNAME
- strcat(herald, uts.machine);
- if( strcmp( uts.sysname, uts.nodename ) != 0 ) { /* SVR2?! */
- strcat(herald, " " );
- strcat(herald, uts.sysname );
- }
- strcat(herald, " release " );
- strcat(herald, uts.release );
- # ifdef UmaxV
- if( strcmp( uts.release, uts.version ) != 0 )
- # endif /* UmaxV defined */
- strcat(herald, " version " ),
- strcat(herald, uts.version );
- # else /* UTSNAME not defined */
- strcat(herald, DEFHERALD );
- # ifdef ARCHITECTURE
- strcat(herald, " " );
- strcat(herald, ARCHITECTURE );
- # endif /* ARCHITECTURE defined */
- # endif /* UTSNAME not defined */
- } /* no MONNAME */
- } /* iniherald */
-
- # ifndef INETD
- getsocket() {
- int f;
- struct servent *sp;
- struct sockaddr_in sin;
-
- bzero(&sin,sizeof sin);
- sin.sin_family = AF_INET;
-
- if( (sp = getservbyname( SERVICE, PROTOCOL )) == NULL)
- sin.sin_port = sp->s_port;
- else
- sin.sin_port = htons( IPPORT_FINGER );
-
- if( (f = socket(AF_INET,SOCK_STREAM,0)) < 0)
- fperror("socket");
-
- if(bind(f,(caddr_t)&sin,sizeof sin,0) < 0)
- fperror("bind");
-
- return( f );
- } /* getsocket */
-
- LOCAL void fireman() { /* catch falling babies */
- # ifdef NO_WAIT_H
- int w;
-
- while( wait(&w) > 0 )
- ;
- # else /* NO_WAIT_H not defined */
- union wait status;
-
- while( wait3( &status, WNOHANG|WUNTRACED, 0) > 0 )
- ;
- # endif /* NO_WAIT_H not defined */
- } /* catchchild */
- # endif /* INETD not defined */
-
- # ifdef SYSLOG
- LOCAL void logit(s, av)
- int s;
- register char **av;
- {
- int i;
- struct hostent *hp;
- char buffer[ 1024 ];
- struct sockaddr_in peer;
- char *name, *inet_ntoa();
-
- i = sizeof( peer );
- if( getpeername( s, &peer, &i) != 0 )
- return;
-
- # ifdef LOG_DAEMON
- if( openlog( "fingerd", 0, LOG_DAEMON ) != 0 )
- return;
- # else /* LOG_DAEMON not defined */
- if( openlog( "fingerd", 0) != 0 )
- return;
- # endif /* LOG_DAEMON not defined */
-
- hp = gethostbyaddr( (char *)&peer.sin_addr, sizeof(peer.sin_addr), AF_INET);
- if( hp == NULL)
- name = inet_ntoa( peer.sin_addr );
- else
- name = hp->h_name;
-
- buffer[0] = EOS;
- av++; /* skip argv[0] */
- while( *av != NULL ) {
- if( buffer[0] != EOS )
- strcat( buffer, " " );
- strcat( buffer, *av++ );
- } /* while av */
-
- syslog( LOG_INFO, "%s: '%s'", name, buffer );
- } /* logit */
- # endif /* SYSLOG defined */
-
- LOCAL void Perror( s ) /* print error */
- char *s;
- {
- # ifdef SYSLOG
- syslog( LOG_ERR, "%s: %m", s );
- # endif /* SYSLOG defined */
-
- if( errno < 1 || errno > sys_nerr )
- fprintf( stderr, "fingerd: %s -- error %d\n", s, errno );
- else
- fprintf( stderr, "fingerd: %s -- %s\n", s, sys_errlist[ errno ] );
- } /* Perror */
-
- LOCAL void fperror( s ) /* fatal Perror */
- char *s;
- {
- Perror( s );
- exit( 1 );
- }/* fperror */
-
- /*
- * Local variables:
- * comment-column: 40
- * End:
- */
-