1: #ifndef lint
   2: static char *sccsid = "@(#)finger.c	4.1 (Berkeley) 10/1/80";
   3: #endif
   4: 
   5: /*  This is a finger program.  It prints out useful information about users
   6:  *  by digging it up from various system files.  It is not very portable
   7:  *  because the most useful parts of the information (the full user name,
   8:  *  office, and phone numbers) are all stored in the VAX-unused gecos field
   9:  *  of /etc/passwd, which, unfortunately, other UNIXes use for other things.
  10:  *
  11:  *  There are three output formats, all of which give login name, teletype
  12:  *  line number, and login time.  The short output format is reminiscent
  13:  *  of finger on ITS, and gives one line of information per user containing
  14:  *  in addition to the minimum basic requirements (MBR), the full name of
  15:  *  the user, his idle time and office location and phone number.  The
  16:  *  quick style output is UNIX who-like, giving only name, teletype and
  17:  *  login time.  Finally, the long style output give the same information
  18:  *  as the short (in more legible format), the home directory and shell
  19:  *  of the user, and, if it exits, a copy of the file .plan in the users
  20:  *  home directory.  Finger may be called with or without a list of people
  21:  *  to finger -- if no list is given, all the people currently logged in
  22:  *  are fingered.
  23:  *
  24:  *  The program is validly called by one of the following:
  25:  *
  26:  *	finger			{short form list of users}
  27:  *	finger -l		{long form list of users}
  28:  *	finger -b		{briefer long form list of users}
  29:  *	finger -q		{quick list of users}
  30:  *	finger -i		{quick list of users with idle times}
  31:  *	finger namelist		{long format list of specified users}
  32:  *	finger -s namelist	{short format list of specified users}
  33:  *	finger -w namelist	{narrow short format list of specified users}
  34:  *
  35:  *  where 'namelist' is a list of users login names.
  36:  *  The other options can all be given after one '-', or each can have its
  37:  *  own '-'.  The -f option disables the printing of headers for short and
  38:  *  quick outputs.  The -b option briefens long format outputs.  The -p
  39:  *  option turns off plans for long format outputs.
  40:  */
  41: 
  42: #include    <sys/types.h>
  43: #include    <sys/stat.h>
  44: #include    <sgtty.h>
  45: #include    <utmp.h>
  46: #include    <signal.h>
  47: #include    <pwd.h>
  48: #include    <stdio.h>
  49: #include    <lastlog.h>
  50: #include    <time.h>
  51: 
  52: struct  utmp    utmp;   /* for sizeof */
  53: #define NMAX sizeof(utmp.ut_name)
  54: #define LMAX sizeof(utmp.ut_line)
  55: 
  56: #define     ASTERISK    '*' /* ignore this in real name */
  57: #define     BLANK       ' ' /* blank character (i.e. space) */
  58: #define     CAPITALIZE  0137&   /* capitalize character macro */
  59: #define     COMMA       ',' /* separator in pw_gecos field */
  60: #define     COMMAND     '-' /* command line flag char */
  61: #define     CORY        'C' /* cory hall office */
  62: #define     EVANS       'E' /* evans hall office */
  63: #define     LINEBREAK   012 /* line feed */
  64: #define     NULLSTR     ""  /* the null string, opposed to NULL */
  65: #define     SAMENAME    '&' /* repeat login name in real name */
  66: #define     TALKABLE    0222    /* tty is writeable if 222 mode */
  67: 
  68: struct  person  {           /* one for each person fingered */
  69:     char        name[NMAX+1];   /* login name */
  70:     char        tty[LMAX+1];    /* NULL terminated tty line */
  71:     long        loginat;    /* time of login (possibly last) */
  72:     long        idletime;   /* how long idle (if logged in) */
  73:     short       loggedin;   /* flag for being logged in */
  74:     short       writeable;  /* flag for tty being writeable */
  75:     char        *realname;  /* pointer to full name */
  76:     char        *office;    /* pointer to office name */
  77:     char        *officephone;   /* pointer to office phone no. */
  78:     char        *homephone; /* pointer to home phone no. */
  79:     char        *random;    /* for any random stuff in pw_gecos */
  80:     struct  passwd  *pwd;       /* structure of /etc/passwd stuff */
  81:     struct  person  *link;      /* link to next person */
  82: };
  83: 
  84: struct  passwd          *NILPWD = 0;
  85: struct  person          *NILPERS = 0;
  86: 
  87: int     persize     = sizeof( struct person );
  88: int     pwdsize     = sizeof( struct passwd );
  89: 
  90: char        LASTLOG[]   = "/usr/adm/lastlog";   /* last login info */
  91: char        USERLOG[]   = "/etc/utmp";      /* who is logged in */
  92: char        outbuf[BUFSIZ];             /* output buffer */
  93: char        *ctime();
  94: 
  95: int     unbrief     = 1;        /* -b option default */
  96: int     header      = 1;        /* -f option default */
  97: int     hack        = 1;        /* -h option default */
  98: int     idle        = 0;        /* -i option default */
  99: int     large       = 0;        /* -l option default */
 100: int     match       = 1;        /* -m option default */
 101: int     plan        = 1;        /* -p option default */
 102: int     unquick     = 1;        /* -q option default */
 103: int     small       = 0;        /* -s option default */
 104: int     wide        = 1;        /* -w option default */
 105: 
 106: int     lf;
 107: int     llopenerr;
 108: 
 109: long        tloc;               /* current time */
 110: 
 111: 
 112: 
 113: main( argc, argv )
 114: 
 115:     int     argc;
 116:     char    *argv[];
 117: 
 118: {
 119:     FILE            *fp,  *fopen();     /* for plans */
 120:     struct  passwd      *getpwent();        /* read /etc/passwd */
 121:     struct  person      *person1,  *p,  *pend;  /* people */
 122:     struct  passwd      *pw;            /* temporary */
 123:     struct  utmp        user;           /*   ditto   */
 124:     char            *malloc();
 125:     char            *s;
 126:     int         c;
 127:     char            *PLAN = "/.plan";   /* what plan file is */
 128:     char            *PROJ = "/.project";    /* what project file */
 129:     int         PLANLEN = strlen( PLAN );
 130:     int         PROJLEN = strlen( PROJ );
 131:     int         numnames = 0;
 132:     int         orgnumnames;
 133:     int         uf;
 134:     int         usize = sizeof user;
 135:     int         unshort;
 136:     int         i, j;
 137:     int         fngrlogin;
 138: 
 139:     setbuf( stdout, outbuf );           /* buffer output */
 140: 
 141:     /*  parse command line for (optional) arguments */
 142: 
 143:     i = 1;
 144:     if(  strcmp( *argv, "sh" )  )  {
 145:         fngrlogin = 0;
 146:         while( i++ < argc  &&  (*++argv)[0] == COMMAND )  {
 147:         for( s = argv[0] + 1; *s != NULL; s++ )  {
 148:             switch  (*s)  {
 149: 
 150:                 case 'b':
 151:                     unbrief = 0;
 152:                     break;
 153: 
 154:                 case 'f':
 155:                     header = 0;
 156:                     break;
 157: 
 158:                 case 'h':
 159:                     hack = 0;
 160:                     break;
 161: 
 162:                 case 'i':
 163:                     idle = 1;
 164:                     unquick = 0;
 165:                     break;
 166: 
 167:                 case 'l':
 168:                     large = 1;
 169:                     break;
 170: 
 171:                 case 'm':
 172:                     match = 0;
 173:                     break;
 174: 
 175:                 case 'p':
 176:                     plan = 0;
 177:                     break;
 178: 
 179:                 case 'q':
 180:                     unquick = 0;
 181:                     break;
 182: 
 183:                 case 's':
 184:                     small = 1;
 185:                     break;
 186: 
 187:                 case 'w':
 188:                     wide = 0;
 189:                     break;
 190: 
 191:                 default:
 192:                 fprintf( stderr, "finger: Usage -- 'finger [-bfhilmpqsw] [login1 [login2 ...] ]'\n" );
 193:                 exit( 1 );
 194:             }
 195:         }
 196:         }
 197:     }
 198:     else  {
 199:         fngrlogin = 1;
 200:     }
 201:     if( unquick )  {
 202:         time( &tloc );
 203:     }
 204:     else  {
 205:         if( idle )  {
 206:         time( &tloc );
 207:         }
 208:     }
 209: 
 210:     /*  i > argc means no login names given so get them by reading USERLOG */
 211: 
 212:     if(  (i > argc)  ||  fngrlogin  )  {
 213:         unshort = large;
 214:         if(  ( uf = open(USERLOG, 0) ) >= 0  )  {
 215:         user.ut_name[0] = NULL;
 216:         while( user.ut_name[0] == NULL )  {
 217:             if( read( uf, (char *) &user, usize ) != usize )  {
 218:             printf( "\nNo one logged on\n" );
 219:             exit( 0 );
 220:             }
 221:         }
 222:         person1 = (struct person  *) malloc( persize );
 223:         for( j = 0; j < NMAX; j++ )  {
 224:             person1->tty[j] = user.ut_line[j];
 225:             person1->name[j] = user.ut_name[j];
 226:         }
 227:         person1->name[NMAX] = NULL;
 228:         person1->tty[NMAX] = NULL;
 229:         person1->loginat = user.ut_time;
 230:         person1->pwd = NILPWD;
 231:         person1->loggedin = 1;
 232:         numnames++;
 233:         p = person1;
 234:         while( read( uf, (char *) &user, usize ) == usize )  {
 235:             if( user.ut_name[0] == NULL )  continue;
 236:             p->link = (struct person  *) malloc( persize );
 237:             p = p->link;
 238:             for( j = 0; j < NMAX; j++ )  {
 239:             p->tty[j] = user.ut_line[j];
 240:             p->name[j] = user.ut_name[j];
 241:             }
 242:             p->name[NMAX] = NULL;
 243:             p->tty[NMAX] = NULL;
 244:             p->loginat = user.ut_time;
 245:             p->pwd = NILPWD;
 246:             p->loggedin = 1;
 247:             numnames++;
 248:         }
 249:         p->link = NILPERS;
 250:         close( uf );
 251:         }
 252:         else  {
 253:         fprintf( stderr, "finger: error opening %s\n", USERLOG );
 254:         exit( 2 );
 255:         }
 256: 
 257:         /*  if we are doing it, read /etc/passwd for the useful info */
 258: 
 259:         if( unquick )  {
 260:         setpwent();
 261:         fwopen();
 262:         i = numnames;
 263:         while(  ( (pw = getpwent()) != NILPWD )  &&  ( i > 0 )  )  {
 264:             p = person1;
 265:             do  {
 266:             if( p->pwd == NILPWD )  {
 267:                 if(  strcmp( p->name, pw->pw_name ) == 0  )  {
 268:                 p->pwd = (struct passwd  *) malloc( pwdsize );
 269:                 pwdcopy( p->pwd, pw );
 270:                 decode( p );
 271:                 i--;
 272:                 }
 273:             }
 274:             p = p->link;
 275:             }  while( p != NILPERS );
 276:         }
 277:         fwclose();
 278:         endpwent();
 279:         }
 280:     }
 281: 
 282:     /* get names from command line and check to see if they're  logged in */
 283: 
 284:     else  {
 285:         unshort = ( small == 1 ? 0 : 1 );
 286:         i++;
 287:         person1 = (struct person  *) malloc( persize );
 288:         strcpy(  person1->name, (argv++)[ 0 ]  );
 289:         person1->loggedin = 0;
 290:         person1->pwd = NILPWD;
 291:         numnames++;
 292:         p = person1;
 293:         while( i++ <= argc )  {
 294:         p->link = (struct person  *) malloc( persize );
 295:         p = p->link;
 296:         strcpy(  p->name, (argv++)[ 0 ]  );
 297:         p->loggedin = 0;
 298:         p->pwd = NILPWD;
 299:         numnames++;
 300:         }
 301:         p->link = NILPERS;
 302:         pend = p;
 303: 
 304:         /*  if we are doing it, read /etc/passwd for the useful info */
 305: 
 306:         orgnumnames = numnames;
 307:         if( unquick )  {
 308:         setpwent();
 309:         while(  ( pw = getpwent() ) != NILPWD  )  {
 310:             p = person1;
 311:             i = 0;
 312:             do  {
 313:             if( strcmp( p->name, pw->pw_name ) == 0    ||
 314:                 matchcmp( pw->pw_gecos, pw->pw_name, p->name ) )  {
 315:                 if( p->pwd == NILPWD )  {
 316:                 p->pwd = (struct passwd  *) malloc( pwdsize );
 317:                 pwdcopy( p->pwd, pw );
 318:                 }
 319:                 else  { /* handle multiple logins -- append new
 320: 					   "duplicate" entry to end of list */
 321:                 pend->link = (struct person  *) malloc(persize);
 322:                 pend = pend->link;
 323:                 pend->link = NILPERS;
 324:                 strcpy( pend->name, p->name );
 325:                 pend->pwd = (struct passwd  *) malloc(pwdsize);
 326:                 pwdcopy( pend->pwd, pw );
 327:                 numnames++;
 328:                 }
 329:             }
 330:             p = p->link;
 331:             }  while( ++i < orgnumnames );
 332:         }
 333:         endpwent();
 334:         }
 335: 
 336:         /*  Now get login information */
 337: 
 338:         if(  ( uf = open(USERLOG, 0) ) >= 0  )  {
 339:         while( read( uf, (char *) &user, usize ) == usize )  {
 340:             if( user.ut_name[0] == NULL )  continue;
 341:             p = person1;
 342:             do  {
 343:             pw = p->pwd;
 344:             if( pw == NILPWD )  {
 345:                 i = ( strcmp( p->name, user.ut_name ) ? 0 : NMAX );
 346:             }
 347:             else  {
 348:                 i = 0;
 349:                 while(  (i < NMAX)  &&
 350:                     ( pw->pw_name[i] == user.ut_name[i])  )  {
 351:                 if( pw->pw_name[i] == NULL )  {
 352:                     i = NMAX;
 353:                     break;
 354:                 }
 355:                 i++;
 356:                 }
 357:             }
 358:             if( i == NMAX )  {
 359:                 if( p->loggedin == 1 )  {
 360:                 pend->link = (struct person  *) malloc(persize);
 361:                 pend = pend->link;
 362:                 pend->link = NILPERS;
 363:                 strcpy( pend->name, p->name );
 364:                 for( j = 0; j < NMAX; j++ )  {
 365:                     pend->tty[j] = user.ut_line[j];
 366:                 }
 367:                 pend->tty[ NMAX ] = NULL;
 368:                 pend->loginat = user.ut_time;
 369:                 pend->loggedin = 2;
 370:                 if(  pw == NILPWD  )  {
 371:                     pend ->pwd = NILPWD;
 372:                 }
 373:                 else  {
 374:                     pend->pwd = (struct passwd  *) malloc(pwdsize);
 375:                     pwdcopy( pend->pwd, pw );
 376:                 }
 377:                 numnames++;
 378:                 }
 379:                 else  {
 380:                 if( p->loggedin != 2 )  {
 381:                     for( j = 0; j < NMAX; j++ )  {
 382:                     p->tty[j] = user.ut_line[j];
 383:                     }
 384:                     p->tty[ NMAX ] = NULL;
 385:                     p->loginat = user.ut_time;
 386:                     p->loggedin = 1;
 387:                 }
 388:                 }
 389:             }
 390:             p = p->link;
 391:             }  while( p != NILPERS );
 392:         }
 393:         fwopen();
 394:         p = person1;
 395:         while( p != NILPERS )  {
 396:             if( p->loggedin == 2 )  {
 397:             p->loggedin = 1;
 398:             }
 399:             decode( p );
 400:             p = p->link;
 401:         }
 402:         fwclose();
 403:         close( uf );
 404:         }
 405:         else  {
 406:         fprintf( stderr, "finger: error opening %s\n", USERLOG );
 407:         exit( 2 );
 408:         }
 409:     }
 410: 
 411:     /* print out what we got */
 412: 
 413:     if( header )  {
 414:         if( unquick )  {
 415:         if( !unshort )  {
 416:             if( wide )  {
 417:             printf(
 418: "Login       Name              TTY Idle    When            Office\n" );
 419:             }
 420:             else  {
 421:             printf(
 422: "Login    TTY Idle    When            Office\n" );
 423:             }
 424:         }
 425:         }
 426:         else  {
 427:         printf( "Login      TTY            When" );
 428:         if( idle )  {
 429:             printf( "             Idle" );
 430:         }
 431:         printf( "\n" );
 432:         }
 433:     }
 434:     p = person1;
 435:     do  {
 436:         if( unquick )  {
 437:         if( unshort )  {
 438:             personprint( p );
 439:             if( p->pwd != NILPWD )  {
 440:             if( hack )  {
 441:                 s = malloc(strlen((p->pwd)->pw_dir) + PROJLEN + 1 );
 442:                 strcpy(  s, (p->pwd)->pw_dir  );
 443:                 strcat( s, PROJ );
 444:                 if(  ( fp = fopen( s, "r") )  != NULL  )  {
 445:                 printf( "Project: " );
 446:                 while(  ( c = getc(fp) )  !=  EOF  )  {
 447:                     if( c == LINEBREAK )  {
 448:                     break;
 449:                     }
 450:                     putc( c, stdout );
 451:                 }
 452:                 fclose( fp );
 453:                 printf( "\n" );
 454:                 }
 455:             }
 456:             if( plan )  {
 457:                 s = malloc( strlen( (p->pwd)->pw_dir ) + PLANLEN + 1 );
 458:                 strcpy(  s, (p->pwd)->pw_dir  );
 459:                 strcat( s, PLAN );
 460:                 if(  ( fp = fopen( s, "r") )  == NULL  )  {
 461:                 printf( "No Plan.\n" );
 462:                 }
 463:                 else  {
 464:                 printf( "Plan:\n" );
 465:                 while(  ( c = getc(fp) )  !=  EOF  )  {
 466:                     putc( c, stdout );
 467:                 }
 468:                 fclose( fp );
 469:                 }
 470:             }
 471:             }
 472:             if( p->link != NILPERS )  {
 473:             printf( "\n" );
 474:             }
 475:         }
 476:         else  {
 477:             shortprint( p );
 478:         }
 479:         }
 480:         else  {
 481:         quickprint( p );
 482:         }
 483:         p = p->link;
 484:     }  while( p != NILPERS );
 485:     exit(0);
 486: }
 487: 
 488: 
 489: /*  given a pointer to a pwd (pfrom) copy it to another one, allocating
 490:  *  space for all the stuff in it.  Note: Only the useful (what the
 491:  *  program currently uses) things are copied.
 492:  */
 493: 
 494: pwdcopy( pto, pfrom )       /* copy relevant fields only */
 495: 
 496:     struct  passwd      *pto,  *pfrom;
 497: {
 498:     pto->pw_name = malloc(  strlen( pfrom->pw_name ) + 1  );
 499:     strcpy( pto->pw_name, pfrom->pw_name );
 500:     pto->pw_uid = pfrom->pw_uid;
 501:     pto->pw_gecos = malloc(  strlen( pfrom->pw_gecos ) + 1  );
 502:     strcpy( pto->pw_gecos, pfrom->pw_gecos );
 503:     pto->pw_dir = malloc(  strlen( pfrom->pw_dir ) + 1  );
 504:     strcpy( pto->pw_dir, pfrom->pw_dir );
 505:     pto->pw_shell = malloc(  strlen( pfrom->pw_shell ) + 1  );
 506:     strcpy( pto->pw_shell, pfrom->pw_shell );
 507: }
 508: 
 509: 
 510: /*  print out information on quick format giving just name, tty, login time
 511:  *  and idle time if idle is set.
 512:  */
 513: 
 514: quickprint( pers )
 515: 
 516:     struct  person      *pers;
 517: {
 518:     printf( "%-*.*s", NMAX, NMAX, pers->name );
 519:     printf( "  " );
 520:     if( pers->loggedin )  {
 521:         if( idle )  {
 522:         findidle( pers );
 523:         if( pers->writeable )  {
 524:             printf(  " %-*.*s %-16.16s", LMAX, LMAX,
 525:             pers->tty, ctime( &pers->loginat )  );
 526:         }
 527:         else  {
 528:             printf(  "*%-*.*s %-16.16s", LMAX, LMAX,
 529:             pers->tty, ctime( &pers->loginat )  );
 530:         }
 531:         printf( "   " );
 532:         }
 533:         else  {
 534:         printf(  " %-*.*s %-16.16s", LMAX, LMAX,
 535:             pers->tty, ctime( &pers->loginat )  );
 536:         }
 537:     }
 538:     else  {
 539:         printf( "          Not Logged In" );
 540:     }
 541:     printf( "\n" );
 542: }
 543: 
 544: 
 545: /*  print out information in short format, giving login name, full name,
 546:  *  tty, idle time, login time, office location and phone.
 547:  */
 548: 
 549: shortprint( pers )
 550: 
 551:     struct  person  *pers;
 552: 
 553: {
 554:     struct  passwd      *pwdt = pers->pwd;
 555:     char            buf[ 26 ];
 556:     int         i,  len,  offset,  dialup;
 557: 
 558:     if( pwdt == NILPWD )  {
 559:         printf( "%-*.*s", NMAX, NMAX,  pers->name );
 560:         printf( "       ???\n" );
 561:         return;
 562:     }
 563:     printf( "%-*.*s", NMAX, NMAX,  pwdt->pw_name );
 564:     dialup = 0;
 565:     if( wide )  {
 566:         if(  strlen( pers->realname ) > 0  )  {
 567:         printf( " %-20.20s", pers->realname );
 568:         }
 569:         else  {
 570:         printf( "        ???          " );
 571:         }
 572:     }
 573:     if( pers->loggedin )  {
 574:         if( pers->writeable )  {
 575:         printf( "  " );
 576:         }
 577:         else  {
 578:         printf( " *" );
 579:         }
 580:     }
 581:     else  {
 582:         printf( "  " );
 583:     }
 584:     if(  strlen( pers->tty ) > 0  )  {
 585:         strcpy( buf, pers->tty );
 586:         if(  (buf[0] == 't')  &&  (buf[1] == 't')  &&  (buf[2] == 'y')  )  {
 587:         offset = 3;
 588:         for( i = 0; i < 2; i++ )  {
 589:             buf[i] = buf[i + offset];
 590:         }
 591:         }
 592:         if(  (buf[0] == 'd')  &&  pers->loggedin  )  {
 593:         dialup = 1;
 594:         }
 595:         printf( "%-2.2s ", buf );
 596:     }
 597:     else  {
 598:         printf( "   " );
 599:     }
 600:     strcpy( buf, ctime( &pers->loginat ) );
 601:     if( pers->loggedin )  {
 602:         stimeprint( &pers->idletime );
 603:         offset = 7;
 604:         for( i = 4; i < 19; i++ )  {
 605:         buf[i] = buf[i + offset];
 606:         }
 607:         printf( " %-9.9s ", buf );
 608:     }
 609:     else  {
 610:         printf( " " );
 611:         offset = 4;
 612:         for( i = 0; i <22; i++ )  {
 613:         buf[i] = buf[i + offset];
 614:         }
 615:         printf( "<%-12.12s>", buf );
 616:     }
 617:     len = strlen( pers->homephone );
 618:     if(  dialup  &&  (len > 0)  )  {
 619:         if( len == 8 )  {
 620:         printf( "             " );
 621:         }
 622:         else  {
 623:         if( len == 12 )  {
 624:             printf( "         " );
 625:         }
 626:         else {
 627:             for( i = 1; i <= 21 - len; i++ )  {
 628:             printf( " " );
 629:             }
 630:         }
 631:         }
 632:         printf( "%s", pers->homephone );
 633:     }
 634:     else  {
 635:         if(  strlen( pers->office ) > 0  )  {
 636:         printf( " %-11.11s", pers->office );
 637:         if(  strlen( pers->officephone ) > 0  )  {
 638:             printf( " %8.8s", pers->officephone );
 639:         }
 640:         else  {
 641:             if( len == 8 )  {
 642:             printf( " %8.8s", pers->homephone );
 643:             }
 644:         }
 645:         }
 646:         else  {
 647:         if(  strlen( pers->officephone ) > 0  )  {
 648:             printf( "             %8.8s", pers->officephone );
 649:         }
 650:         else  {
 651:             if( len == 8 )  {
 652:             printf( "             %8.8s", pers->homephone );
 653:             }
 654:             else  {
 655:             if( len == 12 )  {
 656:                 printf( "         %12.12s", pers->homephone );
 657:             }
 658:             }
 659:         }
 660:         }
 661:     }
 662:     printf( "\n" );
 663: }
 664: 
 665: 
 666: /*  print out a person in long format giving all possible information.
 667:  *  directory and shell are inhibited if unbrief is clear.
 668:  */
 669: 
 670: personprint( pers )
 671: 
 672:     struct  person  *pers;
 673: {
 674:     struct  passwd      *pwdt = pers->pwd;
 675:     int         idleprinted;
 676: 
 677:     if( pwdt == NILPWD )  {
 678:         printf( "Login name: %-10s", pers->name );
 679:         printf( "			" );
 680:         printf( "In real life: ???\n");
 681:         return;
 682:     }
 683:     printf( "Login name: %-10s", pwdt->pw_name );
 684:     if( pers->loggedin )  {
 685:         if( pers->writeable )  {
 686:         printf( "			" );
 687:         }
 688:         else  {
 689:         printf( "	(messages off)	" );
 690:         }
 691:     }
 692:     else  {
 693:         printf( "			" );
 694:     }
 695:     if(  strlen( pers->realname ) > 0  )  {
 696:         printf( "In real life: %-s", pers->realname );
 697:     }
 698:     if(  strlen( pers->office ) > 0  )  {
 699:         printf( "\nOffice: %-.11s", pers->office );
 700:         if(  strlen( pers->officephone ) > 0  )  {
 701:         printf( ", %s", pers->officephone );
 702:         if(  strlen( pers->homephone ) > 0  )  {
 703:             printf( "		Home phone: %s", pers->homephone );
 704:         }
 705:         else  {
 706:             if(  strlen( pers->random ) > 0  )  {
 707:             printf( "	%s", pers->random );
 708:             }
 709:         }
 710:         }
 711:         else  {
 712:         if(  strlen( pers->homephone ) > 0  )  {
 713:             printf("			Home phone: %s",pers->homephone);
 714:         }
 715:         if(  strlen( pers->random ) > 0  )  {
 716:             printf( "			%s", pers->random );
 717:         }
 718:         }
 719:     }
 720:     else  {
 721:         if(  strlen( pers->officephone ) > 0  )  {
 722:         printf( "\nPhone: %s", pers->officephone );
 723:         if(  strlen( pers->homephone ) > 0  )  {
 724:             printf( "\n, %s", pers->homephone );
 725:             if(  strlen( pers->random ) > 0  )  {
 726:             printf( ", %s", pers->random );
 727:             }
 728:         }
 729:         else  {
 730:             if(  strlen( pers->random ) > 0  )  {
 731:             printf( "\n, %s", pers->random );
 732:             }
 733:         }
 734:         }
 735:         else  {
 736:         if(  strlen( pers->homephone ) > 0  )  {
 737:             printf( "\nPhone: %s", pers->homephone );
 738:             if(  strlen( pers->random ) > 0  )  {
 739:             printf( ", %s", pers->random );
 740:             }
 741:         }
 742:         else  {
 743:             if(  strlen( pers->random ) > 0  )  {
 744:             printf( "\n%s", pers->random );
 745:             }
 746:         }
 747:         }
 748:     }
 749:     if( unbrief )  {
 750:         printf( "\n" );
 751:         printf( "Directory: %-25s", pwdt->pw_dir );
 752:         if(  strlen( pwdt->pw_shell ) > 0  )  {
 753:         printf( "	Shell: %-s", pwdt->pw_shell );
 754:         }
 755:     }
 756:     if( pers->loggedin )  {
 757:         register char *ep = ctime( &pers->loginat );
 758:         printf("\nOn since %15.15s on %-*.*s	", &ep[4], LMAX, LMAX, pers->tty );
 759:         idleprinted = ltimeprint( &pers->idletime );
 760:         if( idleprinted )  {
 761:         printf( " Idle Time" );
 762:         }
 763:     }
 764:     else  {
 765:         register char *ep = ctime( &pers->loginat );
 766:         printf("\nLast login %16.16s on %.*s", ep, LMAX, pers->tty );
 767:     }
 768:     printf( "\n" );
 769: }
 770: 
 771: 
 772: /*
 773:  *  very hacky section of code to format phone numbers.  filled with
 774:  *  magic constants like 4, 7 and 10.
 775:  */
 776: 
 777: char  *
 778: phone( s, len )
 779: 
 780:     char        *s;
 781:     int         len;
 782: {
 783:     char        *strsave();
 784:     char        fonebuf[ 15 ];
 785:     int     i;
 786: 
 787:     switch(  len  )  {
 788: 
 789:         case  4:
 790:         fonebuf[ 0 ] = ' ';
 791:         fonebuf[ 1 ] = 'x';
 792:         fonebuf[ 2 ] = '2';
 793:         fonebuf[ 3 ] = '-';
 794:         for( i = 0; i <= 3; i++ )  {
 795:             fonebuf[ 4 + i ] = *s++;
 796:         }
 797:         fonebuf[ 8 ] = NULL;
 798:         return( strsave( &fonebuf[0] ) );
 799:         /*NOTREACHED*/
 800: 
 801:         case  7:
 802:         for( i = 0; i <= 2; i++ )  {
 803:             fonebuf[ i ] = *s++;
 804:         }
 805:         fonebuf[ 3 ] = '-';
 806:         for( i = 0; i <= 3; i++ )  {
 807:             fonebuf[ 4 + i ] = *s++;
 808:         }
 809:         fonebuf[ 8 ] = NULL;
 810:         return( strsave( &fonebuf[0] ) );
 811:         break;
 812: 
 813:         case 10:
 814:         for( i = 0; i <= 2; i++ )  {
 815:             fonebuf[ i ] = *s++;
 816:         }
 817:         fonebuf[ 3 ] = '-';
 818:         for( i = 0; i <= 2; i++ )  {
 819:             fonebuf[ 4 + i ] = *s++;
 820:         }
 821:         fonebuf[ 7 ] = '-';
 822:         for( i = 0; i <= 3; i++ )  {
 823:             fonebuf[ 8 + i ] = *s++;
 824:         }
 825:         fonebuf[ 12 ] = NULL;
 826:         return( strsave( &fonebuf[0] ) );
 827:         /*NOTREACHED*/
 828: 
 829:         default:
 830:         fprintf( stderr, "finger: error in phone numbering\n" );
 831:         return( strsave(s) );
 832:         /*NOTREACHED*/
 833:     }
 834:     /*NOTREACHED*/
 835: }
 836: 
 837: 
 838: /*  decode the information in the gecos field of /etc/passwd
 839:  *  another hacky section of code, but given the format the stuff is in...
 840:  */
 841: 
 842: decode( pers )
 843: 
 844:     struct  person  *pers;
 845: 
 846: {
 847:     struct  passwd      *pwdt = pers->pwd;
 848:     char            buffer[ 40 ],  *bp,  *gp,  *lp;
 849:     char            *phone();
 850:     int         alldigits;
 851:     int         len;
 852: 
 853:     pers->realname = NULLSTR;
 854:     pers->office = NULLSTR;
 855:     pers->officephone = NULLSTR;
 856:     pers->homephone = NULLSTR;
 857:     pers->random = NULLSTR;
 858:     if(  pwdt != NILPWD )  {
 859:         gp = pwdt->pw_gecos;
 860:         bp = &buffer[ 0 ];
 861:         if( *gp == ASTERISK )  {
 862:         gp++;
 863:         }
 864:         while(  (*gp != NULL)  &&  (*gp != COMMA)  )  { /* name */
 865:         if( *gp == SAMENAME )  {
 866:             lp = pwdt->pw_name;
 867:             *bp++ = CAPITALIZE(*lp++);
 868:             while( *lp != NULL )  {
 869:             *bp++ = *lp++;
 870:             }
 871:         }
 872:         else  {
 873:             *bp++ = *gp;
 874:         }
 875:         gp++;
 876:         }
 877:         *bp = NULL;
 878:         pers->realname = malloc( strlen( &buffer[0] ) + 1 );
 879:         strcpy( pers->realname, &buffer[0] );
 880:         if( *gp++ == COMMA )  {         /* office, supposedly */
 881:         alldigits = 1;
 882:         bp = &buffer[ 0 ];
 883:         while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
 884:             *bp = *gp++;
 885:             alldigits = alldigits && ('0' <= *bp) && (*bp <= '9');
 886:             bp++;
 887:         }
 888:         *bp = NULL;
 889:         len = strlen( &buffer[0] );
 890:         if( buffer[ len - 1 ]  ==  CORY )  {
 891:             strcpy( &buffer[ len - 1 ], " Cory" );
 892:             pers->office = malloc( len + 5 );
 893:             strcpy( pers->office, &buffer[0] );
 894:         }
 895:         else  {
 896:             if( buffer[ len - 1 ] == EVANS )  {
 897:             strcpy( &buffer[ len - 1 ], " Evans" );
 898:             pers->office = malloc( len + 6 );
 899:             strcpy( pers->office, &buffer[0] );
 900:             }
 901:             else  {
 902:             if( buffer[ len - 1 ] == 'L' )  {
 903:                 strcpy( &buffer[ len - 1 ], " LBL" );
 904:                 pers->office = malloc( len + 4 );
 905:                 strcpy( pers->office, &buffer[0] );
 906:             }
 907:             else  {
 908:                 if( alldigits )  {
 909:                 if( len == 4 )  {
 910:                     pers->officephone = phone(&buffer[0], len);
 911:                 }
 912:                 else  {
 913:                     if(  (len == 7) || (len == 10)  )  {
 914:                     pers->homephone = phone(&buffer[0],len);
 915:                     }
 916:                 }
 917:                 }
 918:                 else  {
 919:                 pers->random = malloc( len + 1 );
 920:                 strcpy( pers->random, &buffer[0] );
 921:                 }
 922:             }
 923:             }
 924:         }
 925:         if( *gp++ == COMMA )  {     /* office phone, theoretically */
 926:             bp = &buffer[ 0 ];
 927:             alldigits = 1;
 928:             while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
 929:             *bp = *gp++;
 930:             alldigits = alldigits && ('0' <= *bp) && (*bp <= '9');
 931:             bp++;
 932:             }
 933:             *bp = NULL;
 934:             len = strlen( &buffer[0] );
 935:             if( alldigits )  {
 936:             if(  len != 4  )  {
 937:                 if(  (len == 7) || (len == 10)  )  {
 938:                 pers->homephone = phone( &buffer[0], len );
 939:                 }
 940:                 else  {
 941:                 pers->random = malloc( len + 1 );
 942:                 strcpy( pers->random, &buffer[0] );
 943:                 }
 944:             }
 945:             else  {
 946:                 pers->officephone = phone( &buffer[0], len );
 947:             }
 948:             }
 949:             else  {
 950:             pers->random = malloc( len + 1 );
 951:             strcpy( pers->random, &buffer[0] );
 952:             }
 953:             if( *gp++ == COMMA )  {     /* home phone?? */
 954:             bp = &buffer[ 0 ];
 955:             alldigits = 1;
 956:                 while(  (*gp != NULL)  &&  (*gp != COMMA)  )  {
 957:                 *bp = *gp++;
 958:                 alldigits = alldigits && ('0' <= *bp) &&
 959:                             (*bp <= '9');
 960:                 bp++;
 961:                 }
 962:             *bp = NULL;
 963:             len = strlen( &buffer[0] );
 964:             if( alldigits  &&  ( (len == 7) || (len == 10) )  )  {
 965:                 if( *pers->homephone != NULL )  {
 966:                 pers->officephone = pers->homephone;
 967:                 }
 968:                 pers->homephone = phone( &buffer[0], len );
 969:             }
 970:             else  {
 971:                 pers->random = malloc( strlen( &buffer[0] ) + 1 );
 972:                 strcpy( pers->random, &buffer[0] );
 973:             }
 974:             }
 975:         }
 976:         }
 977:         if( pers->loggedin == 0 )  {
 978:         findwhen( pers );
 979:         }
 980:         else  {
 981:         findidle( pers );
 982:         }
 983:     }
 984: }
 985: 
 986: 
 987: /*  find the last log in of a user by checking the LASTLOG file.
 988:  *  the entry is indexed by the uid, so this can only be done if
 989:  *  the uid is known (which it isn't in quick mode)
 990:  */
 991: 
 992: fwopen()
 993: {
 994:     if(  ( lf = open(LASTLOG, 0) ) >= 0  )  {
 995:         llopenerr = 0;
 996:     }
 997:     else  {
 998: #ifdef notdef
 999: /* lots of places don't have lastlog, so don't complain */
1000:         fprintf( stderr, "finger: lastlog open error\n" );
1001: #endif
1002:         llopenerr = 1;
1003:     }
1004: }
1005: 
1006: 
1007: findwhen( pers )
1008: 
1009:     struct  person  *pers;
1010: {
1011:     struct  passwd      *pwdt = pers->pwd;
1012:     struct  lastlog     ll;
1013:     int         llsize = sizeof ll;
1014:     int         i;
1015: 
1016:     if( !llopenerr )  {
1017:         lseek( lf, (long) pwdt->pw_uid*llsize, 0 );
1018:         if( read( lf, (char *) &ll, llsize ) == llsize )  {
1019:             for( i = 0; i < LMAX; i++ )  {
1020:             pers->tty[ i ] = ll.ll_line[ i ];
1021:             }
1022:             pers->tty[ LMAX ] = NULL;
1023:             pers->loginat = ll.ll_time;
1024:         }
1025:         else  {
1026:         fprintf( stderr, "finger: lastlog read error\n" );
1027:         pers->tty[ 0 ] = NULL;
1028:         pers->loginat = 0L;
1029:         }
1030:     }
1031:     else  {
1032:         pers->tty[ 0 ] = NULL;
1033:         pers->loginat = 0L;
1034:     }
1035: }
1036: 
1037: 
1038: fwclose()
1039: {
1040:     if( !llopenerr )  {
1041:         close( lf );
1042:     }
1043: }
1044: 
1045: 
1046: /*  find the idle time of a user by doing a stat on /dev/histty,
1047:  *  where histty has been gotten from USERLOG, supposedly.
1048:  */
1049: 
1050: findidle( pers )
1051: 
1052:     struct  person  *pers;
1053: {
1054:     struct  stat        ttystatus;
1055:     char            buffer[ 20 ];
1056:     char            *TTY = "/dev/";
1057:     int         TTYLEN = strlen( TTY );
1058:     int         i;
1059: 
1060:     strcpy( &buffer[0], TTY );
1061:     i = 0;
1062:     do  {
1063:         buffer[ TTYLEN + i ] = pers->tty[ i ];
1064:     }  while( ++i <= LMAX );
1065:     if(  stat( &buffer[0], &ttystatus ) >= 0  )  {
1066:         time( &tloc );
1067:         if( tloc < ttystatus.st_atime )  {
1068:         pers->idletime = 0L;
1069:         }
1070:         else  {
1071:         pers->idletime = tloc - ttystatus.st_atime;
1072:         }
1073:         if(  (ttystatus.st_mode & TALKABLE) == TALKABLE  )  {
1074:         pers->writeable = 1;
1075:         }
1076:         else  {
1077:         pers->writeable = 0;
1078:         }
1079:     }
1080:     else  {
1081:         fprintf( stderr, "finger: error STATing %s\n", &buffer[0] );
1082:         exit( 4 );
1083:     }
1084: }
1085: 
1086: 
1087: /*  print idle time in short format; this program always prints 4 characters;
1088:  *  if the idle time is zero, it prints 4 blanks.
1089:  */
1090: 
1091: stimeprint( dt )
1092: 
1093:     long    *dt;
1094: {
1095:     struct  tm      *gmtime();
1096:     struct  tm      *delta;
1097: 
1098:     delta = gmtime( dt );
1099:     if( delta->tm_yday == 0 )  {
1100:         if( delta->tm_hour == 0 )  {
1101:         if( delta->tm_min >= 10 )  {
1102:             printf( " %2.2d ", delta->tm_min );
1103:         }
1104:         else  {
1105:             if( delta->tm_min == 0 )  {
1106:             printf( "    " );
1107:             }
1108:             else  {
1109:             printf( "  %1.1d ", delta->tm_min );
1110:             }
1111:         }
1112:         }
1113:         else  {
1114:         if( delta->tm_hour >= 10 )  {
1115:             printf( "%3.3d:", delta->tm_hour );
1116:         }
1117:         else  {
1118:             printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min );
1119:         }
1120:         }
1121:     }
1122:     else  {
1123:         printf( "%3dd", delta->tm_yday );
1124:     }
1125: }
1126: 
1127: 
1128: /*  print idle time in long format with care being taken not to pluralize
1129:  *  1 minutes or 1 hours or 1 days.
1130:  */
1131: 
1132: ltimeprint( dt )
1133: 
1134:     long    *dt;
1135: {
1136:     struct  tm      *gmtime();
1137:     struct  tm      *delta;
1138:     int         printed = 1;
1139: 
1140:     delta = gmtime( dt );
1141:     if( delta->tm_yday == 0 )  {
1142:         if( delta->tm_hour == 0 )  {
1143:         if( delta->tm_min >= 10 )  {
1144:             printf( "%2d minutes", delta->tm_min );
1145:         }
1146:         else  {
1147:             if( delta->tm_min == 0 )  {
1148:             if( delta->tm_sec > 10 )  {
1149:                 printf( "%2d seconds", delta->tm_sec );
1150:             }
1151:             else  {
1152:                 printed = 0;
1153:             }
1154:             }
1155:             else  {
1156:             if( delta->tm_min == 1 )  {
1157:                 if( delta->tm_sec == 1 )  {
1158:                 printf( "%1d minute %1d second",
1159:                     delta->tm_min, delta->tm_sec );
1160:                 }
1161:                 else  {
1162:                 printf( "%1d minute %d seconds",
1163:                     delta->tm_min, delta->tm_sec );
1164:                 }
1165:             }
1166:             else  {
1167:                 if( delta->tm_sec == 1 )  {
1168:                 printf( "%1d minutes %1d second",
1169:                     delta->tm_min, delta->tm_sec );
1170:                 }
1171:                 else  {
1172:                 printf( "%1d minutes %d seconds",
1173:                     delta->tm_min, delta->tm_sec );
1174:                 }
1175:             }
1176:             }
1177:         }
1178:         }
1179:         else  {
1180:         if( delta->tm_hour >= 10 )  {
1181:             printf( "%2d hours", delta->tm_hour );
1182:         }
1183:         else  {
1184:             if( delta->tm_hour == 1 )  {
1185:             if( delta->tm_min == 1 )  {
1186:                 printf( "%1d hour %1d minute",
1187:                 delta->tm_hour, delta->tm_min );
1188:             }
1189:             else  {
1190:                 printf( "%1d hour %2d minutes",
1191:                 delta->tm_hour, delta->tm_min );
1192:             }
1193:             }
1194:             else  {
1195:             if( delta->tm_min == 1 )  {
1196:                 printf( "%1d hours %1d minute",
1197:                 delta->tm_hour, delta->tm_min );
1198:             }
1199:             else  {
1200:                 printf( "%1d hours %2d minutes",
1201:                 delta->tm_hour, delta->tm_min );
1202:             }
1203:             }
1204:         }
1205:         }
1206:     }
1207:     else  {
1208:         if( delta->tm_yday >= 10 )  {
1209:             printf( "%2d days", delta->tm_yday );
1210:         }
1211:         else  {
1212:             if( delta->tm_yday == 1 )  {
1213:             if( delta->tm_hour == 1 )  {
1214:                 printf( "%1d day %1d hour",
1215:                 delta->tm_yday, delta->tm_hour );
1216:             }
1217:             else  {
1218:                 printf( "%1d day %2d hours",
1219:                 delta->tm_yday, delta->tm_hour );
1220:             }
1221:             }
1222:             else  {
1223:             if( delta->tm_hour == 1 )  {
1224:                 printf( "%1d days %1d hour",
1225:                 delta->tm_yday, delta->tm_hour );
1226:             }
1227:             else  {
1228:                 printf( "%1d days %2d hours",
1229:                 delta->tm_yday, delta->tm_hour );
1230:             }
1231:             }
1232:         }
1233:     }
1234:     return( printed );
1235: }
1236: 
1237: 
1238: matchcmp( gname, login, given )
1239: 
1240:     char        *gname;
1241:     char        *login;
1242:     char        *given;
1243: {
1244:     char        buffer[ 20 ];
1245:     char        c;
1246:     int     flag,  i,  unfound;
1247: 
1248:     if( !match )  {
1249:         return( 0 );
1250:     }
1251:     else  {
1252:         if(  namecmp( login, given )  )  {
1253:         return( 1 );
1254:         }
1255:         else  {
1256:         if( *gname == ASTERISK )  {
1257:             gname++;
1258:         }
1259:         flag = 1;
1260:         i = 0;
1261:         unfound = 1;
1262:         while(  unfound  )  {
1263:             if( flag )  {
1264:             c = *gname++;
1265:             if( c == SAMENAME )  {
1266:                 flag = 0;
1267:                 c = *login++;
1268:             }
1269:             else  {
1270:                 unfound = (*gname != COMMA)  &&  (*gname != NULL);
1271:             }
1272:             }
1273:             else {
1274:             c = *login++;
1275:             if( c == NULL )  {
1276:                 if(  (*gname == COMMA)  ||  (*gname == NULL)  )  {
1277:                 break;
1278:                 }
1279:                 else  {
1280:                 flag = 1;
1281:                 continue;
1282:                 }
1283:             }
1284:             }
1285:             if( c == BLANK )  {
1286:             buffer[i++] = NULL;
1287:             if(  namecmp( buffer, given )  )  {
1288:                 return( 1 );
1289:             }
1290:             i = 0;
1291:             flag = 1;
1292:             }
1293:             else  {
1294:             buffer[ i++ ] = c;
1295:             }
1296:         }
1297:         buffer[i++] = NULL;
1298:         if(  namecmp( buffer, given )  )  {
1299:             return( 1 );
1300:         }
1301:         else  {
1302:             return( 0 );
1303:         }
1304:         }
1305:     }
1306: }
1307: 
1308: 
1309: namecmp( name1, name2 )
1310: 
1311:     char        *name1;
1312:     char        *name2;
1313: {
1314:     char        c1,  c2;
1315: 
1316:     c1 = *name1;
1317:     if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) )  {
1318:         c1 = CAPITALIZE( c1 );
1319:     }
1320:     c2 = *name2;
1321:     if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) )  {
1322:         c2 = CAPITALIZE( c2 );
1323:     }
1324:     while( c1 == c2 )  {
1325:         if( c1 == NULL )  {
1326:         return( 1 );
1327:         }
1328:         c1 = *++name1;
1329:         if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) )  {
1330:         c1 = CAPITALIZE( c1 );
1331:         }
1332:         c2 = *++name2;
1333:         if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) )  {
1334:         c2 = CAPITALIZE( c2 );
1335:         }
1336:     }
1337:     if( *name1 == NULL )  {
1338:         while(  ('0' <= *name2)  &&  (*name2 <= '9')  )  {
1339:         name2++;
1340:         }
1341:         if( *name2 == NULL )  {
1342:         return( 1 );
1343:         }
1344:     }
1345:     else  {
1346:         if( *name2 == NULL )  {
1347:         while(  ('0' <= *name1)  &&  (*name1 <= '9')  )  {
1348:             name1++;
1349:         }
1350:         if( *name1 == NULL )  {
1351:             return( 1 );
1352:         }
1353:         }
1354:     }
1355:     return( 0 );
1356: }
1357: 
1358: 
1359: char  *
1360: strsave( s )
1361: 
1362:     char        *s;
1363: {
1364:     char        *malloc();
1365:     char        *p;
1366: 
1367:     p = malloc( strlen( s ) + 1 );
1368:     strcpy( p, s );
1369:     return( p );
1370: }

Defined functions

decode defined in line 842; used 2 times
findidle defined in line 1050; used 2 times
findwhen defined in line 1007; used 1 times
fwclose defined in line 1038; used 2 times
fwopen defined in line 992; used 2 times
ltimeprint defined in line 1132; used 1 times
main defined in line 113; never used
matchcmp defined in line 1238; used 1 times
namecmp defined in line 1309; used 3 times
personprint defined in line 670; used 1 times
phone defined in line 777; used 6 times
pwdcopy defined in line 494; used 4 times
quickprint defined in line 514; used 1 times
shortprint defined in line 549; used 1 times
stimeprint defined in line 1091; used 1 times
strsave defined in line 1359; used 5 times

Defined variables

LASTLOG defined in line 90; used 1 times
NILPERS defined in line 85; used 9 times
NILPWD defined in line 84; used 15 times
USERLOG defined in line 91; used 4 times
hack defined in line 97; used 2 times
header defined in line 96; used 2 times
idle defined in line 98; used 4 times
large defined in line 99; used 2 times
lf defined in line 106; used 4 times
llopenerr defined in line 107; used 4 times
match defined in line 100; used 2 times
outbuf defined in line 92; used 1 times
persize defined in line 87; used 6 times
plan defined in line 101; used 2 times
pwdsize defined in line 88; used 4 times
sccsid defined in line 2; never used
small defined in line 103; used 2 times
tloc defined in line 109; used 5 times
unbrief defined in line 95; used 2 times
unquick defined in line 102; used 7 times
utmp defined in line 52; used 2 times
wide defined in line 104; used 3 times

Defined struct's

person defined in line 68; used 32 times

Defined macros

ASTERISK defined in line 56; used 2 times
BLANK defined in line 57; used 1 times
CAPITALIZE defined in line 58; used 5 times
COMMA defined in line 59; used 9 times
COMMAND defined in line 60; used 1 times
CORY defined in line 61; used 1 times
EVANS defined in line 62; used 1 times
LINEBREAK defined in line 63; used 1 times
LMAX defined in line 54; used 13 times
NMAX defined in line 53; used 21 times
NULLSTR defined in line 64; used 5 times
SAMENAME defined in line 65; used 2 times
TALKABLE defined in line 66; used 2 times
Last modified: 1982-10-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3459
Valid CSS Valid XHTML 1.0 Strict