Annotation of 43BSD/ucb/finger.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.