|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)finger.c 4.5 (Berkeley) 9/16/83"; ! 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 <sys/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 int loggedin; /* flag for being logged in */ ! 74: short int 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, *pn, *ln; ! 126: char 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: int idleprinted; ! 519: ! 520: printf( "%-*.*s", NMAX, NMAX, pers->name ); ! 521: printf( " " ); ! 522: if( pers->loggedin ) { ! 523: if( idle ) { ! 524: findidle( pers ); ! 525: if( pers->writeable ) { ! 526: printf( " %-*.*s %-16.16s", LMAX, LMAX, ! 527: pers->tty, ctime( &pers->loginat ) ); ! 528: } ! 529: else { ! 530: printf( "*%-*.*s %-16.16s", LMAX, LMAX, ! 531: pers->tty, ctime( &pers->loginat ) ); ! 532: } ! 533: printf( " " ); ! 534: idleprinted = ltimeprint( &pers->idletime ); ! 535: } ! 536: else { ! 537: printf( " %-*.*s %-16.16s", LMAX, LMAX, ! 538: pers->tty, ctime( &pers->loginat ) ); ! 539: } ! 540: } ! 541: else { ! 542: printf( " Not Logged In" ); ! 543: } ! 544: printf( "\n" ); ! 545: } ! 546: ! 547: ! 548: /* print out information in short format, giving login name, full name, ! 549: * tty, idle time, login time, office location and phone. ! 550: */ ! 551: ! 552: shortprint( pers ) ! 553: ! 554: struct person *pers; ! 555: ! 556: { ! 557: struct passwd *pwdt = pers->pwd; ! 558: char buf[ 26 ]; ! 559: int i, len, offset, dialup; ! 560: ! 561: if( pwdt == NILPWD ) { ! 562: printf( "%-*.*s", NMAX, NMAX, pers->name ); ! 563: printf( " ???\n" ); ! 564: return; ! 565: } ! 566: printf( "%-*.*s", NMAX, NMAX, pwdt->pw_name ); ! 567: dialup = 0; ! 568: if( wide ) { ! 569: if( strlen( pers->realname ) > 0 ) { ! 570: printf( " %-20.20s", pers->realname ); ! 571: } ! 572: else { ! 573: printf( " ??? " ); ! 574: } ! 575: } ! 576: if( pers->loggedin ) { ! 577: if( pers->writeable ) { ! 578: printf( " " ); ! 579: } ! 580: else { ! 581: printf( " *" ); ! 582: } ! 583: } ! 584: else { ! 585: printf( " " ); ! 586: } ! 587: if( strlen( pers->tty ) > 0 ) { ! 588: strcpy( buf, pers->tty ); ! 589: if( (buf[0] == 't') && (buf[1] == 't') && (buf[2] == 'y') ) { ! 590: offset = 3; ! 591: for( i = 0; i < 2; i++ ) { ! 592: buf[i] = buf[i + offset]; ! 593: } ! 594: } ! 595: if( (buf[0] == 'd') && pers->loggedin ) { ! 596: dialup = 1; ! 597: } ! 598: printf( "%-2.2s ", buf ); ! 599: } ! 600: else { ! 601: printf( " " ); ! 602: } ! 603: strcpy(buf, ctime(&pers->loginat)); ! 604: if( pers->loggedin ) { ! 605: stimeprint( &pers->idletime ); ! 606: offset = 7; ! 607: for( i = 4; i < 19; i++ ) { ! 608: buf[i] = buf[i + offset]; ! 609: } ! 610: printf( " %-9.9s ", buf ); ! 611: } ! 612: else if (pers->loginat == 0) ! 613: printf(" < . . . . >"); ! 614: else if (tloc - pers->loginat >= 180 * 24 * 60 * 60) ! 615: printf( " <%-6.6s, %-4.4s>", buf+4, buf+20 ); ! 616: else ! 617: printf(" <%-12.12s>", buf+4); ! 618: len = strlen( pers->homephone ); ! 619: if( dialup && (len > 0) ) { ! 620: if( len == 8 ) { ! 621: printf( " " ); ! 622: } ! 623: else { ! 624: if( len == 12 ) { ! 625: printf( " " ); ! 626: } ! 627: else { ! 628: for( i = 1; i <= 21 - len; i++ ) { ! 629: printf( " " ); ! 630: } ! 631: } ! 632: } ! 633: printf( "%s", pers->homephone ); ! 634: } ! 635: else { ! 636: if( strlen( pers->office ) > 0 ) { ! 637: printf( " %-11.11s", pers->office ); ! 638: if( strlen( pers->officephone ) > 0 ) { ! 639: printf( " %8.8s", pers->officephone ); ! 640: } ! 641: else { ! 642: if( len == 8 ) { ! 643: printf( " %8.8s", pers->homephone ); ! 644: } ! 645: } ! 646: } ! 647: else { ! 648: if( strlen( pers->officephone ) > 0 ) { ! 649: printf( " %8.8s", pers->officephone ); ! 650: } ! 651: else { ! 652: if( len == 8 ) { ! 653: printf( " %8.8s", pers->homephone ); ! 654: } ! 655: else { ! 656: if( len == 12 ) { ! 657: printf( " %12.12s", pers->homephone ); ! 658: } ! 659: } ! 660: } ! 661: } ! 662: } ! 663: printf( "\n" ); ! 664: } ! 665: ! 666: ! 667: /* print out a person in long format giving all possible information. ! 668: * directory and shell are inhibited if unbrief is clear. ! 669: */ ! 670: ! 671: personprint( pers ) ! 672: ! 673: struct person *pers; ! 674: { ! 675: struct passwd *pwdt = pers->pwd; ! 676: int idleprinted; ! 677: ! 678: if( pwdt == NILPWD ) { ! 679: printf( "Login name: %-10s", pers->name ); ! 680: printf( " " ); ! 681: printf( "In real life: ???\n"); ! 682: return; ! 683: } ! 684: printf( "Login name: %-10s", pwdt->pw_name ); ! 685: if( pers->loggedin ) { ! 686: if( pers->writeable ) { ! 687: printf( " " ); ! 688: } ! 689: else { ! 690: printf( " (messages off) " ); ! 691: } ! 692: } ! 693: else { ! 694: printf( " " ); ! 695: } ! 696: if( strlen( pers->realname ) > 0 ) { ! 697: printf( "In real life: %-s", pers->realname ); ! 698: } ! 699: if( strlen( pers->office ) > 0 ) { ! 700: printf( "\nOffice: %-.11s", pers->office ); ! 701: if( strlen( pers->officephone ) > 0 ) { ! 702: printf( ", %s", pers->officephone ); ! 703: if( strlen( pers->homephone ) > 0 ) { ! 704: printf( " Home phone: %s", pers->homephone ); ! 705: } ! 706: else { ! 707: if( strlen( pers->random ) > 0 ) { ! 708: printf( " %s", pers->random ); ! 709: } ! 710: } ! 711: } ! 712: else { ! 713: if( strlen( pers->homephone ) > 0 ) { ! 714: printf(" Home phone: %s",pers->homephone); ! 715: } ! 716: if( strlen( pers->random ) > 0 ) { ! 717: printf( " %s", pers->random ); ! 718: } ! 719: } ! 720: } ! 721: else { ! 722: if( strlen( pers->officephone ) > 0 ) { ! 723: printf( "\nPhone: %s", pers->officephone ); ! 724: if( strlen( pers->homephone ) > 0 ) { ! 725: printf( "\n, %s", pers->homephone ); ! 726: if( strlen( pers->random ) > 0 ) { ! 727: printf( ", %s", pers->random ); ! 728: } ! 729: } ! 730: else { ! 731: if( strlen( pers->random ) > 0 ) { ! 732: printf( "\n, %s", pers->random ); ! 733: } ! 734: } ! 735: } ! 736: else { ! 737: if( strlen( pers->homephone ) > 0 ) { ! 738: printf( "\nPhone: %s", pers->homephone ); ! 739: if( strlen( pers->random ) > 0 ) { ! 740: printf( ", %s", pers->random ); ! 741: } ! 742: } ! 743: else { ! 744: if( strlen( pers->random ) > 0 ) { ! 745: printf( "\n%s", pers->random ); ! 746: } ! 747: } ! 748: } ! 749: } ! 750: if( unbrief ) { ! 751: printf( "\n" ); ! 752: printf( "Directory: %-25s", pwdt->pw_dir ); ! 753: if( strlen( pwdt->pw_shell ) > 0 ) { ! 754: printf( " Shell: %-s", pwdt->pw_shell ); ! 755: } ! 756: } ! 757: if( pers->loggedin ) { ! 758: register char *ep = ctime( &pers->loginat ); ! 759: printf("\nOn since %15.15s on %-*.*s ", &ep[4], LMAX, LMAX, pers->tty ); ! 760: idleprinted = ltimeprint( &pers->idletime ); ! 761: if( idleprinted ) { ! 762: printf( " Idle Time" ); ! 763: } ! 764: } ! 765: else if (pers->loginat == 0) ! 766: printf("\nNever logged in."); ! 767: else if (tloc - pers->loginat > 180 * 24 * 60 * 60) { ! 768: register char *ep = ctime( &pers->loginat ); ! 769: printf("\nLast login %10.10s, %4.4s on %.*s", ep, ep+20, LMAX, pers->tty); ! 770: } ! 771: else { ! 772: register char *ep = ctime( &pers->loginat ); ! 773: printf("\nLast login %16.16s on %.*s", ep, LMAX, pers->tty ); ! 774: } ! 775: printf( "\n" ); ! 776: } ! 777: ! 778: ! 779: /* ! 780: * very hacky section of code to format phone numbers. filled with ! 781: * magic constants like 4, 7 and 10. ! 782: */ ! 783: ! 784: char *phone( s, len ) ! 785: ! 786: char *s; ! 787: int len; ! 788: { ! 789: char *strsave(); ! 790: char fonebuf[ 15 ]; ! 791: int i; ! 792: ! 793: switch( len ) { ! 794: ! 795: case 4: ! 796: fonebuf[ 0 ] = ' '; ! 797: fonebuf[ 1 ] = 'x'; ! 798: fonebuf[ 2 ] = '2'; ! 799: fonebuf[ 3 ] = '-'; ! 800: for( i = 0; i <= 3; i++ ) { ! 801: fonebuf[ 4 + i ] = *s++; ! 802: } ! 803: fonebuf[ 8 ] = NULL; ! 804: return( strsave( &fonebuf[0] ) ); ! 805: break; ! 806: ! 807: case 7: ! 808: for( i = 0; i <= 2; i++ ) { ! 809: fonebuf[ i ] = *s++; ! 810: } ! 811: fonebuf[ 3 ] = '-'; ! 812: for( i = 0; i <= 3; i++ ) { ! 813: fonebuf[ 4 + i ] = *s++; ! 814: } ! 815: fonebuf[ 8 ] = NULL; ! 816: return( strsave( &fonebuf[0] ) ); ! 817: break; ! 818: ! 819: case 10: ! 820: for( i = 0; i <= 2; i++ ) { ! 821: fonebuf[ i ] = *s++; ! 822: } ! 823: fonebuf[ 3 ] = '-'; ! 824: for( i = 0; i <= 2; i++ ) { ! 825: fonebuf[ 4 + i ] = *s++; ! 826: } ! 827: fonebuf[ 7 ] = '-'; ! 828: for( i = 0; i <= 3; i++ ) { ! 829: fonebuf[ 8 + i ] = *s++; ! 830: } ! 831: fonebuf[ 12 ] = NULL; ! 832: return( strsave( &fonebuf[0] ) ); ! 833: break; ! 834: ! 835: default: ! 836: fprintf( stderr, "finger: error in phone numbering\n" ); ! 837: return( strsave(s) ); ! 838: break; ! 839: } ! 840: } ! 841: ! 842: ! 843: /* decode the information in the gecos field of /etc/passwd ! 844: * another hacky section of code, but given the format the stuff is in... ! 845: */ ! 846: ! 847: decode( pers ) ! 848: ! 849: struct person *pers; ! 850: ! 851: { ! 852: struct passwd *pwdt = pers->pwd; ! 853: char buffer[ 256 ], *bp, *gp, *lp; ! 854: char *phone(); ! 855: int alldigits; ! 856: int len; ! 857: int i; ! 858: ! 859: pers->realname = NULLSTR; ! 860: pers->office = NULLSTR; ! 861: pers->officephone = NULLSTR; ! 862: pers->homephone = NULLSTR; ! 863: pers->random = NULLSTR; ! 864: if( pwdt != NILPWD ) { ! 865: gp = pwdt->pw_gecos; ! 866: bp = &buffer[ 0 ]; ! 867: if( *gp == ASTERISK ) { ! 868: gp++; ! 869: } ! 870: while( (*gp != NULL) && (*gp != COMMA) ) { /* name */ ! 871: if( *gp == SAMENAME ) { ! 872: lp = pwdt->pw_name; ! 873: *bp++ = CAPITALIZE(*lp++); ! 874: while( *lp != NULL ) { ! 875: *bp++ = *lp++; ! 876: } ! 877: } ! 878: else { ! 879: *bp++ = *gp; ! 880: } ! 881: gp++; ! 882: } ! 883: *bp = NULL; ! 884: pers->realname = malloc( strlen( &buffer[0] ) + 1 ); ! 885: strcpy( pers->realname, &buffer[0] ); ! 886: if( *gp++ == COMMA ) { /* office, supposedly */ ! 887: alldigits = 1; ! 888: bp = &buffer[ 0 ]; ! 889: while( (*gp != NULL) && (*gp != COMMA) ) { ! 890: *bp = *gp++; ! 891: alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); ! 892: bp++; ! 893: } ! 894: *bp = NULL; ! 895: len = strlen( &buffer[0] ); ! 896: if( buffer[ len - 1 ] == CORY ) { ! 897: strcpy( &buffer[ len - 1 ], " Cory" ); ! 898: pers->office = malloc( len + 5 ); ! 899: strcpy( pers->office, &buffer[0] ); ! 900: } ! 901: else { ! 902: if( buffer[ len - 1 ] == EVANS ) { ! 903: strcpy( &buffer[ len - 1 ], " Evans" ); ! 904: pers->office = malloc( len + 6 ); ! 905: strcpy( pers->office, &buffer[0] ); ! 906: } ! 907: else { ! 908: if( buffer[ len - 1 ] == 'L' ) { ! 909: strcpy( &buffer[ len - 1 ], " LBL" ); ! 910: pers->office = malloc( len + 4 ); ! 911: strcpy( pers->office, &buffer[0] ); ! 912: } ! 913: else { ! 914: if( alldigits ) { ! 915: if( len == 4 ) { ! 916: pers->officephone = phone(&buffer[0], len); ! 917: } ! 918: else { ! 919: if( (len == 7) || (len == 10) ) { ! 920: pers->homephone = phone(&buffer[0],len); ! 921: } ! 922: } ! 923: } ! 924: else { ! 925: pers->random = malloc( len + 1 ); ! 926: strcpy( pers->random, &buffer[0] ); ! 927: } ! 928: } ! 929: } ! 930: } ! 931: if( *gp++ == COMMA ) { /* office phone, theoretically */ ! 932: bp = &buffer[ 0 ]; ! 933: alldigits = 1; ! 934: while( (*gp != NULL) && (*gp != COMMA) ) { ! 935: *bp = *gp++; ! 936: alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); ! 937: bp++; ! 938: } ! 939: *bp = NULL; ! 940: len = strlen( &buffer[0] ); ! 941: if( alldigits ) { ! 942: if( len != 4 ) { ! 943: if( (len == 7) || (len == 10) ) { ! 944: pers->homephone = phone( &buffer[0], len ); ! 945: } ! 946: else { ! 947: pers->random = malloc( len + 1 ); ! 948: strcpy( pers->random, &buffer[0] ); ! 949: } ! 950: } ! 951: else { ! 952: pers->officephone = phone( &buffer[0], len ); ! 953: } ! 954: } ! 955: else { ! 956: pers->random = malloc( len + 1 ); ! 957: strcpy( pers->random, &buffer[0] ); ! 958: } ! 959: if( *gp++ == COMMA ) { /* home phone?? */ ! 960: bp = &buffer[ 0 ]; ! 961: alldigits = 1; ! 962: while( (*gp != NULL) && (*gp != COMMA) ) { ! 963: *bp = *gp++; ! 964: alldigits = alldigits && ('0' <= *bp) && ! 965: (*bp <= '9'); ! 966: bp++; ! 967: } ! 968: *bp = NULL; ! 969: len = strlen( &buffer[0] ); ! 970: if( alldigits && ( (len == 7) || (len == 10) ) ) { ! 971: if( *pers->homephone != NULL ) { ! 972: pers->officephone = pers->homephone; ! 973: } ! 974: pers->homephone = phone( &buffer[0], len ); ! 975: } ! 976: else { ! 977: pers->random = malloc( strlen( &buffer[0] ) + 1 ); ! 978: strcpy( pers->random, &buffer[0] ); ! 979: } ! 980: } ! 981: } ! 982: } ! 983: if( pers->loggedin == 0 ) { ! 984: findwhen( pers ); ! 985: } ! 986: else { ! 987: findidle( pers ); ! 988: } ! 989: } ! 990: } ! 991: ! 992: ! 993: /* find the last log in of a user by checking the LASTLOG file. ! 994: * the entry is indexed by the uid, so this can only be done if ! 995: * the uid is known (which it isn't in quick mode) ! 996: */ ! 997: ! 998: fwopen() ! 999: { ! 1000: if( ( lf = open(LASTLOG, 0) ) >= 0 ) { ! 1001: llopenerr = 0; ! 1002: } ! 1003: else { ! 1004: fprintf( stderr, "finger: lastlog open error\n" ); ! 1005: llopenerr = 1; ! 1006: } ! 1007: } ! 1008: ! 1009: ! 1010: findwhen( pers ) ! 1011: ! 1012: struct person *pers; ! 1013: { ! 1014: struct passwd *pwdt = pers->pwd; ! 1015: struct lastlog ll; ! 1016: int llsize = sizeof ll; ! 1017: int i; ! 1018: ! 1019: if( !llopenerr ) { ! 1020: lseek( lf, pwdt->pw_uid*llsize, 0 ); ! 1021: if ((i = read( lf, (char *) &ll, llsize )) == llsize) { ! 1022: for( i = 0; i < LMAX; i++ ) { ! 1023: pers->tty[ i ] = ll.ll_line[ i ]; ! 1024: } ! 1025: pers->tty[ LMAX ] = NULL; ! 1026: pers->loginat = ll.ll_time; ! 1027: } ! 1028: else { ! 1029: if (i != 0) ! 1030: fprintf(stderr, "finger: lastlog read error\n"); ! 1031: pers->tty[ 0 ] = NULL; ! 1032: pers->loginat = 0L; ! 1033: } ! 1034: } ! 1035: else { ! 1036: pers->tty[ 0 ] = NULL; ! 1037: pers->loginat = 0L; ! 1038: } ! 1039: } ! 1040: ! 1041: ! 1042: fwclose() ! 1043: { ! 1044: if( !llopenerr ) { ! 1045: close( lf ); ! 1046: } ! 1047: } ! 1048: ! 1049: ! 1050: /* find the idle time of a user by doing a stat on /dev/histty, ! 1051: * where histty has been gotten from USERLOG, supposedly. ! 1052: */ ! 1053: ! 1054: findidle( pers ) ! 1055: ! 1056: struct person *pers; ! 1057: { ! 1058: struct stat ttystatus; ! 1059: struct passwd *pwdt = pers->pwd; ! 1060: char buffer[ 20 ]; ! 1061: char *TTY = "/dev/"; ! 1062: int TTYLEN = strlen( TTY ); ! 1063: int i; ! 1064: ! 1065: strcpy( &buffer[0], TTY ); ! 1066: i = 0; ! 1067: do { ! 1068: buffer[ TTYLEN + i ] = pers->tty[ i ]; ! 1069: } while( ++i <= LMAX ); ! 1070: if( stat( &buffer[0], &ttystatus ) >= 0 ) { ! 1071: time( &tloc ); ! 1072: if( tloc < ttystatus.st_atime ) { ! 1073: pers->idletime = 0L; ! 1074: } ! 1075: else { ! 1076: pers->idletime = tloc - ttystatus.st_atime; ! 1077: } ! 1078: if( (ttystatus.st_mode & TALKABLE) == TALKABLE ) { ! 1079: pers->writeable = 1; ! 1080: } ! 1081: else { ! 1082: pers->writeable = 0; ! 1083: } ! 1084: } ! 1085: else { ! 1086: fprintf( stderr, "finger: error STATing %s\n", &buffer[0] ); ! 1087: exit( 4 ); ! 1088: } ! 1089: } ! 1090: ! 1091: ! 1092: /* print idle time in short format; this program always prints 4 characters; ! 1093: * if the idle time is zero, it prints 4 blanks. ! 1094: */ ! 1095: ! 1096: stimeprint( dt ) ! 1097: ! 1098: long *dt; ! 1099: { ! 1100: struct tm *gmtime(); ! 1101: struct tm *delta; ! 1102: ! 1103: delta = gmtime( dt ); ! 1104: if( delta->tm_yday == 0 ) { ! 1105: if( delta->tm_hour == 0 ) { ! 1106: if( delta->tm_min >= 10 ) { ! 1107: printf( " %2.2d ", delta->tm_min ); ! 1108: } ! 1109: else { ! 1110: if( delta->tm_min == 0 ) { ! 1111: printf( " " ); ! 1112: } ! 1113: else { ! 1114: printf( " %1.1d ", delta->tm_min ); ! 1115: } ! 1116: } ! 1117: } ! 1118: else { ! 1119: if( delta->tm_hour >= 10 ) { ! 1120: printf( "%3.3d:", delta->tm_hour ); ! 1121: } ! 1122: else { ! 1123: printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min ); ! 1124: } ! 1125: } ! 1126: } ! 1127: else { ! 1128: printf( "%3dd", delta->tm_yday ); ! 1129: } ! 1130: } ! 1131: ! 1132: ! 1133: /* print idle time in long format with care being taken not to pluralize ! 1134: * 1 minutes or 1 hours or 1 days. ! 1135: */ ! 1136: ! 1137: ltimeprint( dt ) ! 1138: ! 1139: long *dt; ! 1140: { ! 1141: struct tm *gmtime(); ! 1142: struct tm *delta; ! 1143: int printed = 1; ! 1144: ! 1145: delta = gmtime( dt ); ! 1146: if( delta->tm_yday == 0 ) { ! 1147: if( delta->tm_hour == 0 ) { ! 1148: if( delta->tm_min >= 10 ) { ! 1149: printf( "%2d minutes", delta->tm_min ); ! 1150: } ! 1151: else { ! 1152: if( delta->tm_min == 0 ) { ! 1153: if( delta->tm_sec > 10 ) { ! 1154: printf( "%2d seconds", delta->tm_sec ); ! 1155: } ! 1156: else { ! 1157: printed = 0; ! 1158: } ! 1159: } ! 1160: else { ! 1161: if( delta->tm_min == 1 ) { ! 1162: if( delta->tm_sec == 1 ) { ! 1163: printf( "%1d minute %1d second", ! 1164: delta->tm_min, delta->tm_sec ); ! 1165: } ! 1166: else { ! 1167: printf( "%1d minute %d seconds", ! 1168: delta->tm_min, delta->tm_sec ); ! 1169: } ! 1170: } ! 1171: else { ! 1172: if( delta->tm_sec == 1 ) { ! 1173: printf( "%1d minutes %1d second", ! 1174: delta->tm_min, delta->tm_sec ); ! 1175: } ! 1176: else { ! 1177: printf( "%1d minutes %d seconds", ! 1178: delta->tm_min, delta->tm_sec ); ! 1179: } ! 1180: } ! 1181: } ! 1182: } ! 1183: } ! 1184: else { ! 1185: if( delta->tm_hour >= 10 ) { ! 1186: printf( "%2d hours", delta->tm_hour ); ! 1187: } ! 1188: else { ! 1189: if( delta->tm_hour == 1 ) { ! 1190: if( delta->tm_min == 1 ) { ! 1191: printf( "%1d hour %1d minute", ! 1192: delta->tm_hour, delta->tm_min ); ! 1193: } ! 1194: else { ! 1195: printf( "%1d hour %2d minutes", ! 1196: delta->tm_hour, delta->tm_min ); ! 1197: } ! 1198: } ! 1199: else { ! 1200: if( delta->tm_min == 1 ) { ! 1201: printf( "%1d hours %1d minute", ! 1202: delta->tm_hour, delta->tm_min ); ! 1203: } ! 1204: else { ! 1205: printf( "%1d hours %2d minutes", ! 1206: delta->tm_hour, delta->tm_min ); ! 1207: } ! 1208: } ! 1209: } ! 1210: } ! 1211: } ! 1212: else { ! 1213: if( delta->tm_yday >= 10 ) { ! 1214: printf( "%2d days", delta->tm_yday ); ! 1215: } ! 1216: else { ! 1217: if( delta->tm_yday == 1 ) { ! 1218: if( delta->tm_hour == 1 ) { ! 1219: printf( "%1d day %1d hour", ! 1220: delta->tm_yday, delta->tm_hour ); ! 1221: } ! 1222: else { ! 1223: printf( "%1d day %2d hours", ! 1224: delta->tm_yday, delta->tm_hour ); ! 1225: } ! 1226: } ! 1227: else { ! 1228: if( delta->tm_hour == 1 ) { ! 1229: printf( "%1d days %1d hour", ! 1230: delta->tm_yday, delta->tm_hour ); ! 1231: } ! 1232: else { ! 1233: printf( "%1d days %2d hours", ! 1234: delta->tm_yday, delta->tm_hour ); ! 1235: } ! 1236: } ! 1237: } ! 1238: } ! 1239: return( printed ); ! 1240: } ! 1241: ! 1242: ! 1243: matchcmp( gname, login, given ) ! 1244: ! 1245: char *gname; ! 1246: char *login; ! 1247: char *given; ! 1248: { ! 1249: char buffer[ 20 ]; ! 1250: char c; ! 1251: int flag, i, unfound; ! 1252: ! 1253: if( !match ) { ! 1254: return( 0 ); ! 1255: } ! 1256: else { ! 1257: if( namecmp( login, given ) ) { ! 1258: return( 1 ); ! 1259: } ! 1260: else if (*gname == '\0') ! 1261: return (0); ! 1262: else { ! 1263: if( *gname == ASTERISK ) { ! 1264: gname++; ! 1265: } ! 1266: flag = 1; ! 1267: i = 0; ! 1268: unfound = 1; ! 1269: while( unfound ) { ! 1270: if( flag ) { ! 1271: c = *gname++; ! 1272: if( c == SAMENAME ) { ! 1273: flag = 0; ! 1274: c = *login++; ! 1275: } ! 1276: else { ! 1277: unfound = (*gname != COMMA) && (*gname != NULL); ! 1278: } ! 1279: } ! 1280: else { ! 1281: c = *login++; ! 1282: if( c == NULL ) { ! 1283: if( (*gname == COMMA) || (*gname == NULL) ) { ! 1284: break; ! 1285: } ! 1286: else { ! 1287: flag = 1; ! 1288: continue; ! 1289: } ! 1290: } ! 1291: } ! 1292: if( c == BLANK ) { ! 1293: buffer[i++] = NULL; ! 1294: if( namecmp( buffer, given ) ) { ! 1295: return( 1 ); ! 1296: } ! 1297: i = 0; ! 1298: flag = 1; ! 1299: } ! 1300: else { ! 1301: buffer[ i++ ] = c; ! 1302: } ! 1303: } ! 1304: buffer[i++] = NULL; ! 1305: if( namecmp( buffer, given ) ) { ! 1306: return( 1 ); ! 1307: } ! 1308: else { ! 1309: return( 0 ); ! 1310: } ! 1311: } ! 1312: } ! 1313: } ! 1314: ! 1315: ! 1316: namecmp( name1, name2 ) ! 1317: ! 1318: char *name1; ! 1319: char *name2; ! 1320: { ! 1321: char c1, c2; ! 1322: ! 1323: c1 = *name1; ! 1324: if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) ) { ! 1325: c1 = CAPITALIZE( c1 ); ! 1326: } ! 1327: c2 = *name2; ! 1328: if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) ) { ! 1329: c2 = CAPITALIZE( c2 ); ! 1330: } ! 1331: while( c1 == c2 ) { ! 1332: if( c1 == NULL ) { ! 1333: return( 1 ); ! 1334: } ! 1335: c1 = *++name1; ! 1336: if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) ) { ! 1337: c1 = CAPITALIZE( c1 ); ! 1338: } ! 1339: c2 = *++name2; ! 1340: if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) ) { ! 1341: c2 = CAPITALIZE( c2 ); ! 1342: } ! 1343: } ! 1344: if( *name1 == NULL ) { ! 1345: while( ('0' <= *name2) && (*name2 <= '9') ) { ! 1346: name2++; ! 1347: } ! 1348: if( *name2 == NULL ) { ! 1349: return( 1 ); ! 1350: } ! 1351: } ! 1352: else { ! 1353: if( *name2 == NULL ) { ! 1354: while( ('0' <= *name1) && (*name1 <= '9') ) { ! 1355: name1++; ! 1356: } ! 1357: if( *name1 == NULL ) { ! 1358: return( 1 ); ! 1359: } ! 1360: } ! 1361: } ! 1362: return( 0 ); ! 1363: } ! 1364: ! 1365: ! 1366: char *strsave( s ) ! 1367: ! 1368: char *s; ! 1369: { ! 1370: char *malloc(); ! 1371: char *p; ! 1372: ! 1373: p = malloc( strlen( s ) + 1 ); ! 1374: strcpy( p, s ); ! 1375: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.