|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)finger.c 5.8 (Berkeley) 3/13/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * This is a finger program. It prints out useful information about users ! 19: * by digging it up from various system files. It is not very portable ! 20: * because the most useful parts of the information (the full user name, ! 21: * office, and phone numbers) are all stored in the VAX-unused gecos field ! 22: * of /etc/passwd, which, unfortunately, other UNIXes use for other things. ! 23: * ! 24: * There are three output formats, all of which give login name, teletype ! 25: * line number, and login time. The short output format is reminiscent ! 26: * of finger on ITS, and gives one line of information per user containing ! 27: * in addition to the minimum basic requirements (MBR), the full name of ! 28: * the user, his idle time and office location and phone number. The ! 29: * quick style output is UNIX who-like, giving only name, teletype and ! 30: * login time. Finally, the long style output give the same information ! 31: * as the short (in more legible format), the home directory and shell ! 32: * of the user, and, if it exits, a copy of the file .plan in the users ! 33: * home directory. Finger may be called with or without a list of people ! 34: * to finger -- if no list is given, all the people currently logged in ! 35: * are fingered. ! 36: * ! 37: * The program is validly called by one of the following: ! 38: * ! 39: * finger {short form list of users} ! 40: * finger -l {long form list of users} ! 41: * finger -b {briefer long form list of users} ! 42: * finger -q {quick list of users} ! 43: * finger -i {quick list of users with idle times} ! 44: * finger namelist {long format list of specified users} ! 45: * finger -s namelist {short format list of specified users} ! 46: * finger -w namelist {narrow short format list of specified users} ! 47: * ! 48: * where 'namelist' is a list of users login names. ! 49: * The other options can all be given after one '-', or each can have its ! 50: * own '-'. The -f option disables the printing of headers for short and ! 51: * quick outputs. The -b option briefens long format outputs. The -p ! 52: * option turns off plans for long format outputs. ! 53: */ ! 54: ! 55: #include <sys/types.h> ! 56: #include <sys/stat.h> ! 57: #include <utmp.h> ! 58: #include <sys/signal.h> ! 59: #include <pwd.h> ! 60: #include <stdio.h> ! 61: #include <lastlog.h> ! 62: #include <ctype.h> ! 63: #include <sys/time.h> ! 64: #include <sys/socket.h> ! 65: #include <netinet/in.h> ! 66: #include <netdb.h> ! 67: ! 68: #define ASTERISK '*' /* ignore this in real name */ ! 69: #define COMMA ',' /* separator in pw_gecos field */ ! 70: #define COMMAND '-' /* command line flag char */ ! 71: #define CORY 'C' /* cory hall office */ ! 72: #define EVANS 'E' /* evans hall office */ ! 73: #define SAMENAME '&' /* repeat login name in real name */ ! 74: #define TALKABLE 0220 /* tty is writable if 220 mode */ ! 75: ! 76: struct utmp user; ! 77: #define NMAX sizeof(user.ut_name) ! 78: #define LMAX sizeof(user.ut_line) ! 79: #define HMAX sizeof(user.ut_host) ! 80: ! 81: struct person { /* one for each person fingered */ ! 82: char *name; /* name */ ! 83: char tty[LMAX+1]; /* null terminated tty line */ ! 84: char host[HMAX+1]; /* null terminated remote host name */ ! 85: long loginat; /* time of (last) login */ ! 86: long idletime; /* how long idle (if logged in) */ ! 87: char *realname; /* pointer to full name */ ! 88: char *office; /* pointer to office name */ ! 89: char *officephone; /* pointer to office phone no. */ ! 90: char *homephone; /* pointer to home phone no. */ ! 91: char *random; /* for any random stuff in pw_gecos */ ! 92: struct passwd *pwd; /* structure of /etc/passwd stuff */ ! 93: char loggedin; /* person is logged in */ ! 94: char writable; /* tty is writable */ ! 95: char original; /* this is not a duplicate entry */ ! 96: struct person *link; /* link to next person */ ! 97: }; ! 98: ! 99: char LASTLOG[] = "/usr/adm/lastlog"; /* last login info */ ! 100: char USERLOG[] = "/etc/utmp"; /* who is logged in */ ! 101: char PLAN[] = "/.plan"; /* what plan file is */ ! 102: char PROJ[] = "/.project"; /* what project file */ ! 103: ! 104: int unbrief = 1; /* -b option default */ ! 105: int header = 1; /* -f option default */ ! 106: int hack = 1; /* -h option default */ ! 107: int idle = 0; /* -i option default */ ! 108: int large = 0; /* -l option default */ ! 109: int match = 1; /* -m option default */ ! 110: int plan = 1; /* -p option default */ ! 111: int unquick = 1; /* -q option default */ ! 112: int small = 0; /* -s option default */ ! 113: int wide = 1; /* -w option default */ ! 114: ! 115: int unshort; ! 116: int lf; /* LASTLOG file descriptor */ ! 117: struct person *person1; /* list of people */ ! 118: long tloc; /* current time */ ! 119: ! 120: struct passwd *pwdcopy(); ! 121: char *strcpy(); ! 122: char *malloc(); ! 123: char *ctime(); ! 124: ! 125: main(argc, argv) ! 126: int argc; ! 127: register char **argv; ! 128: { ! 129: FILE *fp; ! 130: register char *s; ! 131: ! 132: /* parse command line for (optional) arguments */ ! 133: while (*++argv && **argv == COMMAND) ! 134: for (s = *argv + 1; *s; s++) ! 135: switch (*s) { ! 136: case 'b': ! 137: unbrief = 0; ! 138: break; ! 139: case 'f': ! 140: header = 0; ! 141: break; ! 142: case 'h': ! 143: hack = 0; ! 144: break; ! 145: case 'i': ! 146: idle = 1; ! 147: unquick = 0; ! 148: break; ! 149: case 'l': ! 150: large = 1; ! 151: break; ! 152: case 'm': ! 153: match = 0; ! 154: break; ! 155: case 'p': ! 156: plan = 0; ! 157: break; ! 158: case 'q': ! 159: unquick = 0; ! 160: break; ! 161: case 's': ! 162: small = 1; ! 163: break; ! 164: case 'w': ! 165: wide = 0; ! 166: break; ! 167: default: ! 168: fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n"); ! 169: exit(1); ! 170: } ! 171: if (unquick || idle) ! 172: time(&tloc); ! 173: /* ! 174: * *argv == 0 means no names given ! 175: */ ! 176: if (*argv == 0) ! 177: doall(); ! 178: else ! 179: donames(argv); ! 180: if (person1) ! 181: print(); ! 182: exit(0); ! 183: } ! 184: ! 185: doall() ! 186: { ! 187: register struct person *p; ! 188: register struct passwd *pw; ! 189: int uf; ! 190: char name[NMAX + 1]; ! 191: ! 192: unshort = large; ! 193: if ((uf = open(USERLOG, 0)) < 0) { ! 194: fprintf(stderr, "finger: error opening %s\n", USERLOG); ! 195: exit(2); ! 196: } ! 197: if (unquick) { ! 198: extern _pw_stayopen; ! 199: ! 200: setpwent(); ! 201: _pw_stayopen = 1; ! 202: fwopen(); ! 203: } ! 204: while (read(uf, (char *)&user, sizeof user) == sizeof user) { ! 205: if (user.ut_name[0] == 0) ! 206: continue; ! 207: if (person1 == 0) ! 208: p = person1 = (struct person *) malloc(sizeof *p); ! 209: else { ! 210: p->link = (struct person *) malloc(sizeof *p); ! 211: p = p->link; ! 212: } ! 213: bcopy(user.ut_name, name, NMAX); ! 214: name[NMAX] = 0; ! 215: bcopy(user.ut_line, p->tty, LMAX); ! 216: p->tty[LMAX] = 0; ! 217: bcopy(user.ut_host, p->host, HMAX); ! 218: p->host[HMAX] = 0; ! 219: p->loginat = user.ut_time; ! 220: p->pwd = 0; ! 221: p->loggedin = 1; ! 222: if (unquick && (pw = getpwnam(name))) { ! 223: p->pwd = pwdcopy(pw); ! 224: decode(p); ! 225: p->name = p->pwd->pw_name; ! 226: } else ! 227: p->name = strcpy(malloc(strlen(name) + 1), name); ! 228: } ! 229: if (unquick) { ! 230: fwclose(); ! 231: endpwent(); ! 232: } ! 233: close(uf); ! 234: if (person1 == 0) { ! 235: printf("No one logged on\n"); ! 236: return; ! 237: } ! 238: p->link = 0; ! 239: } ! 240: ! 241: donames(argv) ! 242: char **argv; ! 243: { ! 244: register struct person *p; ! 245: register struct passwd *pw; ! 246: int uf; ! 247: ! 248: /* ! 249: * get names from command line and check to see if they're ! 250: * logged in ! 251: */ ! 252: unshort = !small; ! 253: for (; *argv != 0; argv++) { ! 254: if (netfinger(*argv)) ! 255: continue; ! 256: if (person1 == 0) ! 257: p = person1 = (struct person *) malloc(sizeof *p); ! 258: else { ! 259: p->link = (struct person *) malloc(sizeof *p); ! 260: p = p->link; ! 261: } ! 262: p->name = *argv; ! 263: p->loggedin = 0; ! 264: p->original = 1; ! 265: p->pwd = 0; ! 266: } ! 267: if (person1 == 0) ! 268: return; ! 269: p->link = 0; ! 270: /* ! 271: * if we are doing it, read /etc/passwd for the useful info ! 272: */ ! 273: if (unquick) { ! 274: setpwent(); ! 275: if (!match) { ! 276: extern _pw_stayopen; ! 277: ! 278: _pw_stayopen = 1; ! 279: for (p = person1; p != 0; p = p->link) ! 280: if (pw = getpwnam(p->name)) ! 281: p->pwd = pwdcopy(pw); ! 282: } else while ((pw = getpwent()) != 0) { ! 283: for (p = person1; p != 0; p = p->link) { ! 284: if (!p->original) ! 285: continue; ! 286: if (strcmp(p->name, pw->pw_name) != 0 && ! 287: !matchcmp(pw->pw_gecos, pw->pw_name, p->name)) ! 288: continue; ! 289: if (p->pwd == 0) ! 290: p->pwd = pwdcopy(pw); ! 291: else { ! 292: struct person *new; ! 293: /* ! 294: * handle multiple login names, insert ! 295: * new "duplicate" entry behind ! 296: */ ! 297: new = (struct person *) ! 298: malloc(sizeof *new); ! 299: new->pwd = pwdcopy(pw); ! 300: new->name = p->name; ! 301: new->original = 1; ! 302: new->loggedin = 0; ! 303: new->link = p->link; ! 304: p->original = 0; ! 305: p->link = new; ! 306: p = new; ! 307: } ! 308: } ! 309: } ! 310: endpwent(); ! 311: } ! 312: /* Now get login information */ ! 313: if ((uf = open(USERLOG, 0)) < 0) { ! 314: fprintf(stderr, "finger: error opening %s\n", USERLOG); ! 315: exit(2); ! 316: } ! 317: while (read(uf, (char *)&user, sizeof user) == sizeof user) { ! 318: if (*user.ut_name == 0) ! 319: continue; ! 320: for (p = person1; p != 0; p = p->link) { ! 321: if (p->loggedin == 2) ! 322: continue; ! 323: if (strncmp(p->pwd ? p->pwd->pw_name : p->name, ! 324: user.ut_name, NMAX) != 0) ! 325: continue; ! 326: if (p->loggedin == 0) { ! 327: bcopy(user.ut_line, p->tty, LMAX); ! 328: p->tty[LMAX] = 0; ! 329: bcopy(user.ut_host, p->host, HMAX); ! 330: p->host[HMAX] = 0; ! 331: p->loginat = user.ut_time; ! 332: p->loggedin = 1; ! 333: } else { /* p->loggedin == 1 */ ! 334: struct person *new; ! 335: new = (struct person *) malloc(sizeof *new); ! 336: new->name = p->name; ! 337: bcopy(user.ut_line, new->tty, LMAX); ! 338: new->tty[LMAX] = 0; ! 339: bcopy(user.ut_host, new->host, HMAX); ! 340: new->host[HMAX] = 0; ! 341: new->loginat = user.ut_time; ! 342: new->pwd = p->pwd; ! 343: new->loggedin = 1; ! 344: new->original = 0; ! 345: new->link = p->link; ! 346: p->loggedin = 2; ! 347: p->link = new; ! 348: p = new; ! 349: } ! 350: } ! 351: } ! 352: close(uf); ! 353: if (unquick) { ! 354: fwopen(); ! 355: for (p = person1; p != 0; p = p->link) ! 356: decode(p); ! 357: fwclose(); ! 358: } ! 359: } ! 360: ! 361: print() ! 362: { ! 363: register FILE *fp; ! 364: register struct person *p; ! 365: register char *s; ! 366: register c; ! 367: ! 368: /* ! 369: * print out what we got ! 370: */ ! 371: if (header) { ! 372: if (unquick) { ! 373: if (!unshort) ! 374: if (wide) ! 375: printf("Login Name TTY Idle When Office\n"); ! 376: else ! 377: printf("Login TTY Idle When Office\n"); ! 378: } else { ! 379: printf("Login TTY When"); ! 380: if (idle) ! 381: printf(" Idle"); ! 382: putchar('\n'); ! 383: } ! 384: } ! 385: for (p = person1; p != 0; p = p->link) { ! 386: if (!unquick) { ! 387: quickprint(p); ! 388: continue; ! 389: } ! 390: if (!unshort) { ! 391: shortprint(p); ! 392: continue; ! 393: } ! 394: personprint(p); ! 395: if (p->pwd != 0) { ! 396: if (hack) { ! 397: s = malloc(strlen(p->pwd->pw_dir) + ! 398: sizeof PROJ); ! 399: strcpy(s, p->pwd->pw_dir); ! 400: strcat(s, PROJ); ! 401: if ((fp = fopen(s, "r")) != 0) { ! 402: printf("Project: "); ! 403: while ((c = getc(fp)) != EOF) { ! 404: if (c == '\n') ! 405: break; ! 406: if (isprint(c) || isspace(c)) ! 407: putchar(c); ! 408: else ! 409: putchar(c ^ 100); ! 410: } ! 411: fclose(fp); ! 412: putchar('\n'); ! 413: } ! 414: free(s); ! 415: } ! 416: if (plan) { ! 417: s = malloc(strlen(p->pwd->pw_dir) + ! 418: sizeof PLAN); ! 419: strcpy(s, p->pwd->pw_dir); ! 420: strcat(s, PLAN); ! 421: if ((fp = fopen(s, "r")) == 0) ! 422: printf("No Plan.\n"); ! 423: else { ! 424: printf("Plan:\n"); ! 425: while ((c = getc(fp)) != EOF) ! 426: if (isprint(c) || isspace(c)) ! 427: putchar(c); ! 428: else ! 429: putchar(c ^ 100); ! 430: fclose(fp); ! 431: } ! 432: free(s); ! 433: } ! 434: } ! 435: if (p->link != 0) ! 436: putchar('\n'); ! 437: } ! 438: } ! 439: ! 440: /* ! 441: * Duplicate a pwd entry. ! 442: * Note: Only the useful things (what the program currently uses) are copied. ! 443: */ ! 444: struct passwd * ! 445: pwdcopy(pfrom) ! 446: register struct passwd *pfrom; ! 447: { ! 448: register struct passwd *pto; ! 449: ! 450: pto = (struct passwd *) malloc(sizeof *pto); ! 451: #define savestr(s) strcpy(malloc(strlen(s) + 1), s) ! 452: pto->pw_name = savestr(pfrom->pw_name); ! 453: pto->pw_uid = pfrom->pw_uid; ! 454: pto->pw_gecos = savestr(pfrom->pw_gecos); ! 455: pto->pw_dir = savestr(pfrom->pw_dir); ! 456: pto->pw_shell = savestr(pfrom->pw_shell); ! 457: #undef savestr ! 458: return pto; ! 459: } ! 460: ! 461: /* ! 462: * print out information on quick format giving just name, tty, login time ! 463: * and idle time if idle is set. ! 464: */ ! 465: quickprint(pers) ! 466: register struct person *pers; ! 467: { ! 468: printf("%-*.*s ", NMAX, NMAX, pers->name); ! 469: if (pers->loggedin) { ! 470: if (idle) { ! 471: findidle(pers); ! 472: printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*', ! 473: LMAX, pers->tty, ctime(&pers->loginat)); ! 474: ltimeprint(" ", &pers->idletime, ""); ! 475: } else ! 476: printf(" %-*s %-16.16s", LMAX, ! 477: pers->tty, ctime(&pers->loginat)); ! 478: putchar('\n'); ! 479: } else ! 480: printf(" Not Logged In\n"); ! 481: } ! 482: ! 483: /* ! 484: * print out information in short format, giving login name, full name, ! 485: * tty, idle time, login time, office location and phone. ! 486: */ ! 487: shortprint(pers) ! 488: register struct person *pers; ! 489: { ! 490: char *p; ! 491: char dialup; ! 492: ! 493: if (pers->pwd == 0) { ! 494: printf("%-15s ???\n", pers->name); ! 495: return; ! 496: } ! 497: printf("%-*s", NMAX, pers->pwd->pw_name); ! 498: dialup = 0; ! 499: if (wide) { ! 500: if (pers->realname) ! 501: printf(" %-20.20s", pers->realname); ! 502: else ! 503: printf(" ??? "); ! 504: } ! 505: putchar(' '); ! 506: if (pers->loggedin && !pers->writable) ! 507: putchar('*'); ! 508: else ! 509: putchar(' '); ! 510: if (*pers->tty) { ! 511: if (pers->tty[0] == 't' && pers->tty[1] == 't' && ! 512: pers->tty[2] == 'y') { ! 513: if (pers->tty[3] == 'd' && pers->loggedin) ! 514: dialup = 1; ! 515: printf("%-2.2s ", pers->tty + 3); ! 516: } else ! 517: printf("%-2.2s ", pers->tty); ! 518: } else ! 519: printf(" "); ! 520: p = ctime(&pers->loginat); ! 521: if (pers->loggedin) { ! 522: stimeprint(&pers->idletime); ! 523: printf(" %3.3s %-5.5s ", p, p + 11); ! 524: } else if (pers->loginat == 0) ! 525: printf(" < . . . . >"); ! 526: else if (tloc - pers->loginat >= 180 * 24 * 60 * 60) ! 527: printf(" <%-6.6s, %-4.4s>", p + 4, p + 20); ! 528: else ! 529: printf(" <%-12.12s>", p + 4); ! 530: if (dialup && pers->homephone) ! 531: printf(" %20s", pers->homephone); ! 532: else { ! 533: if (pers->office) ! 534: printf(" %-11.11s", pers->office); ! 535: else if (pers->officephone || pers->homephone) ! 536: printf(" "); ! 537: if (pers->officephone) ! 538: printf(" %s", pers->officephone); ! 539: else if (pers->homephone) ! 540: printf(" %s", pers->homephone); ! 541: } ! 542: putchar('\n'); ! 543: } ! 544: ! 545: /* ! 546: * print out a person in long format giving all possible information. ! 547: * directory and shell are inhibited if unbrief is clear. ! 548: */ ! 549: personprint(pers) ! 550: register struct person *pers; ! 551: { ! 552: if (pers->pwd == 0) { ! 553: printf("Login name: %-10s\t\t\tIn real life: ???\n", ! 554: pers->name); ! 555: return; ! 556: } ! 557: printf("Login name: %-10s", pers->pwd->pw_name); ! 558: if (pers->loggedin && !pers->writable) ! 559: printf(" (messages off) "); ! 560: else ! 561: printf(" "); ! 562: if (pers->realname) ! 563: printf("In real life: %s", pers->realname); ! 564: if (pers->office) { ! 565: printf("\nOffice: %-.11s", pers->office); ! 566: if (pers->officephone) { ! 567: printf(", %s", pers->officephone); ! 568: if (pers->homephone) ! 569: printf("\t\tHome phone: %s", pers->homephone); ! 570: else if (pers->random) ! 571: printf("\t\t%s", pers->random); ! 572: } else ! 573: if (pers->homephone) ! 574: printf("\t\t\tHome phone: %s", pers->homephone); ! 575: else if (pers->random) ! 576: printf("\t\t\t%s", pers->random); ! 577: } else if (pers->officephone) { ! 578: printf("\nPhone: %s", pers->officephone); ! 579: if (pers->homephone) ! 580: printf(", %s", pers->homephone); ! 581: if (pers->random) ! 582: printf(", %s", pers->random); ! 583: } else if (pers->homephone) { ! 584: printf("\nPhone: %s", pers->homephone); ! 585: if (pers->random) ! 586: printf(", %s", pers->random); ! 587: } else if (pers->random) ! 588: printf("\n%s", pers->random); ! 589: if (unbrief) { ! 590: printf("\nDirectory: %-25s", pers->pwd->pw_dir); ! 591: if (*pers->pwd->pw_shell) ! 592: printf("\tShell: %-s", pers->pwd->pw_shell); ! 593: } ! 594: if (pers->loggedin) { ! 595: register char *ep = ctime(&pers->loginat); ! 596: if (*pers->host) { ! 597: printf("\nOn since %15.15s on %s from %s", ! 598: &ep[4], pers->tty, pers->host); ! 599: ltimeprint("\n", &pers->idletime, " Idle Time"); ! 600: } else { ! 601: printf("\nOn since %15.15s on %-*s", ! 602: &ep[4], LMAX, pers->tty); ! 603: ltimeprint("\t", &pers->idletime, " Idle Time"); ! 604: } ! 605: } else if (pers->loginat == 0) ! 606: printf("\nNever logged in."); ! 607: else if (tloc - pers->loginat > 180 * 24 * 60 * 60) { ! 608: register char *ep = ctime(&pers->loginat); ! 609: printf("\nLast login %10.10s, %4.4s on %s", ! 610: ep, ep+20, pers->tty); ! 611: if (*pers->host) ! 612: printf(" from %s", pers->host); ! 613: } else { ! 614: register char *ep = ctime(&pers->loginat); ! 615: printf("\nLast login %16.16s on %s", ep, pers->tty); ! 616: if (*pers->host) ! 617: printf(" from %s", pers->host); ! 618: } ! 619: putchar('\n'); ! 620: } ! 621: ! 622: /* ! 623: * very hacky section of code to format phone numbers. filled with ! 624: * magic constants like 4, 7 and 10. ! 625: */ ! 626: char * ! 627: phone(s, len, alldigits) ! 628: register char *s; ! 629: int len; ! 630: char alldigits; ! 631: { ! 632: char fonebuf[15]; ! 633: register char *p = fonebuf; ! 634: register i; ! 635: ! 636: if (!alldigits) ! 637: return (strcpy(malloc(len + 1), s)); ! 638: switch (len) { ! 639: case 4: ! 640: *p++ = ' '; ! 641: *p++ = 'x'; ! 642: *p++ = '2'; ! 643: *p++ = '-'; ! 644: for (i = 0; i < 4; i++) ! 645: *p++ = *s++; ! 646: break; ! 647: case 5: ! 648: *p++ = ' '; ! 649: *p++ = 'x'; ! 650: *p++ = *s++; ! 651: *p++ = '-'; ! 652: for (i = 0; i < 4; i++) ! 653: *p++ = *s++; ! 654: break; ! 655: case 7: ! 656: for (i = 0; i < 3; i++) ! 657: *p++ = *s++; ! 658: *p++ = '-'; ! 659: for (i = 0; i < 4; i++) ! 660: *p++ = *s++; ! 661: break; ! 662: case 10: ! 663: for (i = 0; i < 3; i++) ! 664: *p++ = *s++; ! 665: *p++ = '-'; ! 666: for (i = 0; i < 3; i++) ! 667: *p++ = *s++; ! 668: *p++ = '-'; ! 669: for (i = 0; i < 4; i++) ! 670: *p++ = *s++; ! 671: break; ! 672: case 0: ! 673: return 0; ! 674: default: ! 675: return (strcpy(malloc(len + 1), s)); ! 676: } ! 677: *p++ = 0; ! 678: return (strcpy(malloc(p - fonebuf), fonebuf)); ! 679: } ! 680: ! 681: /* ! 682: * decode the information in the gecos field of /etc/passwd ! 683: */ ! 684: decode(pers) ! 685: register struct person *pers; ! 686: { ! 687: char buffer[256]; ! 688: register char *bp, *gp, *lp; ! 689: int alldigits; ! 690: int hasspace; ! 691: int len; ! 692: ! 693: pers->realname = 0; ! 694: pers->office = 0; ! 695: pers->officephone = 0; ! 696: pers->homephone = 0; ! 697: pers->random = 0; ! 698: if (pers->pwd == 0) ! 699: return; ! 700: gp = pers->pwd->pw_gecos; ! 701: bp = buffer; ! 702: if (*gp == ASTERISK) ! 703: gp++; ! 704: while (*gp && *gp != COMMA) /* name */ ! 705: if (*gp == SAMENAME) { ! 706: lp = pers->pwd->pw_name; ! 707: if (islower(*lp)) ! 708: *bp++ = toupper(*lp++); ! 709: while (*bp++ = *lp++) ! 710: ; ! 711: bp--; ! 712: gp++; ! 713: } else ! 714: *bp++ = *gp++; ! 715: *bp++ = 0; ! 716: if ((len = bp - buffer) > 1) ! 717: pers->realname = strcpy(malloc(len), buffer); ! 718: if (*gp == COMMA) { /* office */ ! 719: gp++; ! 720: hasspace = 0; ! 721: bp = buffer; ! 722: while (*gp && *gp != COMMA) { ! 723: *bp = *gp++; ! 724: if (*bp == ' ') ! 725: hasspace = 1; ! 726: /* leave 5 for Cory and Evans expansion */ ! 727: if (bp < buffer + sizeof buffer - 6) ! 728: bp++; ! 729: } ! 730: *bp = 0; ! 731: len = bp - buffer; ! 732: bp--; /* point to last character */ ! 733: if (hasspace || len == 0) ! 734: len++; ! 735: else if (*bp == CORY) { ! 736: strcpy(bp, " Cory"); ! 737: len += 5; ! 738: } else if (*bp == EVANS) { ! 739: strcpy(bp, " Evans"); ! 740: len += 6; ! 741: } else ! 742: len++; ! 743: if (len > 1) ! 744: pers->office = strcpy(malloc(len), buffer); ! 745: } ! 746: if (*gp == COMMA) { /* office phone */ ! 747: gp++; ! 748: bp = buffer; ! 749: alldigits = 1; ! 750: while (*gp && *gp != COMMA) { ! 751: *bp = *gp++; ! 752: if (!isdigit(*bp)) ! 753: alldigits = 0; ! 754: if (bp < buffer + sizeof buffer - 1) ! 755: bp++; ! 756: } ! 757: *bp = 0; ! 758: pers->officephone = phone(buffer, bp - buffer, alldigits); ! 759: } ! 760: if (*gp == COMMA) { /* home phone */ ! 761: gp++; ! 762: bp = buffer; ! 763: alldigits = 1; ! 764: while (*gp && *gp != COMMA) { ! 765: *bp = *gp++; ! 766: if (!isdigit(*bp)) ! 767: alldigits = 0; ! 768: if (bp < buffer + sizeof buffer - 1) ! 769: bp++; ! 770: } ! 771: *bp = 0; ! 772: pers->homephone = phone(buffer, bp - buffer, alldigits); ! 773: } ! 774: if (pers->loggedin) ! 775: findidle(pers); ! 776: else ! 777: findwhen(pers); ! 778: } ! 779: ! 780: /* ! 781: * find the last log in of a user by checking the LASTLOG file. ! 782: * the entry is indexed by the uid, so this can only be done if ! 783: * the uid is known (which it isn't in quick mode) ! 784: */ ! 785: ! 786: fwopen() ! 787: { ! 788: if ((lf = open(LASTLOG, 0)) < 0) ! 789: fprintf(stderr, "finger: %s open error\n", LASTLOG); ! 790: } ! 791: ! 792: findwhen(pers) ! 793: register struct person *pers; ! 794: { ! 795: struct lastlog ll; ! 796: int i; ! 797: ! 798: if (lf >= 0) { ! 799: lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0); ! 800: if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) { ! 801: bcopy(ll.ll_line, pers->tty, LMAX); ! 802: pers->tty[LMAX] = 0; ! 803: bcopy(ll.ll_host, pers->host, HMAX); ! 804: pers->host[HMAX] = 0; ! 805: pers->loginat = ll.ll_time; ! 806: } else { ! 807: if (i != 0) ! 808: fprintf(stderr, "finger: %s read error\n", ! 809: LASTLOG); ! 810: pers->tty[0] = 0; ! 811: pers->host[0] = 0; ! 812: pers->loginat = 0L; ! 813: } ! 814: } else { ! 815: pers->tty[0] = 0; ! 816: pers->host[0] = 0; ! 817: pers->loginat = 0L; ! 818: } ! 819: } ! 820: ! 821: fwclose() ! 822: { ! 823: if (lf >= 0) ! 824: close(lf); ! 825: } ! 826: ! 827: /* ! 828: * find the idle time of a user by doing a stat on /dev/tty??, ! 829: * where tty?? has been gotten from USERLOG, supposedly. ! 830: */ ! 831: findidle(pers) ! 832: register struct person *pers; ! 833: { ! 834: struct stat ttystatus; ! 835: static char buffer[20] = "/dev/"; ! 836: long t; ! 837: #define TTYLEN 5 ! 838: ! 839: strcpy(buffer + TTYLEN, pers->tty); ! 840: buffer[TTYLEN+LMAX] = 0; ! 841: if (stat(buffer, &ttystatus) < 0) { ! 842: fprintf(stderr, "finger: Can't stat %s\n", buffer); ! 843: exit(4); ! 844: } ! 845: time(&t); ! 846: if (t < ttystatus.st_atime) ! 847: pers->idletime = 0L; ! 848: else ! 849: pers->idletime = t - ttystatus.st_atime; ! 850: pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE; ! 851: } ! 852: ! 853: /* ! 854: * print idle time in short format; this program always prints 4 characters; ! 855: * if the idle time is zero, it prints 4 blanks. ! 856: */ ! 857: stimeprint(dt) ! 858: long *dt; ! 859: { ! 860: register struct tm *delta; ! 861: ! 862: delta = gmtime(dt); ! 863: if (delta->tm_yday == 0) ! 864: if (delta->tm_hour == 0) ! 865: if (delta->tm_min == 0) ! 866: printf(" "); ! 867: else ! 868: printf(" %2d", delta->tm_min); ! 869: else ! 870: if (delta->tm_hour >= 10) ! 871: printf("%3d:", delta->tm_hour); ! 872: else ! 873: printf("%1d:%02d", ! 874: delta->tm_hour, delta->tm_min); ! 875: else ! 876: printf("%3dd", delta->tm_yday); ! 877: } ! 878: ! 879: /* ! 880: * print idle time in long format with care being taken not to pluralize ! 881: * 1 minutes or 1 hours or 1 days. ! 882: * print "prefix" first. ! 883: */ ! 884: ltimeprint(before, dt, after) ! 885: long *dt; ! 886: char *before, *after; ! 887: { ! 888: register struct tm *delta; ! 889: ! 890: delta = gmtime(dt); ! 891: if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 && ! 892: delta->tm_sec <= 10) ! 893: return (0); ! 894: printf("%s", before); ! 895: if (delta->tm_yday >= 10) ! 896: printf("%d days", delta->tm_yday); ! 897: else if (delta->tm_yday > 0) ! 898: printf("%d day%s %d hour%s", ! 899: delta->tm_yday, delta->tm_yday == 1 ? "" : "s", ! 900: delta->tm_hour, delta->tm_hour == 1 ? "" : "s"); ! 901: else ! 902: if (delta->tm_hour >= 10) ! 903: printf("%d hours", delta->tm_hour); ! 904: else if (delta->tm_hour > 0) ! 905: printf("%d hour%s %d minute%s", ! 906: delta->tm_hour, delta->tm_hour == 1 ? "" : "s", ! 907: delta->tm_min, delta->tm_min == 1 ? "" : "s"); ! 908: else ! 909: if (delta->tm_min >= 10) ! 910: printf("%2d minutes", delta->tm_min); ! 911: else if (delta->tm_min == 0) ! 912: printf("%2d seconds", delta->tm_sec); ! 913: else ! 914: printf("%d minute%s %d second%s", ! 915: delta->tm_min, ! 916: delta->tm_min == 1 ? "" : "s", ! 917: delta->tm_sec, ! 918: delta->tm_sec == 1 ? "" : "s"); ! 919: printf("%s", after); ! 920: } ! 921: ! 922: matchcmp(gname, login, given) ! 923: register char *gname; ! 924: char *login; ! 925: char *given; ! 926: { ! 927: char buffer[100]; ! 928: register char *bp, *lp; ! 929: register c; ! 930: ! 931: if (*gname == ASTERISK) ! 932: gname++; ! 933: lp = 0; ! 934: bp = buffer; ! 935: for (;;) ! 936: switch (c = *gname++) { ! 937: case SAMENAME: ! 938: for (lp = login; bp < buffer + sizeof buffer ! 939: && (*bp++ = *lp++);) ! 940: ; ! 941: bp--; ! 942: break; ! 943: case ' ': ! 944: case COMMA: ! 945: case '\0': ! 946: *bp = 0; ! 947: if (namecmp(buffer, given)) ! 948: return (1); ! 949: if (c == COMMA || c == 0) ! 950: return (0); ! 951: bp = buffer; ! 952: break; ! 953: default: ! 954: if (bp < buffer + sizeof buffer) ! 955: *bp++ = c; ! 956: } ! 957: /*NOTREACHED*/ ! 958: } ! 959: ! 960: namecmp(name1, name2) ! 961: register char *name1, *name2; ! 962: { ! 963: register c1, c2; ! 964: ! 965: for (;;) { ! 966: c1 = *name1++; ! 967: if (islower(c1)) ! 968: c1 = toupper(c1); ! 969: c2 = *name2++; ! 970: if (islower(c2)) ! 971: c2 = toupper(c2); ! 972: if (c1 != c2) ! 973: break; ! 974: if (c1 == 0) ! 975: return (1); ! 976: } ! 977: if (!c1) { ! 978: for (name2--; isdigit(*name2); name2++) ! 979: ; ! 980: if (*name2 == 0) ! 981: return (1); ! 982: } else if (!c2) { ! 983: for (name1--; isdigit(*name1); name1++) ! 984: ; ! 985: if (*name2 == 0) ! 986: return (1); ! 987: } ! 988: return (0); ! 989: } ! 990: ! 991: netfinger(name) ! 992: char *name; ! 993: { ! 994: char *host; ! 995: char fname[100]; ! 996: struct hostent *hp; ! 997: struct servent *sp; ! 998: struct sockaddr_in sin; ! 999: int s; ! 1000: char *rindex(); ! 1001: register FILE *f; ! 1002: register int c; ! 1003: register int lastc; ! 1004: ! 1005: if (name == NULL) ! 1006: return (0); ! 1007: host = rindex(name, '@'); ! 1008: if (host == NULL) ! 1009: return (0); ! 1010: *host++ = 0; ! 1011: hp = gethostbyname(host); ! 1012: if (hp == NULL) { ! 1013: static struct hostent def; ! 1014: static struct in_addr defaddr; ! 1015: static char *alist[1]; ! 1016: static char namebuf[128]; ! 1017: int inet_addr(); ! 1018: ! 1019: defaddr.s_addr = inet_addr(host); ! 1020: if (defaddr.s_addr == -1) { ! 1021: printf("unknown host: %s\n", host); ! 1022: return (1); ! 1023: } ! 1024: strcpy(namebuf, host); ! 1025: def.h_name = namebuf; ! 1026: def.h_addr_list = alist, def.h_addr = (char *)&defaddr; ! 1027: def.h_length = sizeof (struct in_addr); ! 1028: def.h_addrtype = AF_INET; ! 1029: def.h_aliases = 0; ! 1030: hp = &def; ! 1031: } ! 1032: printf("[%s]", hp->h_name); ! 1033: sp = getservbyname("finger", "tcp"); ! 1034: if (sp == 0) { ! 1035: printf("tcp/finger: unknown service\n"); ! 1036: return (1); ! 1037: } ! 1038: sin.sin_family = hp->h_addrtype; ! 1039: bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); ! 1040: sin.sin_port = sp->s_port; ! 1041: s = socket(hp->h_addrtype, SOCK_STREAM, 0); ! 1042: if (s < 0) { ! 1043: fflush(stdout); ! 1044: perror("socket"); ! 1045: return (1); ! 1046: } ! 1047: if (connect(s, (char *)&sin, sizeof (sin)) < 0) { ! 1048: fflush(stdout); ! 1049: perror("connect"); ! 1050: close(s); ! 1051: return (1); ! 1052: } ! 1053: printf("\n"); ! 1054: if (large) write(s, "/W ", 3); ! 1055: write(s, name, strlen(name)); ! 1056: write(s, "\r\n", 2); ! 1057: f = fdopen(s, "r"); ! 1058: while ((c = getc(f)) != EOF) { ! 1059: switch(c) { ! 1060: case 0210: ! 1061: case 0211: ! 1062: case 0212: ! 1063: case 0214: ! 1064: c -= 0200; ! 1065: break; ! 1066: case 0215: ! 1067: c = '\n'; ! 1068: break; ! 1069: } ! 1070: lastc = c; ! 1071: if (isprint(c) || isspace(c)) ! 1072: putchar(c); ! 1073: else ! 1074: putchar(c ^ 100); ! 1075: } ! 1076: if (lastc != '\n') ! 1077: putchar('\n'); ! 1078: (void)fclose(f); ! 1079: return (1); ! 1080: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.