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