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