home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / finger / part06 / fingerd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-03  |  13.5 KB  |  629 lines

  1. /*
  2.  *    fingerd.c - finger server
  3.  *    Barry Shein/Phil Budne, Boston University
  4.  *
  5.  *    Should conform to RFC742 (which is a pretty vague thing)
  6.  *
  7.  *    Copyright (c) 1986, 1990 Barry Z. Shein & Philip L. Budne
  8.  */
  9.  
  10. # ifndef lint
  11. static char *rcsid = "$Id: fingerd.c,v 3.0 90/07/06 13:10:44 budd Rel $";
  12. # endif /* lint not defined */
  13.  
  14. # include "finger.h"
  15.  
  16. # include <stdio.h>
  17. # include <sys/types.h>
  18. # include <netinet/in.h>        /* sockaddr_in, IPPORT_FINGER */
  19. # include <sys/socket.h>        /* AF_... */
  20. # include <strings.h>            /* index */
  21. # include <errno.h>            /* EINTR */
  22. # include <pwd.h>            /* lookup nobody */
  23.  
  24. # ifndef INETD
  25. # include <sys/ioctl.h>            /* TIOCNOTTY */
  26. # include <signal.h>            /* SIGCHLD */
  27. # ifndef NO_WAIT_H
  28. # include <sys/wait.h>            /* WNOHANG... */
  29. # endif /* NO_WAIT_H not defined */
  30.  
  31. FORWARD LOCAL void fireman();
  32. # endif /* INETD not defined */
  33.  
  34. /*
  35.  *    BZS - optional SYSLOG'ing of connections
  36.  */
  37. # ifdef SYSLOG
  38. # include <syslog.h>            /* LOG_... */
  39. # include <netdb.h>            /* gethostbyaddr */
  40.  
  41. FORWARD LOCAL void logit();
  42. # endif /* SYSLOG defined */
  43.  
  44. # ifdef USG
  45. # define vfork fork
  46. # endif /* USG defined */
  47.  
  48. # ifndef MONNAME            /* ie SYSTEM:MONNAM.TXT */
  49. # define MONNAME "/etc/monnam"        /* System name */
  50. # endif /* MONNAME not defined */
  51.  
  52. # ifndef NOLOGIN
  53. # define NOLOGIN "/etc/nologin"
  54. # endif /* NOLOGIN not defined */
  55.  
  56. # define SERVICE "finger"        /* for getservent */
  57. # define PROTOCOL "tcp"
  58.  
  59. # ifndef IPPORT_FINGER            /* if services deficient */
  60. # define IPPORT_FINGER 79        /* usually in netinet/in.h */
  61. # endif /* IPPORT_FINGER not defined */
  62.  
  63. # ifndef UID_NOBODY
  64. # define UID_NOBODY -2
  65. # endif /* UID_NOBODY not defined */
  66.  
  67. # ifndef USER_NOBODY
  68. # define USER_NOBODY "nobody"
  69. # endif /* USER_NOBODY not defined */
  70.  
  71.  
  72. # define BACKLOG 5            /* max under 4.2 */
  73.  
  74. /*
  75.  *    Arbitrary...
  76.  */
  77. # define MAXNAMES 100
  78. # define MAXHERALD 100
  79.  
  80. /****************************************************************/
  81.  
  82. # ifdef UTSNAME
  83. # include <sys/utsname.h>
  84. # else  /* UTSNAME not defined */
  85.  
  86. /* perhaps ARCHITECTURE should be split into MFGR and MACHINE? */
  87.  
  88. # ifdef sun
  89. # ifdef mc68010
  90. # define ARCHITECTURE "Sun-2"
  91. # endif /* mc68010 defined */
  92. # ifdef mc68020
  93. # define ARCHITECTURE "Sun-3"
  94. # endif /* mc68020 defined */
  95. # ifdef sparc
  96. # define ARCHITECTURE "Sun-4"
  97. # endif /* sparc defined */
  98. # ifdef i386
  99. # define ARCHITECTURE "Sun 386i"    /* "Road Runner"? */
  100. # endif /* i386 defined */
  101. # ifndef ARCHITECTURE
  102. # define ARCHITECTURE "Sun"
  103. # endif /* ARCHITECTURE not defined */
  104. # endif /* sun defined */
  105.  
  106. # ifdef ibm032
  107. # define ARCHITECTURE "IBM ROMP"
  108. # endif /* ibm032 defined */
  109.  
  110. # ifdef u3b
  111. # define ARCHITECTURE "AT&T 3B"
  112. # endif /* u3b defined */
  113.  
  114. # ifdef u370
  115. # define ARCHITECTURE "IBM S/370"
  116. # endif /* u370 defined */
  117.  
  118. # ifdef pdp11
  119. # define ARCHITECTURE "PDP-11"
  120. # endif /* pdp11 defined */
  121.  
  122. # ifdef accel
  123. # define ARCHITECTURE "Celerity Accel"
  124. # endif /* accel defined */
  125.  
  126. # ifndef ARCHITECTURE
  127.  
  128. # ifdef vax
  129. # define ARCHITECTURE "VAX"
  130. # endif /* vax defined */
  131.  
  132. # if defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332)
  133. # define ARCHITECTURE "NS32k"
  134. # endif /* defined(n16) || defined(ns32000) || defined(ns32032) || defined(ns32332) */
  135.  
  136. # ifdef mips
  137. # define ARCHITECTURE "MIPS"
  138. # endif /* mips defined */
  139.  
  140. # ifdef sparc
  141. # define ARCHITECTURE "SPARC"
  142. # endif /* sparc defined */
  143.  
  144. # if defined(mc68000) || defined(mc68020)
  145. # define ARCHITECTURE "MC68k"
  146. # endif /* defined(mc68000) || defined(mc68020) */
  147.  
  148. # ifdef i386
  149. # define ARCHITECTURE "i386"
  150. # endif /* i386 defined */
  151.  
  152. # endif /* ARCHITECTURE not defined */
  153.  
  154. /****************************************************************/
  155.  
  156. # ifdef bsd4_3
  157. # define DEFHERALD "4.3 BSD"
  158. # endif /* bsd4_3 defined */
  159.  
  160. # if SunOS >= 400
  161. # define DEFHERALD "SunOS 4.0"        /* 4.1 has uname(2) */
  162. # endif /* SunOS >= 400 */
  163.  
  164. # ifdef USG
  165. # define DEFHERALD "USG"
  166. # endif /* USG defined */
  167.  
  168. # ifdef sequent
  169. # define DEFHERALD "Sequent Dynix"
  170. # endif /* sequent defined */
  171.  
  172. # if Umax == 42
  173. # define DEFHERALD "Encore Umax 4.2"
  174. # endif /* Umax == 42 */
  175.  
  176. # if Umax == 43
  177. # define DEFHERALD "Encore Umax 4.3"
  178. # endif /* Umax == 43 */
  179.  
  180. # ifdef ultrix                /* Digital's big ideas */
  181.  
  182. # define DEFHERALD "Ultrix"        /* Ultrix has uname(2) */
  183. # endif /* ultrix defined */
  184.  
  185. # ifdef sony_news
  186. # define DEFHERALD "Sony NewsOS"
  187. # endif /* sony_news defined */
  188.  
  189. # ifndef DEFHERALD            /* the default default herald!! */
  190. # define DEFHERALD "4.2 BSD"
  191. # endif /* DEFHERALD not defined */
  192.  
  193. # endif /* UTSNAME not defined */
  194.  
  195. char herald[MAXHERALD];
  196. extern int errno, sys_nerr;
  197. char *sys_errlist[];
  198.  
  199. /*
  200.  *    Program we will fork to actually do the lookups
  201.  */
  202. char *fingerpaths[] = {
  203. # ifdef FINGERPATHS
  204.     FINGERPATHS ,            /* alternate finger paths */
  205. # endif /* FINGERPATHS defined */
  206.     "/usr/local/bin/finger",
  207.     "/usr/local/finger",
  208.     "/usr/bin/finger",
  209.     "/usr/ucb/finger",
  210.  
  211.     "/usr/local/bin/xf",
  212.     "/usr/local/xf",
  213.     "/usr/bin/xf",
  214.     "/usr/ucb/xf",
  215.  
  216.     "/usr/ucb/w",
  217.     "/bin/who",
  218.     NULL
  219. };
  220.  
  221. /* argv[0] for above
  222. # ifndef FINGER0
  223. # define FINGER0 "finger"
  224. # endif /* FINGER0 not defined */
  225.  
  226. /*
  227.  *    Program to print pretty hello message
  228.  */
  229.  
  230. # ifndef UPTIME
  231. # define UPTIME "/usr/ucb/uptime"    /* define this to print ldav, uptime */
  232. # endif /* UPTIME not defined */
  233.  
  234. # ifndef UPTIME0
  235. # define UPTIME0 "uptime"
  236. # endif /* UPTIME0 not defined */
  237.  
  238. int debug;
  239.  
  240. FORWARD LOCAL void Perror(), fperror(), iniherald(), doit(), pherald();
  241.  
  242. int main( argc, argv )
  243.     int argc;
  244.     char *argv[];
  245. {
  246. # ifdef INETD
  247.     iniherald();
  248.     doit( 0 );
  249.     exit( 0 );
  250. # else  /* INETD not defined */
  251.     int i, f;
  252.  
  253.     iniherald();
  254.     /*
  255.      *    skip detaching the tty if first arg '-d'
  256.      */
  257.     if( (argc > 1)  && (argv[1][0] == '-') && (argv[1][1] == 'd'))
  258.     debug = 1;
  259.     else
  260.     debug = 0;
  261.  
  262.     /*
  263.      *    After forking, child detaches controlling
  264.      *    terminal, parent exits, we are free
  265.      */
  266.     if( !debug ) {
  267.     switch( fork() ) {
  268.     case 0:                /* parent */
  269.         exit( 0 );
  270.  
  271.     case -1:
  272.         Perror( "fork1" );
  273.     } /* switch */
  274.  
  275. # ifdef USG
  276.     f = 32;                /* FIXME! */
  277. # else  /* USG not defined */
  278.     f = getdtablesize();
  279. # endif /* USG not defined */
  280.     for( i = 0; i < f; i++ )
  281.         (void) close( i );
  282.  
  283.     /*
  284.      *    No one can hear you scream in space....
  285.      */
  286.     (void) open("/", 1);
  287. # ifdef USG                /* FIXME! */
  288.     (void) dup( 0 );
  289.     (void) dup( 0 );
  290. # else  /* USG not defined */
  291.     (void) dup2(0, 1);
  292.     (void) dup2(0, 2);
  293. # endif /* USG not defined */
  294.  
  295. # ifdef TIOCNOTTY
  296.     if( (i = open("/dev/tty",2)) >= 0 ) {
  297.         (void) ioctl(i,TIOCNOTTY,0);
  298.         (void) close(i);
  299.     } /* tty open */
  300. # endif /* TIOCNOTTY defined */
  301. # ifdef USG
  302.     setpgrp();
  303. # endif /* USG defined */
  304.     } /* not debug */
  305.  
  306.     signal(SIGCHLD, fireman);
  307.     f = getsocket();
  308.     listen(f,BACKLOG);
  309.     for( ; ; ) {
  310.     int  g, szfrom;
  311.     struct sockaddr_in from;
  312.  
  313.     szfrom = sizeof( from );
  314.     if( (g = accept(f, &from, &szfrom)) < 0 ) {
  315.         if(errno != EINTR)
  316.         Perror("accept");
  317.         continue;
  318.     } /* accept */
  319.     switch( fork() ) {
  320.     case 0:
  321.         (void) close( f );
  322.         doit( g );
  323.         exit( 1 );            /* SHOULDNT HAPPEN */
  324.  
  325.     case -1:
  326.         Perror( "fork2" );
  327.         break;
  328.     } /* fork switch */
  329.     (void) close(g);
  330.     } /* for ever */
  331.     /*NOTREACHED*/
  332. # endif /* INETD not defined */
  333.     return( 0 );            /* be ANSI, keep gcc quiet! */
  334. } /* main */
  335.  
  336. /*
  337.  *    doit -- forked to actually satisfy request
  338.  */
  339. LOCAL void doit( s )
  340.     int s;
  341. {
  342.     char buf[BUFSIZ+1];
  343.     char *av[MAXNAMES+2], *ep[1];
  344.     register int i;
  345.     register char *bp, **pp;
  346.     int uid = UID_NOBODY;
  347. # ifdef USER_NOBODY
  348.     struct passwd *pw;
  349. # endif /* USER_NOBODY defined */
  350.         
  351.     (void) dup2( s, 1 );        /* dup socket onto stdout */
  352.     (void) dup2( s, 2 );        /* and stderr */
  353.     pherald();
  354.  
  355.     /*
  356.      *    Note: this assumes request is sent in one shot
  357.      *    which is consistent with RFC742.
  358.      *
  359.      *  Never used gets() so never had worm hole!!
  360.      */
  361.     if( (i = read( s, buf, BUFSIZ)) < 0 )
  362.     fperror("could not read request");
  363.     buf[i] = EOS;            /* tie off buf */
  364.  
  365.     /*
  366.      *    Make an argv list breaking at any space or ctrl chars
  367.      *    This is slightly more liberal than RFC742:
  368.      *        name,name,name is ok (RFC742)
  369.      *    so is
  370.      *        name name name
  371.      *    and by default things like:
  372.      *        name\nname\n
  373.      *        name\r\nname\r\n
  374.      */
  375.     i = 1;
  376.     bp = buf;
  377.     while( *bp != EOS ) {
  378.     while( (*bp <= ' ') || (*bp == ',') ) {
  379.         if(*bp == EOS)
  380.         break;
  381.         else
  382.         *bp = EOS;
  383.         bp++;
  384.     } /* while non print or comma */
  385.     if(*bp == EOS)
  386.         break;
  387.     av[i++] = bp;
  388.     if(i == MAXNAMES)
  389.         break;
  390.     while((*bp > ' ') && (*bp != ','))
  391.         bp++;
  392.     } /* while bp */
  393.     av[i] = NULL;            /* tie off argv */
  394.     ep[0] = NULL;            /* null environment */
  395.  
  396. # ifdef SYSLOG
  397.     logit( s, av);
  398. # endif /* SYSLOG defined */
  399.  
  400. # ifdef USER_NOBODY
  401.     if( (pw = getpwnam( USER_NOBODY )) != NULL )
  402.     uid = pw->pw_uid;
  403. # endif /* USER_NOBODY defined */
  404.     setuid( uid );            /* become noone --  so we are under */
  405.                     /* control of maxuprc */
  406.  
  407.     for( pp = fingerpaths; *pp != NULL; pp++ ) {
  408.     av[0] = *pp;
  409.     execv(*pp, av);
  410.     } /* for fingerpaths */
  411.     /*
  412.      *    ERROR
  413.      */
  414.     puts("Could not find local finger program.");
  415.     fflush( stdout );
  416. # ifdef SYSLOG
  417.     syslog( LOG_ERR, "Could not find local finger program" );
  418. # endif /* SYSLOG defined */
  419.     _exit( 1 );
  420. } /* doit */
  421.  
  422. LOCAL void pherald() {            /* print herald */
  423.     int fk;
  424.     FILE *fd;
  425.     char *ep[1];
  426.  
  427.     ep[0] = NULL;
  428.     printf( "%s\r\n", herald );
  429.     fflush( stdout );
  430.  
  431. # ifdef UPTIME
  432.     if( (fk = vfork()) == 0 ) {
  433.     execl(UPTIME, UPTIME0, 0 );
  434.     fperror(UPTIME);
  435.     }
  436.     else if( fk != -1 ) {
  437.     int wf;
  438.     while( (wf = wait(0)) != -1 && (wf != fk) )
  439.        ;
  440.     putchar( '\r' );        /* assume last char was \n */
  441.     }
  442.     else
  443.     Perror("fork3");
  444. # endif /* UPTIME defined */
  445.  
  446. # ifdef NOLOGIN
  447.     if( (fd = fopen(NOLOGIN, "r")) != NULL ) {
  448.     register c, lc;
  449.  
  450.     fputs( "\r\nNo Logins:\r\n", stdout );
  451.  
  452.     lc = -1;            /* zap last char */
  453.     while( (c = getc( fd )) != EOF ) {
  454.         if( c == '\n' )
  455.         putchar( '\r' );
  456.         putchar( c );        /* output char */
  457.         lc = c;            /* save it */
  458.     } /* while */
  459.     fclose( fd );            /* close file */
  460.  
  461.     if( lc != '\n' ) {        /* was last a newline? */
  462.         putchar( '\r' );
  463.         putchar( '\n' );        /* no, output one now */
  464.     }
  465.  
  466.     /* WISH: perhaps print /etc/motd here too? */
  467.     } /* opened NOLOGIN */
  468. # endif /* NOLOGIN defined */
  469.  
  470.     putchar( '\r' );
  471.     putchar( '\n' );            /* blank line */
  472.     fflush( stdout );
  473. } /* pherald */
  474.  
  475. LOCAL void iniherald() {        /* create herald string once */
  476.     int f;
  477.     char namebuf[200];
  478. # ifdef UTSNAME
  479.     struct utsname uts;
  480.  
  481.     uname( &uts );
  482.     strcpy( herald, uts.nodename );
  483. # else  /* UTSNAME not defined */
  484.     char myname[MAXHOSTLEN];
  485.  
  486.     gethostname(myname, sizeof( myname ) );
  487.     strcpy(herald, myname );
  488. # endif /* UTSNAME not defined */
  489.     strcat(herald, " -- ");
  490.  
  491.     if( (f = open(MONNAME, 0)) >= 0 &&
  492.        read(f, namebuf, sizeof( namebuf) -1 ) > 0 ) {
  493.     char *cp;
  494.  
  495.     if( (cp = index(namebuf, '\n')) != NULL )
  496.         *cp = EOS;
  497.  
  498.     strcat(herald, namebuf);
  499.     close( f );
  500.     } /* got MONNAME */
  501.     else {
  502. # ifdef UTSNAME
  503.     strcat(herald, uts.machine);
  504.     if( strcmp( uts.sysname, uts.nodename ) != 0 ) { /* SVR2?! */
  505.         strcat(herald, " " );
  506.         strcat(herald, uts.sysname );
  507.     }
  508.     strcat(herald, " release " );
  509.     strcat(herald, uts.release );
  510. # ifdef UmaxV
  511.     if( strcmp( uts.release, uts.version ) != 0 )
  512. # endif /* UmaxV defined */
  513.         strcat(herald, " version " ),
  514.         strcat(herald, uts.version );
  515. # else  /* UTSNAME not defined */
  516.     strcat(herald, DEFHERALD );
  517. # ifdef ARCHITECTURE
  518.     strcat(herald, " " );
  519.     strcat(herald, ARCHITECTURE );
  520. # endif /* ARCHITECTURE defined */
  521. # endif /* UTSNAME not defined */
  522.     } /* no MONNAME */
  523. } /* iniherald */
  524.  
  525. # ifndef INETD
  526. getsocket() {
  527.     int f;
  528.     struct servent *sp;
  529.     struct sockaddr_in sin;
  530.       
  531.     bzero(&sin,sizeof sin);
  532.     sin.sin_family = AF_INET;
  533.  
  534.     if( (sp = getservbyname( SERVICE, PROTOCOL )) == NULL)
  535.     sin.sin_port = sp->s_port;
  536.     else
  537.     sin.sin_port = htons( IPPORT_FINGER );
  538.  
  539.     if( (f = socket(AF_INET,SOCK_STREAM,0)) < 0)
  540.     fperror("socket");
  541.  
  542.     if(bind(f,(caddr_t)&sin,sizeof sin,0) < 0)
  543.     fperror("bind");
  544.  
  545.     return( f );
  546. } /* getsocket */
  547.  
  548. LOCAL void fireman() {            /* catch falling babies */
  549. # ifdef NO_WAIT_H
  550.     int w;
  551.  
  552.     while( wait(&w) > 0 )
  553.     ;
  554. # else  /* NO_WAIT_H not defined */
  555.     union wait status;
  556.  
  557.     while( wait3( &status, WNOHANG|WUNTRACED, 0) > 0 )
  558.     ;
  559. # endif /* NO_WAIT_H not defined */
  560. } /* catchchild */
  561. # endif /* INETD not defined */
  562.  
  563. # ifdef SYSLOG
  564. LOCAL void logit(s, av)
  565.     int s;
  566.     register char **av;
  567. {
  568.     int i;
  569.     struct hostent *hp;
  570.     char buffer[ 1024 ];
  571.     struct sockaddr_in peer;
  572.     char *name, *inet_ntoa();
  573.  
  574.     i = sizeof( peer );
  575.     if( getpeername( s, &peer, &i) != 0 )
  576.     return;
  577.  
  578. # ifdef LOG_DAEMON
  579.     if( openlog( "fingerd", 0, LOG_DAEMON ) != 0 )
  580.     return;
  581. # else  /* LOG_DAEMON not defined */
  582.     if( openlog( "fingerd", 0) != 0 )
  583.     return;
  584. # endif /* LOG_DAEMON not defined */
  585.  
  586.     hp = gethostbyaddr( (char *)&peer.sin_addr, sizeof(peer.sin_addr), AF_INET);
  587.     if( hp == NULL)
  588.     name = inet_ntoa( peer.sin_addr );
  589.     else
  590.     name = hp->h_name;
  591.  
  592.     buffer[0] = EOS;
  593.     av++;                /* skip argv[0] */
  594.     while( *av != NULL ) {
  595.     if( buffer[0] != EOS )
  596.         strcat( buffer, " " );
  597.     strcat( buffer, *av++ );
  598.     } /* while av */
  599.  
  600.     syslog( LOG_INFO, "%s: '%s'", name, buffer );
  601. } /* logit */
  602. # endif /* SYSLOG defined */
  603.  
  604. LOCAL void Perror( s )            /* print error */
  605.     char *s;
  606. {
  607. # ifdef SYSLOG
  608.     syslog( LOG_ERR, "%s: %m", s );
  609. # endif /* SYSLOG defined */
  610.  
  611.     if( errno < 1 || errno > sys_nerr )
  612.     fprintf( stderr, "fingerd: %s -- error %d\n", s, errno );
  613.     else
  614.     fprintf( stderr, "fingerd: %s -- %s\n", s, sys_errlist[ errno ] );
  615. } /* Perror */
  616.  
  617. LOCAL void fperror( s )            /* fatal Perror */
  618.     char *s;
  619. {
  620.     Perror( s );
  621.     exit( 1 );
  622. }/* fperror */
  623.  
  624. /*
  625.  * Local variables:
  626.  * comment-column: 40
  627.  * End:
  628.  */
  629.