BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / finger / finger.c
index 349fe8c..7c08c04 100644 (file)
-#ifndef lint
-static char *sccsid = "@(#)finger.c    4.6 (Berkeley) %G%";
-#endif
-
-/*  This is a finger program.  It prints out useful information about users
- *  by digging it up from various system files.  It is not very portable
- *  because the most useful parts of the information (the full user name,
- *  office, and phone numbers) are all stored in the VAX-unused gecos field
- *  of /etc/passwd, which, unfortunately, other UNIXes use for other things.
- *
- *  There are three output formats, all of which give login name, teletype
- *  line number, and login time.  The short output format is reminiscent
- *  of finger on ITS, and gives one line of information per user containing
- *  in addition to the minimum basic requirements (MBR), the full name of
- *  the user, his idle time and office location and phone number.  The
- *  quick style output is UNIX who-like, giving only name, teletype and
- *  login time.  Finally, the long style output give the same information
- *  as the short (in more legible format), the home directory and shell
- *  of the user, and, if it exits, a copy of the file .plan in the users
- *  home directory.  Finger may be called with or without a list of people
- *  to finger -- if no list is given, all the people currently logged in
- *  are fingered.
- *
- *  The program is validly called by one of the following:
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     finger                  {short form list of users}
- *     finger -l               {long form list of users}
- *     finger -b               {briefer long form list of users}
- *     finger -q               {quick list of users}
- *     finger -i               {quick list of users with idle times}
- *     finger namelist         {long format list of specified users}
- *     finger -s namelist      {short format list of specified users}
- *     finger -w namelist      {narrow short format list of specified users}
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
  *
  *
- *  where 'namelist' is a list of users login names.
- *  The other options can all be given after one '-', or each can have its
- *  own '-'.  The -f option disables the printing of headers for short and
- *  quick outputs.  The -b option briefens long format outputs.  The -p
- *  option turns off plans for long format outputs.
- */
-
-#include       <sys/types.h>
-#include       <sys/stat.h>
-#include       <sgtty.h>
-#include       <utmp.h>
-#include       <signal.h>
-#include       <pwd.h>
-#include       <stdio.h>
-#include       <lastlog.h>
-#include       <sys/time.h>
-#include       <sys/socket.h>
-#include       <netinet/in.h>
-#include       <netdb.h>
-
-struct utmp    utmp;   /* for sizeof */
-#define NMAX sizeof(utmp.ut_name)
-#define LMAX sizeof(utmp.ut_line)
-
-#define                ASTERISK        '*'     /* ignore this in real name */
-#define                BLANK           ' '     /* blank character (i.e. space) */
-#define                CAPITALIZE      0137&   /* capitalize character macro */
-#define                COMMA           ','     /* separator in pw_gecos field */
-#define                COMMAND         '-'     /* command line flag char */
-#define                CORY            'C'     /* cory hall office */
-#define                EVANS           'E'     /* evans hall office */
-#define                LINEBREAK       012     /* line feed */
-#define                NULLSTR         ""      /* the null string, opposed to NULL */
-#define                SAMENAME        '&'     /* repeat login name in real name */
-#define                TALKABLE        0222    /* tty is writeable if 222 mode */
-
-struct  person  {                      /* one for each person fingered */
-       char            name[NMAX+1];   /* login name */
-       char            tty[LMAX+1];    /* NULL terminated tty line */
-       long            loginat;        /* time of login (possibly last) */
-       long            idletime;       /* how long idle (if logged in) */
-       short int       loggedin;       /* flag for being logged in */
-       short int       writeable;      /* flag for tty being writeable */
-       char            *realname;      /* pointer to full name */
-       char            *office;        /* pointer to office name */
-       char            *officephone;   /* pointer to office phone no. */
-       char            *homephone;     /* pointer to home phone no. */
-       char            *random;        /* for any random stuff in pw_gecos */
-       struct  passwd  *pwd;           /* structure of /etc/passwd stuff */
-       struct  person  *link;          /* link to next person */
-};
-
-struct  passwd                 *NILPWD = 0;
-struct  person                 *NILPERS = 0;
-
-int            persize         = sizeof( struct person );
-int            pwdsize         = sizeof( struct passwd );
-
-char           LASTLOG[]       = "/usr/adm/lastlog";   /* last login info */
-char           USERLOG[]       = "/etc/utmp";          /* who is logged in */
-char           outbuf[BUFSIZ];                         /* output buffer */
-char           *ctime();
-
-int            unbrief         = 1;            /* -b option default */
-int            header          = 1;            /* -f option default */
-int            hack            = 1;            /* -h option default */
-int            idle            = 0;            /* -i option default */
-int            large           = 0;            /* -l option default */
-int            match           = 1;            /* -m option default */
-int            plan            = 1;            /* -p option default */
-int            unquick         = 1;            /* -q option default */
-int            small           = 0;            /* -s option default */
-int            wide            = 1;            /* -w option default */
-
-int            lf;
-int            llopenerr;
-
-long           tloc;                           /* current time */
-
-
-
-main( argc, argv )
-
-    int                argc;
-    char       *argv[];
-
-{
-       FILE                    *fp,  *fopen();         /* for plans */
-       struct  passwd          *getpwent();            /* read /etc/passwd */
-       struct  person          *person1,  *p,  *pend;  /* people */
-       struct  passwd          *pw;                    /* temporary */
-       struct  utmp            user;                   /*   ditto   */
-       char                    *malloc();
-       char                    *s,  *pn,  *ln;
-       char                    c;
-       char                    *PLAN = "/.plan";       /* what plan file is */
-       char                    *PROJ = "/.project";    /* what project file */
-       int                     PLANLEN = strlen( PLAN );
-       int                     PROJLEN = strlen( PROJ );
-       int                     numnames = 0;
-       int                     orgnumnames;
-       int                     uf;
-       int                     usize = sizeof user;
-       int                     unshort;
-       int                     i, j;
-       int                     fngrlogin;
-
-       setbuf( stdout, outbuf );                       /* buffer output */
-
-    /*  parse command line for (optional) arguments */
-
-       i = 1;
-       if(  strcmp( *argv, "sh" )  )  {
-           fngrlogin = 0;
-           while( i++ < argc  &&  (*++argv)[0] == COMMAND )  {
-               for( s = argv[0] + 1; *s != NULL; s++ )  {
-                       switch  (*s)  {
-
-                           case 'b':
-                                   unbrief = 0;
-                                   break;
-
-                           case 'f':
-                                   header = 0;
-                                   break;
-
-                           case 'h':
-                                   hack = 0;
-                                   break;
-
-                           case 'i':
-                                   idle = 1;
-                                   unquick = 0;
-                                   break;
-
-                           case 'l':
-                                   large = 1;
-                                   break;
-
-                           case 'm':
-                                   match = 0;
-                                   break;
-
-                           case 'p':
-                                   plan = 0;
-                                   break;
-
-                           case 'q':
-                                   unquick = 0;
-                                   break;
-
-                           case 's':
-                                   small = 1;
-                                   break;
-
-                           case 'w':
-                                   wide = 0;
-                                   break;
-
-                           default:
-                               fprintf( stderr, "finger: Usage -- 'finger [-bfhilmpqsw] [login1 [login2 ...] ]'\n" );
-                               exit( 1 );
-                       }
-               }
-           }
-       }
-       else  {
-           fngrlogin = 1;
-       }
-       if( unquick )  {
-           time( &tloc );
-       }
-       else  {
-           if( idle )  {
-               time( &tloc );
-           }
-       }
-
-    /*  i > argc means no login names given so get them by reading USERLOG */
-
-       if(  (i > argc)  ||  fngrlogin  )  {
-           unshort = large;
-           if(  ( uf = open(USERLOG, 0) ) >= 0  )  {
-               user.ut_name[0] = NULL;
-               while( user.ut_name[0] == NULL )  {
-                   if( read( uf, (char *) &user, usize ) != usize )  {
-                       printf( "No one logged on\n" );
-                       exit( 0 );
-                   }
-               }
-               person1 = (struct person  *) malloc( persize );
-               for( j = 0; j < NMAX; j++ )  {
-                   person1->tty[j] = user.ut_line[j];
-                   person1->name[j] = user.ut_name[j];
-               }
-               person1->name[NMAX] = NULL;
-               person1->tty[NMAX] = NULL;
-               person1->loginat = user.ut_time;
-               person1->pwd = NILPWD;
-               person1->loggedin = 1;
-               numnames++;
-               p = person1;
-               while( read( uf, (char *) &user, usize ) == usize )  {
-                   if( user.ut_name[0] == NULL )  continue;
-                   p->link = (struct person  *) malloc( persize );
-                   p = p->link;
-                   for( j = 0; j < NMAX; j++ )  {
-                       p->tty[j] = user.ut_line[j];
-                       p->name[j] = user.ut_name[j];
-                   }
-                   p->name[NMAX] = NULL;
-                   p->tty[NMAX] = NULL;
-                   p->loginat = user.ut_time;
-                   p->pwd = NILPWD;
-                   p->loggedin = 1;
-                   numnames++;
-               }
-               p->link = NILPERS;
-               close( uf );
-           }
-           else  {
-               fprintf( stderr, "finger: error opening %s\n", USERLOG );
-               exit( 2 );
-           }
-
-               /*  if we are doing it, read /etc/passwd for the useful info */
-
-           if( unquick )  {
-               setpwent();
-               fwopen();
-               i = numnames;
-               while(  ( (pw = getpwent()) != NILPWD )  &&  ( i > 0 )  )  {
-                   p = person1;
-                   do  {
-                       if( p->pwd == NILPWD )  {
-                           if(  strcmp( p->name, pw->pw_name ) == 0  )  {
-                               p->pwd = (struct passwd  *) malloc( pwdsize );
-                               pwdcopy( p->pwd, pw );
-                               decode( p );
-                               i--;
-                           }
-                       }
-                       p = p->link;
-                   }  while( p != NILPERS );
-               }
-               fwclose();
-               endpwent();
-           }
-       }
-
-    /* get names from command line and check to see if they're  logged in */
-
-       else  {
-           unshort = ( small == 1 ? 0 : 1 );
-           while (i <= argc && netfinger(*argv)) {
-               i++;
-               argv++;
-           }
-           if (i++ > argc)
-               exit(0);
-           person1 = (struct person  *) malloc( persize );
-           strcpy(  person1->name, (argv++)[ 0 ]  );
-           person1->loggedin = 0;
-           person1->pwd = NILPWD;
-           numnames++;
-           p = person1;
-           while( i++ <= argc )  {
-               if (netfinger(*argv)) {
-                   argv++;
-                   continue;
-               }
-               p->link = (struct person  *) malloc( persize );
-               p = p->link;
-               strcpy(  p->name, (argv++)[ 0 ]  );
-               p->loggedin = 0;
-               p->pwd = NILPWD;
-               numnames++;
-           }
-           p->link = NILPERS;
-           pend = p;
-
-               /*  if we are doing it, read /etc/passwd for the useful info */
-
-           orgnumnames = numnames;
-           if( unquick )  {
-               setpwent();
-               while(  ( pw = getpwent() ) != NILPWD  )  {
-                   p = person1;
-                   i = 0;
-                   do  {
-                       if( strcmp( p->name, pw->pw_name ) == 0    ||
-                           matchcmp( pw->pw_gecos, pw->pw_name, p->name ) )  {
-                           if( p->pwd == NILPWD )  {
-                               p->pwd = (struct passwd  *) malloc( pwdsize );
-                               pwdcopy( p->pwd, pw );
-                           }
-                           else  {     /* handle multiple logins -- append new
-                                          "duplicate" entry to end of list */
-                               pend->link = (struct person  *) malloc(persize);
-                               pend = pend->link;
-                               pend->link = NILPERS;
-                               strcpy( pend->name, p->name );
-                               pend->pwd = (struct passwd  *) malloc(pwdsize);
-                               pwdcopy( pend->pwd, pw );
-                               numnames++;
-                           }
-                       }
-                       p = p->link;
-                   }  while( ++i < orgnumnames );
-               }
-               endpwent();
-           }
-
-               /*  Now get login information */
-
-           if(  ( uf = open(USERLOG, 0) ) >= 0  )  {
-               while( read( uf, (char *) &user, usize ) == usize )  {
-                   if( user.ut_name[0] == NULL )  continue;
-                   p = person1;
-                   do  {
-                       pw = p->pwd;
-                       if( pw == NILPWD )  {
-                           i = ( strcmp( p->name, user.ut_name ) ? 0 : NMAX );
-                       }
-                       else  {
-                           i = 0;
-                           while(  (i < NMAX)  &&
-                                   ( pw->pw_name[i] == user.ut_name[i])  )  {
-                               if( pw->pw_name[i] == NULL )  {
-                                   i = NMAX;
-                                   break;
-                               }
-                               i++;
-                           }
-                       }
-                       if( i == NMAX )  {
-                           if( p->loggedin == 1 )  {
-                               pend->link = (struct person  *) malloc(persize);
-                               pend = pend->link;
-                               pend->link = NILPERS;
-                               strcpy( pend->name, p->name );
-                               for( j = 0; j < NMAX; j++ )  {
-                                   pend->tty[j] = user.ut_line[j];
-                               }
-                               pend->tty[ NMAX ] = NULL;
-                               pend->loginat = user.ut_time;
-                               pend->loggedin = 2;
-                               if(  pw == NILPWD  )  {
-                                   pend ->pwd = NILPWD;
-                               }
-                               else  {
-                                   pend->pwd = (struct passwd  *) malloc(pwdsize);
-                                   pwdcopy( pend->pwd, pw );
-                               }
-                               numnames++;
-                           }
-                           else  {
-                               if( p->loggedin != 2 )  {
-                                   for( j = 0; j < NMAX; j++ )  {
-                                       p->tty[j] = user.ut_line[j];
-                                   }
-                                   p->tty[ NMAX ] = NULL;
-                                   p->loginat = user.ut_time;
-                                   p->loggedin = 1;
-                               }
-                           }
-                       }
-                       p = p->link;
-                   }  while( p != NILPERS );
-               }
-               fwopen();
-               p = person1;
-               while( p != NILPERS )  {
-                   if( p->loggedin == 2 )  {
-                       p->loggedin = 1;
-                   }
-                   decode( p );
-                   p = p->link;
-               }
-               fwclose();
-               close( uf );
-           }
-           else  {
-               fprintf( stderr, "finger: error opening %s\n", USERLOG );
-               exit( 2 );
-           }
-       }
-
-    /* print out what we got */
-
-       if( header )  {
-           if( unquick )  {
-               if( !unshort )  {
-                   if( wide )  {
-                       printf(
-"Login       Name              TTY Idle    When            Office\n" );
-                   }
-                   else  {
-                       printf(
-"Login    TTY Idle    When            Office\n" );
-                   }
-               }
-           }
-           else  {
-               printf( "Login      TTY            When" );
-               if( idle )  {
-                   printf( "             Idle" );
-               }
-               printf( "\n" );
-           }
-       }
-       p = person1;
-       do  {
-           if( unquick )  {
-               if( unshort )  {
-                   personprint( p );
-                   if( p->pwd != NILPWD )  {
-                       if( hack )  {
-                           s = malloc(strlen((p->pwd)->pw_dir) + PROJLEN + 1 );
-                           strcpy(  s, (p->pwd)->pw_dir  );
-                           strcat( s, PROJ );
-                           if(  ( fp = fopen( s, "r") )  != NULL  )  {
-                               printf( "Project: " );
-                               while(  ( c = getc(fp) )  !=  EOF  )  {
-                                   if( c == LINEBREAK )  {
-                                       break;
-                                   }
-                                   putc( c, stdout );
-                               }
-                               fclose( fp );
-                               printf( "\n" );
-                           }
-                       }
-                       if( plan )  {
-                           s = malloc( strlen( (p->pwd)->pw_dir ) + PLANLEN + 1 );
-                           strcpy(  s, (p->pwd)->pw_dir  );
-                           strcat( s, PLAN );
-                           if(  ( fp = fopen( s, "r") )  == NULL  )  {
-                               printf( "No Plan.\n" );
-                           }
-                           else  {
-                               printf( "Plan:\n" );
-                               while(  ( c = getc(fp) )  !=  EOF  )  {
-                                   putc( c, stdout );
-                               }
-                               fclose( fp );
-                           }
-                       }
-                   }
-                   if( p->link != NILPERS )  {
-                       printf( "\n" );
-                   }
-               }
-               else  {
-                   shortprint( p );
-               }
-           }
-           else  {
-               quickprint( p );
-           }
-           p = p->link;
-       }  while( p != NILPERS );
-       exit(0);
-}
-
-
-/*  given a pointer to a pwd (pfrom) copy it to another one, allocating
- *  space for all the stuff in it.  Note: Only the useful (what the
- *  program currently uses) things are copied.
- */
-
-pwdcopy( pto, pfrom )          /* copy relevant fields only */
-
-    struct  passwd             *pto,  *pfrom;
-{
-       pto->pw_name = malloc(  strlen( pfrom->pw_name ) + 1  );
-       strcpy( pto->pw_name, pfrom->pw_name );
-       pto->pw_uid = pfrom->pw_uid;
-       pto->pw_gecos = malloc(  strlen( pfrom->pw_gecos ) + 1  );
-       strcpy( pto->pw_gecos, pfrom->pw_gecos );
-       pto->pw_dir = malloc(  strlen( pfrom->pw_dir ) + 1  );
-       strcpy( pto->pw_dir, pfrom->pw_dir );
-       pto->pw_shell = malloc(  strlen( pfrom->pw_shell ) + 1  );
-       strcpy( pto->pw_shell, pfrom->pw_shell );
-}
-
-
-/*  print out information on quick format giving just name, tty, login time
- *  and idle time if idle is set.
- */
-
-quickprint( pers )
-
-    struct  person             *pers;
-{
-       int                     idleprinted;
-
-       printf( "%-*.*s", NMAX, NMAX, pers->name );
-       printf( "  " );
-       if( pers->loggedin )  {
-           if( idle )  {
-               findidle( pers );
-               if( pers->writeable )  {
-                   printf(  " %-*.*s %-16.16s", LMAX, LMAX, 
-                       pers->tty, ctime( &pers->loginat )  );
-               }
-               else  {
-                   printf(  "*%-*.*s %-16.16s", LMAX, LMAX, 
-                       pers->tty, ctime( &pers->loginat )  );
-               }
-               printf( "   " );
-               idleprinted = ltimeprint( &pers->idletime );
-           }
-           else  {
-               printf(  " %-*.*s %-16.16s", LMAX, LMAX, 
-                   pers->tty, ctime( &pers->loginat )  );
-           }
-       }
-       else  {
-           printf( "          Not Logged In" );
-       }
-       printf( "\n" );
-}
-
-
-/*  print out information in short format, giving login name, full name,
- *  tty, idle time, login time, office location and phone.
- */
-
-shortprint( pers )
-
-    struct  person     *pers;
-
-{
-       struct  passwd          *pwdt = pers->pwd;
-       char                    buf[ 26 ];
-       int                     i,  len,  offset,  dialup;
-
-       if( pwdt == NILPWD )  {
-           printf( "%-*.*s", NMAX, NMAX,  pers->name );
-           printf( "       ???\n" );
-           return;
-       }
-       printf( "%-*.*s", NMAX, NMAX,  pwdt->pw_name );
-       dialup = 0;
-       if( wide )  {
-           if(  strlen( pers->realname ) > 0  )  {
-               printf( " %-20.20s", pers->realname );
-           }
-           else  {
-               printf( "        ???          " );
-           }
-       }
-       if( pers->loggedin )  {
-           if( pers->writeable )  {
-               printf( "  " );
-           }
-           else  {
-               printf( " *" );
-           }
-       }
-       else  {
-           printf( "  " );
-       }
-       if(  strlen( pers->tty ) > 0  )  {
-           strcpy( buf, pers->tty );
-           if(  (buf[0] == 't')  &&  (buf[1] == 't')  &&  (buf[2] == 'y')  )  {
-               offset = 3;
-               for( i = 0; i < 2; i++ )  {
-                   buf[i] = buf[i + offset];
-               }
-           }
-           if(  (buf[0] == 'd')  &&  pers->loggedin  )  {
-               dialup = 1;
-           }
-           printf( "%-2.2s ", buf );
-       }
-       else  {
-           printf( "   " );
-       }
-       strcpy(buf, ctime(&pers->loginat));
-       if( pers->loggedin )  {
-           stimeprint( &pers->idletime );
-           offset = 7;
-           for( i = 4; i < 19; i++ )  {
-               buf[i] = buf[i + offset];
-           }
-           printf( " %-9.9s ", buf );
-       }
-       else if (pers->loginat == 0)
-           printf(" < .  .  .  . >");
-       else if (tloc - pers->loginat >= 180 * 24 * 60 * 60)
-           printf( " <%-6.6s, %-4.4s>", buf+4, buf+20 );
-       else
-           printf(" <%-12.12s>", buf+4);
-       len = strlen( pers->homephone );
-       if(  dialup  &&  (len > 0)  )  {
-           if( len == 8 )  {
-               printf( "             " );
-           }
-           else  {
-               if( len == 12 )  {
-                   printf( "         " );
-               }
-               else {
-                   for( i = 1; i <= 21 - len; i++ )  {
-                       printf( " " );
-                   }
-               }
-           }
-           printf( "%s", pers->homephone );
-       }
-       else  {
-           if(  strlen( pers->office ) > 0  )  {
-               printf( " %-11.11s", pers->office );
-               if(  strlen( pers->officephone ) > 0  )  {
-                   printf( " %8.8s", pers->officephone );
-               }
-               else  {
-                   if( len == 8 )  {
-                       printf( " %8.8s", pers->homephone );
-                   }
-               }
-           }
-           else  {
-               if(  strlen( pers->officephone ) > 0  )  {
-                   printf( "             %8.8s", pers->officephone );
-               }
-               else  {
-                   if( len == 8 )  {
-                       printf( "             %8.8s", pers->homephone );
-                   }
-                   else  {
-                       if( len == 12 )  {
-                           printf( "         %12.12s", pers->homephone );
-                       }
-                   }
-               }
-           }
-       }
-       printf( "\n" );
-}
-
-
-/*  print out a person in long format giving all possible information.
- *  directory and shell are inhibited if unbrief is clear.
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  */
 
-personprint( pers )
-
-    struct  person     *pers;
-{
-       struct  passwd          *pwdt = pers->pwd;
-       int                     idleprinted;
-
-       if( pwdt == NILPWD )  {
-           printf( "Login name: %-10s", pers->name );
-           printf( "                   " );
-           printf( "In real life: ???\n");
-           return;
-       }
-       printf( "Login name: %-10s", pwdt->pw_name );
-       if( pers->loggedin )  {
-           if( pers->writeable )  {
-               printf( "                       " );
-           }
-           else  {
-               printf( "       (messages off)  " );
-           }
-       }
-       else  {
-           printf( "                   " );
-       }
-       if(  strlen( pers->realname ) > 0  )  {
-           printf( "In real life: %-s", pers->realname );
-       }
-       if(  strlen( pers->office ) > 0  )  {
-           printf( "\nOffice: %-.11s", pers->office );
-           if(  strlen( pers->officephone ) > 0  )  {
-               printf( ", %s", pers->officephone );
-               if(  strlen( pers->homephone ) > 0  )  {
-                   printf( "           Home phone: %s", pers->homephone );
-               }
-               else  {
-                   if(  strlen( pers->random ) > 0  )  {
-                       printf( "       %s", pers->random );
-                   }
-               }
-           }
-           else  {
-               if(  strlen( pers->homephone ) > 0  )  {
-                   printf("                    Home phone: %s",pers->homephone);
-               }
-               if(  strlen( pers->random ) > 0  )  {
-                   printf( "                   %s", pers->random );
-               }
-           }
-       }
-       else  {
-           if(  strlen( pers->officephone ) > 0  )  {
-               printf( "\nPhone: %s", pers->officephone );
-               if(  strlen( pers->homephone ) > 0  )  {
-                   printf( "\n, %s", pers->homephone );
-                   if(  strlen( pers->random ) > 0  )  {
-                       printf( ", %s", pers->random );
-                   }
-               }
-               else  {
-                   if(  strlen( pers->random ) > 0  )  {
-                       printf( "\n, %s", pers->random );
-                   }
-               }
-           }
-           else  {
-               if(  strlen( pers->homephone ) > 0  )  {
-                   printf( "\nPhone: %s", pers->homephone );
-                   if(  strlen( pers->random ) > 0  )  {
-                       printf( ", %s", pers->random );
-                   }
-               }
-               else  {
-                   if(  strlen( pers->random ) > 0  )  {
-                       printf( "\n%s", pers->random );
-                   }
-               }
-           }
-       }
-       if( unbrief )  {
-           printf( "\n" );
-           printf( "Directory: %-25s", pwdt->pw_dir );
-           if(  strlen( pwdt->pw_shell ) > 0  )  {
-               printf( "       Shell: %-s", pwdt->pw_shell );
-           }
-       }
-       if( pers->loggedin )  {
-           register char *ep = ctime( &pers->loginat );
-           printf("\nOn since %15.15s on %-*.*s        ", &ep[4], LMAX, LMAX, pers->tty );
-           idleprinted = ltimeprint( &pers->idletime );
-           if( idleprinted )  {
-               printf( " Idle Time" );
-           }
-       }
-       else if (pers->loginat == 0)
-           printf("\nNever logged in.");
-       else if (tloc - pers->loginat > 180 * 24 * 60 * 60) {
-           register char *ep = ctime( &pers->loginat );
-           printf("\nLast login %10.10s, %4.4s on %.*s", ep, ep+20, LMAX, pers->tty);
-       }
-       else  {
-           register char *ep = ctime( &pers->loginat );
-           printf("\nLast login %16.16s on %.*s", ep, LMAX, pers->tty );
-       }
-       printf( "\n" );
-}
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
 
 
+#ifndef lint
+static char sccsid[] = "@(#)finger.c   5.21 (Berkeley) 6/24/90";
+#endif /* not lint */
 
 /*
 
 /*
- *  very hacky section of code to format phone numbers.  filled with
- *  magic constants like 4, 7 and 10.
- */
-
-char  *phone( s, len )
-
-    char               *s;
-    int                        len;
-{
-       char            *strsave();
-       char            fonebuf[ 15 ];
-       int             i;
-
-       switch(  len  )  {
-
-           case  4:
-               fonebuf[ 0 ] = ' ';
-               fonebuf[ 1 ] = 'x';
-               fonebuf[ 2 ] = '2';
-               fonebuf[ 3 ] = '-';
-               for( i = 0; i <= 3; i++ )  {
-                   fonebuf[ 4 + i ] = *s++;
-               }
-               fonebuf[ 8 ] = NULL;
-               return( strsave( &fonebuf[0] ) );
-               break;
-
-           case  7:
-               for( i = 0; i <= 2; i++ )  {
-                   fonebuf[ i ] = *s++;
-               }
-               fonebuf[ 3 ] = '-';
-               for( i = 0; i <= 3; i++ )  {
-                   fonebuf[ 4 + i ] = *s++;
-               }
-               fonebuf[ 8 ] = NULL;
-               return( strsave( &fonebuf[0] ) );
-               break;
-
-           case 10:
-               for( i = 0; i <= 2; i++ )  {
-                   fonebuf[ i ] = *s++;
-               }
-               fonebuf[ 3 ] = '-';
-               for( i = 0; i <= 2; i++ )  {
-                   fonebuf[ 4 + i ] = *s++;
-               }
-               fonebuf[ 7 ] = '-';
-               for( i = 0; i <= 3; i++ )  {
-                   fonebuf[ 8 + i ] = *s++;
-               }
-               fonebuf[ 12 ] = NULL;
-               return( strsave( &fonebuf[0] ) );
-               break;
-
-           default:
-               fprintf( stderr, "finger: error in phone numbering\n" );
-               return( strsave(s) );
-               break;
-       }
-}
-
-
-/*  decode the information in the gecos field of /etc/passwd
- *  another hacky section of code, but given the format the stuff is in...
- */
-
-decode( pers )
-
-    struct  person     *pers;
-
-{
-       struct  passwd          *pwdt = pers->pwd;
-       char                    buffer[ 256 ],  *bp,  *gp,  *lp;
-       char                    *phone();
-       int                     alldigits;
-       int                     len;
-       int                     i;
-
-       pers->realname = NULLSTR;
-       pers->office = NULLSTR;
-       pers->officephone = NULLSTR;
-       pers->homephone = NULLSTR;
-       pers->random = NULLSTR;
-       if(  pwdt != NILPWD )  {
-           gp = pwdt->pw_gecos;
-           bp = &buffer[ 0 ];
-           if( *gp == ASTERISK )  {
-               gp++;
-           }
-           while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {     /* name */
-               if( *gp == SAMENAME )  {
-                   lp = pwdt->pw_name;
-                   *bp++ = CAPITALIZE(*lp++);
-                   while( *lp != NULL )  {
-                       *bp++ = *lp++;
-                   }
-               }
-               else  {
-                   *bp++ = *gp;
-               }
-               gp++;
-           }
-           *bp = NULL;
-           pers->realname = malloc( strlen( &buffer[0] ) + 1 );
-           strcpy( pers->realname, &buffer[0] );
-           if( *gp++ == COMMA )  {                     /* office, supposedly */
-               alldigits = 1;
-               bp = &buffer[ 0 ];
-               while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
-                   *bp = *gp++;
-                   alldigits = alldigits && ('0' <= *bp) && (*bp <= '9');
-                   bp++;
-               }
-               *bp = NULL;
-               len = strlen( &buffer[0] );
-               if( buffer[ len - 1 ]  ==  CORY )  {
-                   strcpy( &buffer[ len - 1 ], " Cory" );
-                   pers->office = malloc( len + 5 );
-                   strcpy( pers->office, &buffer[0] );
-               }
-               else  {
-                   if( buffer[ len - 1 ] == EVANS )  {
-                       strcpy( &buffer[ len - 1 ], " Evans" );
-                       pers->office = malloc( len + 6 );
-                       strcpy( pers->office, &buffer[0] );
-                   }
-                   else  {
-                       if( buffer[ len - 1 ] == 'L' )  {
-                           strcpy( &buffer[ len - 1 ], " LBL" );
-                           pers->office = malloc( len + 4 );
-                           strcpy( pers->office, &buffer[0] );
-                       }
-                       else  {
-                           if( alldigits )  {
-                               if( len == 4 )  {
-                                   pers->officephone = phone(&buffer[0], len);
-                               }
-                               else  {
-                                   if(  (len == 7) || (len == 10)  )  {
-                                       pers->homephone = phone(&buffer[0],len);
-                                   }
-                               }
-                           }
-                           else  {
-                               pers->random = malloc( len + 1 );
-                               strcpy( pers->random, &buffer[0] );
-                           }
-                       }
-                   }
-               }
-               if( *gp++ == COMMA )  {     /* office phone, theoretically */
-                   bp = &buffer[ 0 ];
-                   alldigits = 1;
-                   while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
-                       *bp = *gp++;
-                       alldigits = alldigits && ('0' <= *bp) && (*bp <= '9');
-                       bp++;
-                   }
-                   *bp = NULL;
-                   len = strlen( &buffer[0] );
-                   if( alldigits )  {
-                       if(  len != 4  )  {
-                           if(  (len == 7) || (len == 10)  )  {
-                               pers->homephone = phone( &buffer[0], len );
-                           }
-                           else  {
-                               pers->random = malloc( len + 1 );
-                               strcpy( pers->random, &buffer[0] );
-                           }
-                       }
-                       else  {
-                               pers->officephone = phone( &buffer[0], len );
-                       }
-                   }
-                   else  {
-                       pers->random = malloc( len + 1 );
-                       strcpy( pers->random, &buffer[0] );
-                   }
-                   if( *gp++ == COMMA )  {             /* home phone?? */
-                       bp = &buffer[ 0 ];
-                       alldigits = 1;
-                           while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
-                               *bp = *gp++;
-                               alldigits = alldigits && ('0' <= *bp) &&
-                                                       (*bp <= '9');
-                               bp++;
-                           }
-                       *bp = NULL;
-                       len = strlen( &buffer[0] );
-                       if( alldigits  &&  ( (len == 7) || (len == 10) )  )  {
-                           if( *pers->homephone != NULL )  {
-                               pers->officephone = pers->homephone;
-                           }
-                           pers->homephone = phone( &buffer[0], len );
-                       }
-                       else  {
-                           pers->random = malloc( strlen( &buffer[0] ) + 1 );
-                           strcpy( pers->random, &buffer[0] );
-                       }
-                   }
-               }
-           }
-           if( pers->loggedin == 0 )  {
-               findwhen( pers );
-           }
-           else  {
-               findidle( pers );
-           }
-       }
-}
-
-
-/*  find the last log in of a user by checking the LASTLOG file.
- *  the entry is indexed by the uid, so this can only be done if
- *  the uid is known (which it isn't in quick mode)
- */
-
-fwopen()
-{
-       if(  ( lf = open(LASTLOG, 0) ) >= 0  )  {
-           llopenerr = 0;
-       }
-       else  {
-           fprintf( stderr, "finger: lastlog open error\n" );
-           llopenerr = 1;
-       }
-}
-
-
-findwhen( pers )
-
-    struct  person     *pers;
-{
-       struct  passwd          *pwdt = pers->pwd;
-       struct  lastlog         ll;
-       int                     llsize = sizeof ll;
-       int                     i;
-
-       if( !llopenerr )  {
-           lseek( lf, pwdt->pw_uid*llsize, 0 );
-           if ((i = read( lf, (char *) &ll, llsize )) == llsize) {
-                   for( i = 0; i < LMAX; i++ )  {
-                       pers->tty[ i ] = ll.ll_line[ i ];
-                   }
-                   pers->tty[ LMAX ] = NULL;
-                   pers->loginat = ll.ll_time;
-           }
-           else  {
-               if (i != 0)
-                       fprintf(stderr, "finger: lastlog read error\n");
-               pers->tty[ 0 ] = NULL;
-               pers->loginat = 0L;
-           }
-       }
-       else  {
-           pers->tty[ 0 ] = NULL;
-           pers->loginat = 0L;
-       }
-}
-
-
-fwclose()
-{
-       if( !llopenerr )  {
-           close( lf );
-       }
-}
-
-
-/*  find the idle time of a user by doing a stat on /dev/histty,
- *  where histty has been gotten from USERLOG, supposedly.
+ * Finger prints out information about users.  It is not portable since
+ * certain fields (e.g. the full user name, office, and phone numbers) are
+ * extracted from the gecos field of the passwd file which other UNIXes
+ * may not have or may use for other things.
+ *
+ * There are currently two output formats; the short format is one line
+ * per user and displays login name, tty, login time, real name, idle time,
+ * and office location/phone number.  The long format gives the same
+ * information (in a more legible format) as well as home directory, shell,
+ * mail info, and .plan/.project files.
  */
 
  */
 
-findidle( pers )
-
-    struct  person     *pers;
-{
-       struct  stat            ttystatus;
-       struct  passwd          *pwdt = pers->pwd;
-       char                    buffer[ 20 ];
-       char                    *TTY = "/dev/";
-       int                     TTYLEN = strlen( TTY );
-       int                     i;
-
-       strcpy( &buffer[0], TTY );
-       i = 0;
-       do  {
-           buffer[ TTYLEN + i ] = pers->tty[ i ];
-       }  while( ++i <= LMAX );
-       if(  stat( &buffer[0], &ttystatus ) >= 0  )  {
-           time( &tloc );
-           if( tloc < ttystatus.st_atime )  {
-               pers->idletime = 0L;
-           }
-           else  {
-               pers->idletime = tloc - ttystatus.st_atime;
-           }
-           if(  (ttystatus.st_mode & TALKABLE) == TALKABLE  )  {
-               pers->writeable = 1;
-           }
-           else  {
-               pers->writeable = 0;
-           }
-       }
-       else  {
-           fprintf( stderr, "finger: error STATing %s\n", &buffer[0] );
-           exit( 4 );
-       }
-}
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include "finger.h"
 
 
+time_t now;
+int lflag, sflag, mflag, pplan;
+char tbuf[1024];
 
 
-/*  print idle time in short format; this program always prints 4 characters;
- *  if the idle time is zero, it prints 4 blanks.
- */
-
-stimeprint( dt )
-
-    long       *dt;
+main(argc, argv)
+       int argc;
+       char **argv;
 {
 {
-       struct  tm              *gmtime();
-       struct  tm              *delta;
+       extern int optind;
+       int ch;
+       time_t time();
 
 
-       delta = gmtime( dt );
-       if( delta->tm_yday == 0 )  {
-           if( delta->tm_hour == 0 )  {
-               if( delta->tm_min >= 10 )  {
-                   printf( " %2.2d ", delta->tm_min );
-               }
-               else  {
-                   if( delta->tm_min == 0 )  {
-                       printf( "    " );
-                   }
-                   else  {
-                       printf( "  %1.1d ", delta->tm_min );
-                   }
-               }
-           }
-           else  {
-               if( delta->tm_hour >= 10 )  {
-                   printf( "%3.3d:", delta->tm_hour );
-               }
-               else  {
-                   printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min );
-               }
-           }
-       }
-       else  {
-           printf( "%3dd", delta->tm_yday );
-       }
-}
-
-
-/*  print idle time in long format with care being taken not to pluralize
- *  1 minutes or 1 hours or 1 days.
- */
-
-ltimeprint( dt )
-
-    long       *dt;
-{
-       struct  tm              *gmtime();
-       struct  tm              *delta;
-       int                     printed = 1;
-
-       delta = gmtime( dt );
-       if( delta->tm_yday == 0 )  {
-           if( delta->tm_hour == 0 )  {
-               if( delta->tm_min >= 10 )  {
-                   printf( "%2d minutes", delta->tm_min );
-               }
-               else  {
-                   if( delta->tm_min == 0 )  {
-                       if( delta->tm_sec > 10 )  {
-                           printf( "%2d seconds", delta->tm_sec );
-                       }
-                       else  {
-                           printed = 0;
-                       }
-                   }
-                   else  {
-                       if( delta->tm_min == 1 )  {
-                           if( delta->tm_sec == 1 )  {
-                               printf( "%1d minute %1d second",
-                                   delta->tm_min, delta->tm_sec );
-                           }
-                           else  {
-                               printf( "%1d minute %d seconds",
-                                   delta->tm_min, delta->tm_sec );
-                           }
-                       }
-                       else  {
-                           if( delta->tm_sec == 1 )  {
-                               printf( "%1d minutes %1d second",
-                                   delta->tm_min, delta->tm_sec );
-                           }
-                           else  {
-                               printf( "%1d minutes %d seconds",
-                                   delta->tm_min, delta->tm_sec );
-                           }
-                       }
-                   }
-               }
-           }
-           else  {
-               if( delta->tm_hour >= 10 )  {
-                   printf( "%2d hours", delta->tm_hour );
-               }
-               else  {
-                   if( delta->tm_hour == 1 )  {
-                       if( delta->tm_min == 1 )  {
-                           printf( "%1d hour %1d minute",
-                               delta->tm_hour, delta->tm_min );
-                       }
-                       else  {
-                           printf( "%1d hour %2d minutes",
-                               delta->tm_hour, delta->tm_min );
-                       }
-                   }
-                   else  {
-                       if( delta->tm_min == 1 )  {
-                           printf( "%1d hours %1d minute",
-                               delta->tm_hour, delta->tm_min );
-                       }
-                       else  {
-                           printf( "%1d hours %2d minutes",
-                               delta->tm_hour, delta->tm_min );
-                       }
-                   }
-               }
-           }
-       }
-       else  {
-               if( delta->tm_yday >= 10 )  {
-                   printf( "%2d days", delta->tm_yday );
-               }
-               else  {
-                   if( delta->tm_yday == 1 )  {
-                       if( delta->tm_hour == 1 )  {
-                           printf( "%1d day %1d hour",
-                               delta->tm_yday, delta->tm_hour );
-                       }
-                       else  {
-                           printf( "%1d day %2d hours",
-                               delta->tm_yday, delta->tm_hour );
-                       }
-                   }
-                   else  {
-                       if( delta->tm_hour == 1 )  {
-                           printf( "%1d days %1d hour",
-                               delta->tm_yday, delta->tm_hour );
-                       }
-                       else  {
-                           printf( "%1d days %2d hours",
-                               delta->tm_yday, delta->tm_hour );
-                       }
-                   }
-               }
+       while ((ch = getopt(argc, argv, "lmps")) != EOF)
+               switch(ch) {
+               case 'l':
+                       lflag = 1;              /* long format */
+                       break;
+               case 'm':
+                       mflag = 1;              /* force exact match of names */
+                       break;
+               case 'p':
+                       pplan = 1;              /* don't show .plan/.project */
+                       break;
+               case 's':
+                       sflag = 1;              /* short format */
+                       break;
+               case '?':
+               default:
+                       (void)fprintf(stderr,
+                           "usage: finger [-lmps] [login ...]\n");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       (void)time(&now);
+       setpassent(1);
+       if (!*argv) {
+               /*
+                * Assign explicit "small" format if no names given and -l
+                * not selected.  Force the -s BEFORE we get names so proper
+                * screening will be done.
+                */
+               if (!lflag)
+                       sflag = 1;      /* if -l not explicit, force -s */
+               loginlist();
+               if (entries == 0)
+                       (void)printf("No one logged on.\n");
+       } else {
+               userlist(argc, argv);
+               /*
+                * Assign explicit "large" format if names given and -s not
+                * explicitly stated.  Force the -l AFTER we get names so any
+                * remote finger attempts specified won't be mishandled.
+                */
+               if (!sflag)
+                       lflag = 1;      /* if -s not explicit, force -l */
+       }
+       if (entries != 0) {
+               if (lflag)
+                       lflag_print();
+               else
+                       sflag_print();
        }
        }
-       return( printed );
+       exit(0);
 }
 
 }
 
-
-matchcmp( gname, login, given )
-
-    char               *gname;
-    char               *login;
-    char               *given;
+loginlist()
 {
 {
-       char            buffer[ 20 ];
-       char            c;
-       int             flag,  i,  unfound;
+       register PERSON *pn;
+       struct passwd *pw;
+       struct utmp user;
+       char name[UT_NAMESIZE + 1];
 
 
-       if( !match )  {
-           return( 0 );
+       if (!freopen(_PATH_UTMP, "r", stdin)) {
+               (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP);
+               exit(2);
        }
        }
-       else  {
-           if(  namecmp( login, given )  )  {
-               return( 1 );
-           }
-           else if (*gname == '\0')
-               return (0);
-           else  {
-               if( *gname == ASTERISK )  {
-                   gname++;
-               }
-               flag = 1;
-               i = 0;
-               unfound = 1;
-               while(  unfound  )  {
-                   if( flag )  {
-                       c = *gname++;
-                       if( c == SAMENAME )  {
-                           flag = 0;
-                           c = *login++;
-                       }
-                       else  {
-                           unfound = (*gname != COMMA)  &&  (*gname != NULL);
-                       }
-                   }
-                   else {
-                       c = *login++;
-                       if( c == NULL )  {
-                           if(  (*gname == COMMA)  ||  (*gname == NULL)  )  {
-                               break;
-                           }
-                           else  {
-                               flag = 1;
+       name[UT_NAMESIZE] = NULL;
+       while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
+               if (!user.ut_name[0])
+                       continue;
+               if ((pn = find_person(user.ut_name)) == NULL) {
+                       bcopy(user.ut_name, name, UT_NAMESIZE);
+                       if ((pw = getpwnam(name)) == NULL)
                                continue;
                                continue;
-                           }
-                       }
-                   }
-                   if( c == BLANK )  {
-                       buffer[i++] = NULL;
-                       if(  namecmp( buffer, given )  )  {
-                           return( 1 );
-                       }
-                       i = 0;
-                       flag = 1;
-                   }
-                   else  {
-                       buffer[ i++ ] = c;
-                   }
-               }
-               buffer[i++] = NULL;
-               if(  namecmp( buffer, given )  )  {
-                   return( 1 );
-               }
-               else  {
-                   return( 0 );
-               }
-           }
-       }
-}
-
-
-namecmp( name1, name2 )
-
-    char               *name1;
-    char               *name2;
-{
-       char            c1,  c2;
-
-       c1 = *name1;
-       if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) )  {
-           c1 = CAPITALIZE( c1 );
-       }
-       c2 = *name2;
-       if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) )  {
-           c2 = CAPITALIZE( c2 );
-       }
-       while( c1 == c2 )  {
-           if( c1 == NULL )  {
-               return( 1 );
-           }
-           c1 = *++name1;
-           if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) )  {
-               c1 = CAPITALIZE( c1 );
-           }
-           c2 = *++name2;
-           if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) )  {
-               c2 = CAPITALIZE( c2 );
-           }
-       }
-       if( *name1 == NULL )  {
-           while(  ('0' <= *name2)  &&  (*name2 <= '9')  )  {
-               name2++;
-           }
-           if( *name2 == NULL )  {
-               return( 1 );
-           }
-       }
-       else  {
-           if( *name2 == NULL )  {
-               while(  ('0' <= *name1)  &&  (*name1 <= '9')  )  {
-                   name1++;
-               }
-               if( *name1 == NULL )  {
-                   return( 1 );
-               }
-           }
-       }
-       return( 0 );
-}
-
-
-char  *strsave( s )
-
-    char               *s;
-{
-       char            *malloc();
-       char            *p;
-
-       p = malloc( strlen( s ) + 1 );
-       strcpy( p, s );
-}
-
-netfinger(name)
-char *name;
-{
-       char *host;
-       char fname[100];
-       struct hostent *hp;
-       struct servent *sp;
-       struct  sockaddr_in sin;
-       int s;
-       char *rindex();
-       register FILE *f;
-       register int c;
-       register int lastc;
-
-       if (name == NULL)
-               return(0);
-       host = rindex(name, '@');
-       if (host == NULL)
-               return(0);
-       *host++ = 0;
-       hp = gethostbyname(host);
-       if (hp == NULL) {
-               static struct hostent def;
-               static struct in_addr defaddr;
-               static char namebuf[128];
-               int inet_addr();
-
-               defaddr.s_addr = inet_addr(host);
-               if (defaddr.s_addr == -1) {
-                       printf("unknown host: %s\n", host);
-                       return(1);
-               }
-               strcpy(namebuf, host);
-               def.h_name = namebuf;
-               def.h_addr = (char *)&defaddr;
-               def.h_length = sizeof (struct in_addr);
-               def.h_addrtype = AF_INET;
-               def.h_aliases = 0;
-               hp = &def;
-       }
-       printf("[%s]", hp->h_name);
-       sp = getservbyname("finger", "tcp");
-       if (sp == 0) {
-               printf("tcp/finger: unknown service\n");
-               return(1);
-       }
-       sin.sin_family = hp->h_addrtype;
-       bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
-       sin.sin_port = sp->s_port;
-       s = socket(hp->h_addrtype, SOCK_STREAM, 0);
-       if (s < 0) {
-               fflush(stdout);
-               perror("socket");
-               return(1);
-       }
-       if (connect(s, (char *)&sin, sizeof (sin)) < 0) {
-               fflush(stdout);
-               perror("connect");
-               close(s);
-               return(1);
-       }
-       printf("\n");
-       if (large) write(s, "/W ", 3);
-       write(s, name, strlen(name));
-       write(s, "\r\n", 2);
-       f = fdopen(s, "r");
-       while ((c = getc(f)) != EOF) {
-               switch(c) {
-               case 0210:
-               case 0211:
-               case 0212:
-               case 0214:
-                       c -= 0200;
-                       break;
-               case 0215:
-                       c = '\n';
-                       break;
-               }
-               putchar(lastc = c);
-       }
-       if (lastc != '\n')
-               putchar('\n');
-       return(1);
+                       pn = enter_person(pw);
+               }
+               enter_where(&user, pn);
+       }
+       for (pn = phead; lflag && pn != NULL; pn = pn->next)
+               enter_lastlog(pn);
+}
+
+userlist(argc, argv)
+       register argc;
+       register char **argv;
+{
+       register i;
+       register PERSON *pn;
+       PERSON *nethead;
+       struct utmp user;
+       struct passwd *pw;
+       int dolocal, *used;
+       char *index();
+
+       if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) {
+               (void)fprintf(stderr, "finger: out of space.\n");
+               exit(1);
+       }
+
+       /* pull out all network requests */
+       for (i = 0, dolocal = 0, nethead = NULL; i < argc; i++) {
+               if (!index(argv[i], '@')) {
+                       dolocal = 1;
+                       continue;
+               }
+               pn = palloc();
+               pn->next = nethead;
+               nethead = pn;
+               pn->name = argv[i];
+               used[i] = -1;
+       }
+
+       if (!dolocal)
+               goto net;
+
+       /*
+        * traverse the list of possible login names and check the login name
+        * and real name against the name specified by the user.
+        */
+       if (mflag) {
+               for (i = 0; i < argc; i++)
+                       if (used[i] >= 0 && (pw = getpwnam(argv[i]))) {
+                               enter_person(pw);
+                               used[i] = 1;
+                       }
+       } else while (pw = getpwent())
+               for (i = 0; i < argc; i++)
+                       if (used[i] >= 0 &&
+                           (!strcasecmp(pw->pw_name, argv[i]) ||
+                           match(pw, argv[i]))) {
+                               enter_person(pw);
+                               used[i] = 1;
+                       }
+
+       /* list errors */
+       for (i = 0; i < argc; i++)
+               if (!used[i])
+                       (void)fprintf(stderr,
+                           "finger: %s: no such user.\n", argv[i]);
+
+       /* handle network requests */
+net:   for (pn = nethead; pn; pn = pn->next) {
+               netfinger(pn->name);
+               if (pn->next || entries)
+                       putchar('\n');
+       }
+
+       if (entries == 0)
+               return;
+
+       /*
+        * Scan thru the list of users currently logged in, saving
+        * appropriate data whenever a match occurs.
+        */
+       if (!freopen(_PATH_UTMP, "r", stdin)) {
+               (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP);
+               exit(1);
+       }
+       while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
+               if (!user.ut_name[0])
+                       continue;
+               if ((pn = find_person(user.ut_name)) == NULL)
+                       continue;
+               enter_where(&user, pn);
+       }
+       for (pn = phead; pn != NULL; pn = pn->next)
+               enter_lastlog(pn);
 }
 }