source: trunk/athena/bin/finger/finger.c @ 22842

Revision 22842, 33.7 KB checked in by tabbott, 16 years ago (diff)
In finger: * Merged quilt patches into mainline Athena tree
RevLine 
[737]1/*
[745]2 * Copyright 1987 by the Massachusetts Institute of Technology.
3 * For copying and distribution information, see the file
4 * "mit-copyright.h".
5 *
[22069]6 * $Id: finger.c,v 1.40 2005-06-27 03:33:42 zacheiss Exp $
[737]7 */
8
[738]9#ifndef lint
[22069]10static char *rcsid_finger_c = "$Id: finger.c,v 1.40 2005-06-27 03:33:42 zacheiss Exp $";
[7601]11#endif /*lint*/
[737]12
13/*
14 * Copyright (c) 1980 Regents of the University of California.
15 * All rights reserved.  The Berkeley software License Agreement
16 * specifies the terms and conditions for redistribution.
17 */
18
19#ifndef lint
20char copyright[] =
21"@(#) Copyright (c) 1980 Regents of the University of California.\n\
22 All rights reserved.\n";
[770]23
[7601]24#endif /*not lint*/
[737]25
26#ifndef lint
27static char sccsid[] = "@(#)finger.c    5.8 (Berkeley) 3/13/86";
[770]28
[7601]29#endif /*not lint */
[737]30
31/*
[740]32 * This is a finger program.  It prints out useful information about
33 * users by digging it up from various system files.  It is not very
34 * portable because the most useful parts of the information (the full
35 * user name, office, and phone numbers) are all stored in the
36 * VAX-unused gecos field of /etc/passwd, which, unfortunately, other
37 * UNIXes use for other things.
[737]38 *
[740]39 * There are three output formats, all of which give login name,
40 * teletype line number, and login time.  The short output format is
41 * reminiscent of finger on ITS, and gives one line of information per
42 * user containing in addition to the minimum basic requirements
43 * (MBR), the full name of the user, his idle time and office location
44 * and phone number.  The quick style output is UNIX who-like, giving
45 * only name, teletype and login time.  Finally, the long style output
46 * give the same information as the short (in more legible format),
47 * the home directory and shell of the user, and, if it exists, copies
48 * of the files .plan and .project in the user's home directory.
49 * Finger may be called with or without a list of people to finger --
50 * if no list is given, all the people currently logged in are
51 * fingered.
[737]52 *
53 * The program is validly called by one of the following:
54 *
55 *      finger                  {short form list of users}
56 *      finger -l               {long form list of users}
57 *      finger -b               {briefer long form list of users}
58 *      finger -q               {quick list of users}
59 *      finger -i               {quick list of users with idle times}
60 *      finger namelist         {long format list of specified users}
61 *      finger -s namelist      {short format list of specified users}
62 *      finger -w namelist      {narrow short format list of specified users}
63 *
64 * where 'namelist' is a list of users login names.
65 * The other options can all be given after one '-', or each can have its
66 * own '-'.  The -f option disables the printing of headers for short and
67 * quick outputs.  The -b option briefens long format outputs.  The -p
68 * option turns off plans for long format outputs.
69 */
70
[13844]71#define _GNU_SOURCE /* Make UTMPX_FILE etc. visible on glibc systems */
72
[5231]73#include <sys/types.h>
[737]74#include <sys/stat.h>
[10970]75#include <unistd.h>
76#include <fcntl.h>
[8855]77#include <string.h>
[737]78#include <utmp.h>
[10970]79#include <signal.h>
[737]80#include <pwd.h>
81#include <stdio.h>
[10851]82#include <stdlib.h>
[737]83#include <ctype.h>
[5231]84#include <time.h>
[737]85#include <sys/time.h>
86#include <sys/socket.h>
87#include <netinet/in.h>
88#include <netdb.h>
[10970]89#ifdef HAVE_UTMPX_H
90#include <utmpx.h>
91#endif
92#ifdef HAVE_LASTLOG_H
93#include <lastlog.h>
94#endif
95#ifdef HAVE_PATHS_H
96#include <paths.h>
97#endif
[740]98#include <hesiod.h>
[1677]99#include <zephyr/zephyr.h>
[745]100#include "mit-copyright.h"
[770]101
[737]102#define MAXTTYS 256
103#define MAXSEARCH 750
104
[5963]105#define NOIDLE -1               /* Magic number for unavailable idle time */
[745]106#define CAPITALIZE      0137&   /* capitalize character macro */
107#define ASTERISK        '*'     /* ignore this in real name */
108#define COMMA           ','     /* separator in pw_gecos field */
109#define COMMAND         '-'     /* command line flag char */
110#define TECHSQ          'T'     /* tech square office */
111#define MIT             'M'     /* MIT office */
112#define SAMENAME        '&'     /* repeat login name in real name */
113#define TALKABLE        0220    /* tty is writable if 220 mode */
[10996]114#define MAILDIR         "/var/mail/"    /* default mail directory */
[737]115
[10970]116#ifdef HAVE_UTMPX_H
[6604]117struct utmpx user;
[10851]118#define UTTIME(ut) (ut).ut_tv.tv_sec
[6604]119#else
[737]120struct utmp user;
[10851]121#define UTTIME(ut) (ut).ut_time
[6604]122#endif
[745]123
[737]124#define NMAX sizeof(user.ut_name)
125#define LMAX sizeof(user.ut_line)
126#define HMAX sizeof(user.ut_host)
[4538]127#ifdef MIN
128#undef MIN
129#endif
[901]130#define MIN(a,b) ((a) < (b) ? (a) : (b))
[737]131
132struct person {                 /* one for each person fingered */
[770]133        char *name;             /* name */
[8464]134        char tty[BUFSIZ];       /* null terminated tty line */
[770]135        char host[BUFSIZ];      /* null terminated remote host name */
[15094]136        char logintime[BUFSIZ]; /* null terminated login time */
[770]137        int loginout;           /* 0 means login time, 1 logout */
[10851]138        time_t loginat;         /* time of (last) login/out */
139        time_t idletime;        /* how long idle (if logged in) */
[770]140        char *realname;         /* pointer to full name */
141        char *nickname;         /* pointer to nickname */
142        char *office;           /* pointer to office name */
143        char *officephone;      /* pointer to office phone no. */
144        char *homephone;        /* pointer to home phone no. */
145        char *random;           /* for any random stuff in pw_gecos */
146        struct passwd *pwd;     /* structure of /etc/passwd stuff */
147        int loggedin;           /* person is logged in */
148        char writable;          /* tty is writable */
149        int original;           /* this is not a duplicate entry */
150        struct person *link;    /* link to next person */
[1677]151        int zlocation;          /* found via Zephyr */
[737]152};
153
[10970]154#if defined(HAVE_UTMPX_H)
[10851]155char USERLOG[] = UTMPX_FILE;            /* who is logged in */
156char ACCTLOG[] = WTMPX_FILE;            /* Accounting file */
157#elif defined(UTMP_FILE)
158char USERLOG[] = UTMP_FILE;
159char ACCTLOG[] = WTMP_FILE;
160#elif defined(_PATH_UTMP)
161char USERLOG[] = _PATH_UTMP;
162char ACCTLOG[] = _PATH_WTMP;
[6604]163#else
[10851]164char USERLOG[] = "/var/adm/utmp";
165char ACCTLOG[] = "/var/adm/wtmp";
[6604]166#endif
[7601]167
[10851]168#ifdef _PATH_LASTLOG
169char LASTLOG[] = _PATH_LASTLOG;         /* last login info */
170#else
[10996]171char LASTLOG[] = "/var/adm/lastlog";
[10851]172#endif
173
[745]174char PLAN[] = "/.plan";         /* what plan file is */
175char PROJ[] = "/.project";      /* what project file */
176char MM[] = "%MENTION-MAIL%\n"; /* if present, check for mail */
[737]177int MMLEN = 15;
178
[745]179int unbrief = 1;                /* -b option default */
180int header = 1;                 /* -f option default */
181int hack = 1;                   /* -h option default */
[12355]182int idlep = 0;                  /* -i option default */
[745]183int large = 0;                  /* -l option default */
[22842]184int match = 0;                  /* -m option default */
[745]185int plan = 1;                   /* -p option default */
186int unquick = 1;                /* -q option default */
187int small = 0;                  /* -s option default */
188int wide = 1;                   /* -w option default */
[737]189
[767]190int numloc = 1;                 /* number of locations from zgetlocations */
[770]191ZLocations_t location;          /* holds Zephyr locations */
[10970]192int znloc = 0;                  /* number of locations returned via a Zephyr
[745]193                                 * lookup */
[737]194int unshort;
[1677]195int lf = -1;                    /* LASTLOG file descriptor */
196int lw = -1;                    /* ACCTLOG file descriptor */
[745]197
[740]198/* !#$%!@#$! Bezerkeley non-initializations !!! */
[745]199struct person *person1 = (struct person *) NULL;        /* list of people */
200struct person *person2 = (struct person *) NULL;        /* 2nd list of people */
[7601]201time_t tloc;
[737]202
[745]203char ttnames[MAXTTYS][LMAX];    /* TTY names */
[10851]204time_t logouts[MAXTTYS];        /* Logout times */
[737]205
206struct passwd *pwdcopy();
[7404]207
[738]208/*ARGSUSED*/
[737]209main(argc, argv)
[770]210        int argc;
211        register char **argv;
[737]212{
[770]213        register char *s;
[737]214
[770]215        /* parse command line for (optional) arguments */
216        while (*++argv && **argv == COMMAND)
217                for (s = *argv + 1; *s; s++)
218                        switch (*s) {
219                        case 'b':
220                                unbrief = 0;
221                                break;
222                        case 'f':
223                                header = 0;
224                                break;
225                        case 'h':
226                                hack = 0;
227                                break;
228                        case 'i':
[12355]229                                idlep = 1;
[770]230                                unquick = 0;
231                                break;
232                        case 'l':
233                                large = 1;
234                                break;
235                        case 'm':
236                                match = 0;
237                                break;
238                        case 'p':
239                                plan = 0;
240                                break;
241                        case 'q':
242                                unquick = 0;
243                                break;
244                        case 's':
245                                small = 1;
246                                break;
247                        case 'w':
248                                wide = 0;
249                                break;
250                        default:
251                                fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");
252                                exit(1);
253                        }
[12355]254        if (unquick || idlep)
[770]255                (void) time(&tloc);
256        /*
257         * *argv == 0 means no names given
258         *
259         * this procedure should not (and doesn't) use zephyr at all, because
260         * finger [no args] should NOT give you every logged-in person...
261         */
262        if (*argv == 0)
263                doall();
264        else
265                donames(argv);
266        if (person1) {
267                printf("\nLocal:\n");
268                print(person1);
269        }
270        if (person2) {
271                printf("\nAthena-wide:\n");
272                print(person2);
273        }
274        exit(0);
[737]275}
276
277doall()
278{
[770]279        register struct person *p;
280        register struct passwd *pw;
281        int uf;
282        char name[NMAX + 1];
[737]283
[770]284        unshort = large;
285        if ((uf = open(USERLOG, 0)) < 0) {
286                fprintf(stderr, "finger: error opening %s\n", USERLOG);
287                exit(2);
288        }
289        if (unquick) {
[1677]290                setpwent();
[10851]291                fw_open();
[737]292        }
[770]293        while (read(uf, (char *) &user, sizeof user) == sizeof user) {
294                if (user.ut_name[0] == 0)
295                        continue;
[5454]296#if defined(USER_PROCESS)
297                if (user.ut_type != USER_PROCESS)
298                        continue;
299#endif
[770]300                if (person1 == 0)
301                        p = person1 = (struct person *) malloc(sizeof *p);
302                else {
303                        p->link = (struct person *) malloc(sizeof *p);
304                        p = p->link;
305                }
[8855]306                memcpy(name, user.ut_name, NMAX);
[770]307                name[NMAX] = 0;
[8855]308                memcpy(p->tty, user.ut_line, LMAX);
[770]309                p->tty[LMAX] = 0;
[8855]310                memcpy(p->host, user.ut_host, HMAX);
[770]311                p->host[HMAX] = 0;
312                p->loginout = 0;
[10851]313                p->loginat = UTTIME(user);
[770]314                p->pwd = 0;
315                p->loggedin = 1;
[1677]316                p->zlocation = 0;
[15094]317                p->logintime[0] = '\0';
[770]318                if (unquick && (pw = getpwnam(name))) {
319                        p->pwd = pwdcopy(pw);
320                        decode(p);
321                        p->name = p->pwd->pw_name;
322                }
323                else
324                        p->name = strcpy(malloc((unsigned) (strlen(name) + 1)),
325                                         name);
[737]326        }
[770]327        if (unquick) {
328                fwclose();
329                endpwent();
330        }
331        (void) close(uf);
332        if (person1 == 0) {
333                printf("\nNo one logged on\n");
334                return;
335        }
336        p->link = 0;
[737]337}
338
339donames(argv)
[770]340        char **argv;
[737]341{
[770]342        register struct person *p;
343        register struct person *q;      /* A second chain for athena-wide
344                                         * finger */
345        register struct passwd *pw;
[5019]346        struct passwd *hes_getpwnam();
[770]347        int uf, i;
348        Code_t state;
[737]349
[770]350        /*
351         * get names from command line and check to see if they're logged in
352         */
353        unshort = !small;
354        for (; *argv != 0; argv++) {
355                if (netfinger(*argv))
356                        continue;
357                if (person1 == 0) {
358                        p = person1 = (struct person *) malloc(sizeof *p);
359                        q = person2 = (struct person *) malloc(sizeof *q);
360                }
361                else {
362                        p->link = (struct person *) malloc(sizeof *p);
363                        p = p->link;
364                        q->link = (struct person *) malloc(sizeof *q);
365                        q = q->link;
366                }
367                p->name = q->name = *argv;
368                p->tty[0] = q->tty[0] = '\0';
369                p->host[0] = q->host[0] = '\0';
[15094]370                p->logintime[0] = q->logintime[0] = '\0';
[770]371                p->loginout = q->loginout = 0;
372                p->loginat = q->loginat = 0;
373                p->idletime = q->idletime = 0;
374                p->realname = q->realname = (char *) NULL;
375                p->nickname = q->nickname = (char *) NULL;
376                p->office = q->office = (char *) NULL;
377                p->officephone = q->officephone = (char *) NULL;
378                p->homephone = q->homephone = (char *) NULL;
379                p->random = q->random = (char *) NULL;
380                p->pwd = q->pwd = (struct passwd *) NULL;
381                p->loggedin = q->loggedin = 0;
382                p->writable = q->writable = '\0';
383                p->original = q->original = 1;
[1677]384                p->zlocation = q->zlocation = 0;
[737]385        }
[770]386        if (person1 == 0)
387                return;
388        p->link = q->link = 0;
389        /*
390         * if we are doing it, read /etc/passwd for the useful info for p* --
391         * ask hesiod for the entries for q*.
392         */
393        if (unquick) {
394                setpwent();
395                if (!match) {
396                        for (p = person1; p != 0; p = p->link)
397                                if (pw = getpwnam(p->name))
398                                        p->pwd = pwdcopy(pw);
[740]399
[770]400                }
401                else
402                        while ((pw = getpwent()) != 0) {
403                                for (p = person1; p != 0; p = p->link) {
404                                        if (!p->original)
405                                                continue;
406                                        if (strcmp(p->name, pw->pw_name) != 0 &&
407                                            !matchcmp(pw->pw_gecos, pw->pw_name, p->name))
408                                                continue;
409                                        if (p->pwd == 0) {
410                                                p->pwd = pwdcopy(pw);
411                                        }
412                                        else {
413                                                struct person *new;
[740]414
[770]415                                                /*
416                                                 * handle multiple login
417                                                 * names, insert new
418                                                 * "duplicate" entry behind
419                                                 */
420                                                new = (struct person *)
421                                                        malloc(sizeof *new);
422                                                new->pwd = pwdcopy(pw);
423                                                new->name = p->name;
424                                                new->original = 1;
[8598]425                                                new->zlocation = 0;
[770]426                                                new->loggedin = 0;
427                                                new->link = p->link;
428                                                p->original = 0;
429                                                p->link = new;
430                                                p = new;
431                                        }
432                                }
433                        }
434                /* now do the hesiod chain */
435                for (q = person2; q != 0; q = q->link)
[5019]436                        if (pw = hes_getpwnam(q->name))
[770]437                                q->pwd = pwdcopy(pw);
438                endpwent();
[737]439        }
[770]440        /* Now get login information */
441        if ((uf = open(USERLOG, 0)) < 0) {
442                fprintf(stderr, "finger: error opening %s\n", USERLOG);
443                exit(2);
444        }
445        while (read(uf, (char *) &user, sizeof user) == sizeof user) {
446                if (*user.ut_name == 0)
447                        continue;
[5455]448#if defined(USER_PROCESS)
449                if (user.ut_type != USER_PROCESS)
450                        continue;
451#endif
[745]452                for (p = person1; p != 0; p = p->link) {
[770]453                        if (p->loggedin == 2)
454                                continue;
455                        if (strncmp(p->pwd ? p->pwd->pw_name : p->name,
456                                    user.ut_name, NMAX) != 0)
457                                continue;
458                        if (p->loggedin == 0) {
[8855]459                                memcpy(p->tty, user.ut_line, LMAX);
[770]460                                p->tty[LMAX] = 0;
[8855]461                                memcpy(p->host, user.ut_host, HMAX);
[770]462                                p->host[HMAX] = 0;
[10851]463                                p->loginat = UTTIME(user);
[770]464                                p->loggedin = 1;
465                        }
466                        else {  /* p->loggedin == 1 */
467                                struct person *new;
[745]468
[770]469                                new = (struct person *) malloc(sizeof *new);
470                                new->name = p->name;
[8855]471                                memcpy(new->tty, user.ut_line, LMAX);
[770]472                                new->tty[LMAX] = 0;
[8855]473                                memcpy(new->host, user.ut_host, HMAX);
[770]474                                new->host[HMAX] = 0;
[10851]475                                new->loginat = UTTIME(user);
[15094]476                                new->logintime[0] = '\0';
[770]477                                new->pwd = p->pwd;
478                                new->loggedin = 1;
479                                new->original = 0;
[8598]480                                new->zlocation = 0;
[770]481                                new->link = p->link;
482                                p->loggedin = 2;
483                                p->link = new;
484                                p = new;
485                        }
[737]486                }
487        }
[770]488        /* Ask Zephyr if someone is logged in. */
489        if ((state = ZInitialize()) != ZERR_NONE) {
490                com_err("finger", state, "\nFailure in Zephyr \
491initialization");
492        }
493        else {
494                for (q = person2; q != (struct person *) NULL; q = q->link) {
495                        char curname[BUFSIZ];
[745]496
[770]497                        (void) strcpy(curname, q->name);
498                        (void) strcat(curname, "@");
499                        (void) strcat(curname, ZGetRealm());
[745]500
[5302]501                        if ((state = ZLocateUser(curname, &znloc,ZAUTH)) != ZERR_NONE) {
[770]502                                break;
503                        }
[1677]504                        q->zlocation = 1;
505                        q->loggedin = 0;
[1735]506                        for (i = 1; i <= znloc; i++) {
[770]507                                if ((state = ZGetLocations(&location, &numloc))
508                                    != 0)
509                                        break;
510                                else {
[15094]511                                        (void) strncpy(q->host, location.host,
512                                                       sizeof(q->host));
513                                        (void) strncpy(q->logintime,
514                                                       location.time,
515                                                       sizeof(q->logintime));
516                                        (void) strncpy(q->tty,
517                                                       location.tty,
518                                                       sizeof(q->tty));
[770]519                                        q->loggedin = 1;
[1677]520                                        /* if we can zlocate them, we can
521                                         * zwrite them -- if they're
522                                         * subscribing. */
523                                        q->writable = 1;
524
[770]525                                }
526                        }
527                }
[745]528        }
[770]529        (void) close(uf);
530        if (unquick) {
[10851]531                fw_open();
[770]532                for (p = person1, q = person2; p != 0 && q != 0;
533                     p = p->link, q = q->link) {
534                        decode(p);
535                        decode(q);
536                }
537                fwclose();
[745]538        }
[737]539}
540
[745]541print(personn)
[770]542        register struct person *personn;
[737]543{
[770]544        register struct person *p;
545        register FILE *fp;
546        register char *s;
547        register c;
[737]548
[770]549        /*
550         * print out what we got
551         */
552        if (header) {
553                if (unquick) {
554                        if (!unshort)
555                                if (wide)
[9689]556                                        printf("Login       Name               TTY Idle When        Office\n");
[770]557                                else
[9689]558                                        printf("Login     TTY Idle When        Office\n");
[770]559                }
560                else {
[9689]561                        printf("Login      TTY      When");
[12355]562                        if (idlep)
[9689]563                                printf("               Idle");
[770]564                        (void) putchar('\n');
565                }
[737]566        }
[770]567        for (p = personn; p != 0; p = p->link) {
568                if (!unquick) {
569                        quickprint(p);
570                        continue;
[737]571                }
[770]572                else
573                        decode(p);
574                if (!unshort) {
575                        shortprint(p);
576                        continue;
577                }
578                personprint(p);
579                if (p->pwd != 0) {
580                        if (hack) {
581                                s = malloc(strlen(p->pwd->pw_dir) +
582                                           (unsigned) sizeof PROJ);
583                                (void) strcpy(s, p->pwd->pw_dir);
584                                (void) strcat(s, PROJ);
585                                if ((fp = fopen(s, "r")) != 0) {
586                                        printf("Project: ");
587                                        while ((c = getc(fp)) != EOF) {
588                                                if (c == '\n')
589                                                        break;
590                                                if (isprint(c) || isspace(c))
591                                                        (void) putchar(c);
592                                                else
593                                                        (void) putchar(c ^ 100);
594                                        }
595                                        (void) fclose(fp);
596                                        (void) putchar('\n');
[737]597                                }
[770]598                                free(s);
[737]599                        }
[770]600                        if (plan) {
601                                register int i = 0, j;
602                                register int okay = 1;
603                                char mailbox[100];      /* mailbox name */
[745]604
[770]605                                s = malloc(strlen(p->pwd->pw_dir) +
606                                           (unsigned) sizeof PLAN);
607                                (void) strcpy(s, p->pwd->pw_dir);
608                                (void) strcat(s, PLAN);
609                                if ((fp = fopen(s, "r")) == 0)
610                                        printf("No Plan.\n");
611                                else {
612                                        printf("Plan:\n");
613                                        while ((c = getc(fp)) != EOF) {
[8597]614                                                if (i < MMLEN && okay) {
[770]615                                                        if (c != MM[i]) {
[8597]616                                                                for (j = 0; j < i; j++)
617                                                                        (void) putchar(MM[j]);
[770]618                                                                if (isprint(c) || isspace(c))
619                                                                        (void) putchar(c);
620                                                                else
621                                                                        (void) putchar(c ^ 100);
622                                                                okay = 0;
623                                                        }
624                                                }
625                                                else if (isprint(c) || isspace(c))
626                                                        (void) putchar(c);
627                                                else
628                                                        (void) putchar(c ^ 100);
629                                                i++;
630                                        }
631                                        (void) fclose(fp);
632                                        if (okay) {
633                                                (void) strcpy(mailbox, MAILDIR);
634                                                /* start with the directory */
635                                                (void) strcat(mailbox,
636                                                         (p->pwd)->pw_name);
637                                                if (access(mailbox, F_OK) == 0) {
638                                                        struct stat statb;
639
640                                                        (void) stat(mailbox, &statb);
641                                                        if (statb.st_size) {
642                                                                printf("User %s has new mail.\n", (p->pwd)->pw_name);
643                                                        };
644                                                }
645                                        }
646                                }
647                                free(s);
[745]648                        }
[737]649                }
[770]650                if (p->link != 0)
651                        (void) putchar('\n');
[737]652        }
653}
654
655/*
656 * Duplicate a pwd entry.
657 * Note: Only the useful things (what the program currently uses) are copied.
658 */
659struct passwd *
660pwdcopy(pfrom)
[770]661        register struct passwd *pfrom;
[737]662{
[770]663        register struct passwd *pto;
[737]664
[770]665        pto = (struct passwd *) malloc((unsigned) (sizeof *pto));
[740]666#define savestr(s) strcpy(malloc((unsigned)(strlen(s) + 1)), s)
[770]667        pto->pw_name = savestr(pfrom->pw_name);
668        pto->pw_uid = pfrom->pw_uid;
669        pto->pw_gecos = savestr(pfrom->pw_gecos);
670        pto->pw_dir = savestr(pfrom->pw_dir);
671        pto->pw_shell = savestr(pfrom->pw_shell);
[737]672#undef savestr
[770]673        return pto;
[737]674}
675
676/*
677 * print out information on quick format giving just name, tty, login time
678 * and idle time if idle is set.
679 */
680quickprint(pers)
[770]681        register struct person *pers;
[737]682{
[9689]683        printf("%-8.8s  ", pers->name);
[770]684        if (pers->loggedin) {
[12355]685                if (idlep) {
[770]686                        findidle(pers);
[9689]687                        printf("%c%-8s %-16.16s", pers->writable ? ' ' : '*',
688                               pers->tty, ctime(&pers->loginat));
[770]689                        (void) ltimeprint("   ", &pers->idletime, "");
690                }
691                else
[9689]692                        printf(" %-8s %-16.16s", pers->tty,
693                               ctime(&pers->loginat));
[770]694                (void) putchar('\n');
[745]695        }
696        else
[770]697                printf("          Not Logged In\n");
[737]698}
699
700/*
701 * print out information in short format, giving login name, full name,
702 * tty, idle time, login time, office location and phone.
703 */
704shortprint(pers)
[770]705        register struct person *pers;
[737]706{
[770]707        char *p;
708        char dialup;
[737]709
[770]710        if (pers->pwd == 0) {
711                printf("%-15s       ???\n", pers->name);
712                return;
713        }
[7601]714        printf("%-8s",  pers->pwd->pw_name);
[770]715        dialup = 0;
716        if (wide) {
717                if (pers->realname)
[7601]718                        printf(" %-20.20s", pers->realname);
719
[770]720                else
721                        printf("        ???          ");
722        }
[7601]723        (void) putchar(' '); 
[770]724        if (pers->loggedin && !pers->writable)
725                (void) putchar('*');
[745]726        else
[7601]727                (void) putchar(' ');
[770]728        if (*pers->tty) {
[5455]729                if (!strncmp(pers->tty, "tty", 3)) {
[770]730                        if (pers->tty[3] == 'd' && pers->loggedin)
731                                dialup = 1;
[9689]732                        printf("%-3.3s ", pers->tty + 3);
[5455]733                } else
734                if (!strncmp(pers->tty, "pts/", 4)) {
[9689]735                        printf("p%-2.2s ", pers->tty + 4);
[5455]736                } else
[9689]737                        printf("%-3.3s ", pers->tty);
[737]738        }
739        else
[770]740                printf("   ");
741        p = ctime(&pers->loginat);
742        if (pers->loggedin) {
743                stimeprint(&pers->idletime);
744                printf(" %3.3s %-5.5s ", p, p + 11);
745        }
746        else if (pers->loginat == 0)
747                printf(" < .  .  .  . >");
748        else if (tloc - pers->loginat >= 180 * 24 * 60 * 60)
749                printf(" <%-6.6s, %-4.4s>", p + 4, p + 20);
750        else
751                printf(" <%-12.12s>", p + 4);
752        if (dialup && pers->homephone)
753                printf(" %20s", pers->homephone);
754        else {
[7601]755                (void) putchar(' ');
[770]756                if (pers->office)
757                        printf(" %-12.12s", pers->office);
758                else if (pers->officephone || pers->homephone)
759                        printf("            ");
760                if (pers->officephone)
761                        printf(" %s", pers->officephone);
762                else if (pers->homephone)
763                        printf(" %s", pers->homephone);
764        }
765        (void) putchar('\n');
[737]766}
767
768/*
769 * print out a person in long format giving all possible information.
770 * directory and shell are inhibited if unbrief is clear.
771 */
772personprint(pers)
[770]773        register struct person *pers;
[737]774{
[770]775        if (pers->pwd == (struct passwd *) NULL) {
776                printf("Login name: %-10s\t\t\tIn real life: ???\n",
777                       pers->name);
778                return;
[737]779        }
[770]780        printf("Login name: %-10s", pers->pwd->pw_name);
781        if (pers->loggedin && !pers->writable)
782                printf("        (messages off)  ");
783        else
784                printf("                        ");
785        if (pers->realname)
786                printf("In real life: %s", pers->realname);
787        if (pers->nickname)
788                printf("\nNickname: %-s", pers->nickname);
789        if (pers->office) {
790                printf("\nOffice: %-.12s", pers->office);
791                if (pers->officephone) {
792                        printf(", %s", pers->officephone);
793                        if (pers->homephone)
794                                printf("\t\tHome phone: %s", pers->homephone);
795                        else if (pers->random)
796                                printf("\t\t%s", pers->random);
797                }
798                else if (pers->homephone)
799                        printf("\t\t\tHome phone: %s", pers->homephone);
800                else if (pers->random)
801                        printf("\t\t\t%s", pers->random);
802        }
803        else if (pers->officephone) {
804                printf("\nPhone: %s", pers->officephone);
805                if (pers->homephone)
806                        printf(", %s", pers->homephone);
807                if (pers->random)
808                        printf(", %s", pers->random);
809        }
810        else if (pers->homephone) {
811                printf("\nPhone: %s", pers->homephone);
812                if (pers->random)
813                        printf(", %s", pers->random);
814        }
[745]815        else if (pers->random)
[770]816                printf("\n%s", pers->random);
817        if (unbrief) {
818                printf("\nDirectory: %-25s", pers->pwd->pw_dir);
819                if (*pers->pwd->pw_shell)
820                        printf("\tShell: %-s", pers->pwd->pw_shell);
821        }
[1677]822        if (pers->zlocation) {
823                if (pers->loggedin)
824                        printf("\nOn since %s on %s on host %s",
825                               pers->logintime, pers->tty, pers->host);
826                else
827                        printf("\nNot currently locatable.");
828        }
829        else if (pers->loggedin) {
[770]830                if (*pers->host) {
[15349]831                        if (*pers->logintime) {
[770]832                                printf("\nOn since %s on %s from %s",
833                                    pers->logintime, pers->tty, pers->host);
834                        }
835                        else {
836                                register char *ep = ctime(&pers->loginat);
[745]837
[770]838                                printf("\nOn since %15.15s on %s from %s",
839                                       &ep[4], pers->tty, pers->host);
840                        (void) ltimeprint("\n", &pers->idletime, " Idle Time");
841                        }
842                }
843                else {
844                        register char *ep = ctime(&pers->loginat);
845
846                        printf("\nOn since %15.15s on %-*s",
847                               &ep[4], LMAX, pers->tty);
848                        (void) ltimeprint("\t", &pers->idletime, " Idle Time");
849                }
[737]850        }
[770]851        else if (pers->loginat == 0)
852                printf("\nNever logged in.");
853        else if (tloc - pers->loginat > 180 * 24 * 60 * 60) {
854                register char *ep = ctime(&pers->loginat);
855
856                printf("\nLast %s %10.10s, %4.4s on %s",
857                       pers->loginout ? "logout" : "login",
858                       ep, ep + 20, pers->tty);
859                if (*pers->host)
860                        printf(" from %s", pers->host);
861        }
[745]862        else {
[770]863                register char *ep = ctime(&pers->loginat);
864
865                printf("\nLast %s %16.16s on %s",
866                       pers->loginout ? "logout" : "login",
867                       ep, pers->tty);
868                if (*pers->host)
869                        printf(" from %s", pers->host);
[737]870        }
[770]871        (void) putchar('\n');
[737]872}
873
874/*
875 *  very hacky section of code to format phone numbers.  filled with
876 *  magic constants like 4, 7 and 10.
877 */
878char *
879phone(s, len, alldigits)
[770]880        register char *s;
881        int len;
882        char alldigits;
[737]883{
[770]884        char fonebuf[15];
885        register char *p = fonebuf;
886        register i;
[737]887
[770]888        if (!alldigits)
889                return (strcpy(malloc((unsigned) (len + 1)), s));
890        switch (len) {
891        case 4:
892                *p++ = ' ';
893                *p++ = 'x';
894                *p++ = '3';
895                *p++ = '-';
896                for (i = 0; i < 4; i++)
897                        *p++ = *s++;
898                break;
899        case 5:
900                *p++ = ' ';
901                *p++ = 'x';
902                *p++ = *s++;
903                *p++ = '-';
904                for (i = 0; i < 4; i++)
905                        *p++ = *s++;
906                break;
907        case 7:
908                for (i = 0; i < 3; i++)
909                        *p++ = *s++;
910                *p++ = '-';
911                for (i = 0; i < 4; i++)
912                        *p++ = *s++;
913                break;
914        case 10:
915                for (i = 0; i < 3; i++)
916                        *p++ = *s++;
917                *p++ = '-';
918                for (i = 0; i < 3; i++)
919                        *p++ = *s++;
920                *p++ = '-';
921                for (i = 0; i < 4; i++)
922                        *p++ = *s++;
923                break;
924        case 0:
925                return 0;
926        default:
927                return (strcpy(malloc((unsigned) (len + 1)), s));
928        }
929        *p++ = 0;
930        return (strcpy(malloc((unsigned) (p - fonebuf)), fonebuf));
[737]931}
932
933/*
934 * decode the information in the gecos field of /etc/passwd
935 */
936decode(pers)
[770]937        register struct person *pers;
[737]938{
[770]939        char buffer[256];
940        register char *bp, *gp, *lp;
941        int alldigits;
942        int hasspace;
943        int len;
[737]944
[770]945        pers->realname = 0;
946        pers->nickname = 0;
947        pers->office = 0;
948        pers->officephone = 0;
949        pers->homephone = 0;
950        pers->random = 0;
951        if (pers->pwd == 0)
952                return;
953        gp = pers->pwd->pw_gecos;
[737]954        bp = buffer;
[770]955        if (*gp == ASTERISK)
956                gp++;
957        while (*gp && *gp != COMMA)     /* name */
958                if (*gp == SAMENAME) {
959                        lp = pers->pwd->pw_name;
960                        if (islower(*lp))
961                                *bp++ = toupper(*lp++);
962                        while (*bp++ = *lp++);
963                        bp--;
964                        gp++;
[737]965                }
[770]966                else
967                        *bp++ = *gp++;
968        *bp++ = 0;
969        if ((len = bp - buffer) > 1)
970                pers->realname = strcpy(malloc((unsigned) len), buffer);
971        if (*gp == COMMA) {     /* nickname */
972                gp++;
973                bp = buffer;
[10970]974                while ((*gp != 0) && (*gp != COMMA)) {
[770]975                        if (*gp == SAMENAME) {
976                                lp = pers->pwd->pw_name;
977                                *bp++ = CAPITALIZE(*lp++);
[10970]978                                while (*lp != 0) {
[770]979                                        *bp++ = *lp++;
980                                }
981                        }
982                        else {
983                                *bp++ = *gp;
984                        }
985                        gp++;
986                }
[10970]987                *bp = 0;
[770]988                if (strlen(buffer) > 0) {
989                        pers->nickname = malloc((unsigned) (strlen(&buffer[0])
990                                                            + 1));
991                        (void) strcpy(pers->nickname, &buffer[0]);
992                }
[737]993        }
[770]994        if (*gp == COMMA) {     /* office, supposedly */
995                gp++;
996                hasspace = 0;
997                bp = buffer;
998                while (*gp && *gp != COMMA) {
999                        *bp = *gp++;
1000                        if (*bp == ' ')
1001                                hasspace = 1;
1002                        /* leave 9 for Tech Sq. and MIT expansion */
1003                        if (bp < buffer + sizeof buffer - 9)
1004                                bp++;
1005                }
1006                *bp = 0;
1007                len = bp - buffer;
1008                bp--;           /* point to last character */
1009                if (hasspace || len == 0)
1010                        len++;
1011                else if (*bp == TECHSQ) {
1012                        (void) strcpy(bp, " Tech Sq.");
1013                        len += 9;
1014                }
1015                else if (*bp == MIT) {
1016                        (void) strcpy(bp, " MIT");
1017                        len += 4;
1018                }
1019                else
1020                        len++;
1021                if (len > 1)
1022                        pers->office = strcpy(malloc((unsigned) len), buffer);
[737]1023        }
[770]1024        if (*gp == COMMA) {     /* office phone */
1025                gp++;
1026                bp = buffer;
1027                alldigits = 1;
1028                while (*gp && *gp != COMMA) {
1029                        *bp = *gp++;
1030                        if (!isdigit(*bp))
1031                                alldigits = 0;
1032                        if (bp < buffer + sizeof buffer - 1)
1033                                bp++;
1034                }
1035                *bp = 0;
1036                pers->officephone = phone(buffer, bp - buffer, alldigits);
[737]1037        }
[770]1038        if (*gp == COMMA) {     /* home phone */
1039                gp++;
1040                bp = buffer;
1041                alldigits = 1;
1042                while (*gp && *gp != COMMA) {
1043                        *bp = *gp++;
1044                        if (!isdigit(*bp))
1045                                alldigits = 0;
1046                        if (bp < buffer + sizeof buffer - 1)
1047                                bp++;
1048                }
1049                *bp = 0;
1050                pers->homephone = phone(buffer, bp - buffer, alldigits);
[737]1051        }
[770]1052        if (pers->loggedin)
1053                findidle(pers);
[1677]1054        else if (!pers->zlocation)
[770]1055                findwhen(pers);
[737]1056}
1057
1058/*
1059 * find the last log in of a user by checking the LASTLOG file.
1060 * the entry is indexed by the uid, so this can only be done if
1061 * the uid is known (which it isn't in quick mode)
1062 */
1063
[10851]1064fw_open()
[737]1065{
[5019]1066#ifndef NO_LASTLOG
[22069]1067        lf = open(LASTLOG, 0);
[4538]1068#endif
[22069]1069        lw = open(ACCTLOG, 0);
[737]1070}
1071
1072findwhen(pers)
[770]1073        register struct person *pers;
[737]1074{
[5019]1075#ifndef NO_LASTLOG
[770]1076        struct lastlog ll;
[5019]1077#endif
[770]1078        struct stat stb;
[10970]1079#ifndef HAVE_UTMPX_H
[770]1080        struct utmp *bp;
1081        struct utmp buf[128];
[6604]1082#else
1083        struct utmpx *bp;
1084        struct utmpx buf[128];
1085#endif
[770]1086        int i, bl, count;
1087        off_t lseek();
[737]1088
[770]1089        if (lw >= 0) {
1090                (void) fstat(lw, &stb);
1091                bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
1092                count = 0;
1093                for (bl--; bl >= 0; bl--) {
1094                        (void) lseek(lw, (off_t) (bl * sizeof(buf)), 0);
1095                        bp = &buf[read(lw, (char *) buf, sizeof(buf))
1096                                  / sizeof(buf[0]) - 1];
1097                        for (; bp >= buf; bp--) {
1098                                if (count++ == MAXSEARCH)
1099                                        goto fudged;
1100                                if (!strncmp(bp->ut_name, pers->name,
[901]1101                                             MIN(strlen(pers->name)+1, NMAX))) {
[770]1102                                        (void) strncpy(pers->tty,
1103                                                       bp->ut_line, LMAX);
1104                                        (void) strncpy(pers->host,
1105                                                       bp->ut_host, HMAX);
1106                                        pers->loginout = 1;
1107                                        for (i = 0; i < MAXTTYS; i++) {
1108                                                if (!strncmp(ttnames[i],
1109                                                             bp->ut_line,
1110                                                     sizeof(bp->ut_line))) {
1111                                                        pers->loginat = logouts[i];
1112                                                        return;
1113                                                }
1114                                        }
1115                                        goto fudged;
1116                                }
1117                                else {
1118                                        for (i = 0; i < MAXTTYS; i++) {
1119                                                if (ttnames[i][0] == 0) {
1120                                                        (void) strncpy(ttnames[i],
1121                                                                bp->ut_line,
1122                                                        sizeof(bp->ut_line));
[10851]1123                                                        logouts[i] =
1124                                                            UTTIME(*bp);
[770]1125                                                        break;
1126                                                }
1127                                                if (!strncmp(ttnames[i],
1128                                                             bp->ut_line,
1129                                                     sizeof(bp->ut_line))) {
[10851]1130                                                        logouts[i] =
1131                                                            UTTIME(*bp);
[770]1132                                                        break;
1133                                                }
1134                                        }
1135                                }
[737]1136                        }
1137                }
[770]1138        }
1139fudged:
[5019]1140#ifndef NO_LASTLOG
[770]1141        if (lf >= 0) {
1142                (void) lseek(lf, (long) pers->pwd->pw_uid * sizeof ll, 0);
1143                if ((i = read(lf, (char *) &ll, sizeof ll)) == sizeof ll) {
[8855]1144                        memcpy(pers->tty, ll.ll_line, LMAX);
[770]1145                        pers->tty[LMAX] = 0;
[8855]1146                        memcpy(pers->host, ll.ll_host, HMAX);
[770]1147                        pers->host[HMAX] = 0;
1148                        pers->loginat = ll.ll_time;
1149                        pers->loginout = 0;
1150                }
[745]1151                else {
[770]1152                        if (i != 0)
1153                                fprintf(stderr, "finger: %s read error\n",
1154                                        LASTLOG);
1155                        pers->tty[0] = 0;
1156                        pers->host[0] = 0;
1157                        pers->loginat = 0L;
[737]1158                }
[5019]1159        } else
1160#endif
1161        {
[770]1162                pers->tty[0] = 0;
1163                pers->host[0] = 0;
1164                pers->loginat = 0L;
[745]1165        }
[737]1166}
1167
1168fwclose()
1169{
[5019]1170#ifndef NO_LASTLOG
[1677]1171        if (lf >= 0) {
[770]1172                (void) close(lf);
[1677]1173                lf = -1;
1174        }
[5019]1175#endif
[1677]1176        if (lw >= 0) {
[770]1177                (void) close(lw);
[1677]1178                lw = -1;
1179        }
[737]1180}
1181
[10851]1182#define TTYLEN 5
1183
[737]1184/*
1185 * find the idle time of a user by doing a stat on /dev/tty??,
1186 * where tty?? has been gotten from USERLOG, supposedly.
1187 */
1188findidle(pers)
[770]1189        register struct person *pers;
[737]1190{
[770]1191        struct stat ttystatus;
[10851]1192        static char buffer[TTYLEN + LMAX + 1] = "/dev/";
[7601]1193        time_t t;
[745]1194
[1677]1195        if (!pers->zlocation) {
1196                (void) strcpy(buffer + TTYLEN, pers->tty);
1197                buffer[TTYLEN + LMAX] = 0;
1198                if (stat(buffer, &ttystatus) < 0) {
[5963]1199                        pers->idletime = NOIDLE;
1200                        pers->writable = 0;
1201                        return;
1202/*
[1677]1203                        fprintf(stderr, "finger: Can't stat %s\n", buffer);
1204                        exit(4);
[5963]1205*/
[1677]1206                }
1207                (void) time(&t);
1208                if (t < ttystatus.st_atime)
1209                        pers->idletime = 0L;
1210                else
1211                        pers->idletime = t - ttystatus.st_atime;
1212                pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE;
1213        } else {
1214                pers->idletime = 0L;
1215                pers->writable = 1;
[770]1216        }
[737]1217}
1218
1219/*
1220 * print idle time in short format; this program always prints 4 characters;
1221 * if the idle time is zero, it prints 4 blanks.
1222 */
1223stimeprint(dt)
[7601]1224        time_t *dt;
[737]1225{
[770]1226        register struct tm *delta;
[737]1227
[5963]1228        if (*dt == NOIDLE) {
1229                printf("   -");
1230                return;
1231        }
1232
[770]1233        delta = gmtime(dt);
1234        if (delta->tm_yday == 0)
1235                if (delta->tm_hour == 0)
1236                        if (delta->tm_min == 0)
1237                                printf("    ");
1238                        else
1239                                printf("  %2d", delta->tm_min);
1240                else if (delta->tm_hour >= 10)
1241                        printf("%3d:", delta->tm_hour);
1242                else
1243                        printf("%1d:%02d",
1244                               delta->tm_hour, delta->tm_min);
[737]1245        else
[770]1246                printf("%3dd", delta->tm_yday);
[737]1247}
1248
1249/*
1250 * print idle time in long format with care being taken not to pluralize
1251 * 1 minutes or 1 hours or 1 days.
1252 * print "prefix" first.
1253 */
1254ltimeprint(before, dt, after)
[770]1255        long *dt;
1256        char *before, *after;
[737]1257{
[770]1258        register struct tm *delta;
[737]1259
[5963]1260        if (*dt == NOIDLE) {
1261                printf("%sUnavailable%s", before, after);
1262                return (0);
1263        }
1264
[770]1265        delta = gmtime(dt);
1266        if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 &&
1267            delta->tm_sec <= 10)
1268                return (0);
1269        printf("%s", before);
1270        if (delta->tm_yday >= 10)
1271                printf("%d days", delta->tm_yday);
1272        else if (delta->tm_yday > 0)
1273                printf("%d day%s %d hour%s",
1274                       delta->tm_yday, delta->tm_yday == 1 ? "" : "s",
1275                       delta->tm_hour, delta->tm_hour == 1 ? "" : "s");
1276        else if (delta->tm_hour >= 10)
1277                printf("%d hours", delta->tm_hour);
1278        else if (delta->tm_hour > 0)
1279                printf("%d hour%s %d minute%s",
1280                       delta->tm_hour, delta->tm_hour == 1 ? "" : "s",
1281                       delta->tm_min, delta->tm_min == 1 ? "" : "s");
1282        else if (delta->tm_min >= 10)
1283                printf("%2d minutes", delta->tm_min);
1284        else if (delta->tm_min == 0)
1285                printf("%2d seconds", delta->tm_sec);
1286        else
1287                printf("%d minute%s %d second%s",
1288                       delta->tm_min,
1289                       delta->tm_min == 1 ? "" : "s",
1290                       delta->tm_sec,
1291                       delta->tm_sec == 1 ? "" : "s");
1292        printf("%s", after);
[745]1293        return (0);
[737]1294}
1295
1296matchcmp(gname, login, given)
[770]1297        register char *gname;
1298        char *login;
1299        char *given;
[737]1300{
[770]1301        char buffer[100];
1302        register char *bp, *lp;
1303        register c;
[737]1304
[770]1305        if (*gname == ASTERISK)
1306                gname++;
1307        lp = 0;
1308        bp = buffer;
1309        for (;;)
1310                switch (c = *gname++) {
1311                case SAMENAME:
1312                        for (lp = login; bp < buffer + sizeof buffer
1313                             && (*bp++ = *lp++););
1314                        bp--;
1315                        break;
1316                case ' ':
1317                case COMMA:
1318                case '\0':
1319                        *bp = 0;
1320                        if (namecmp(buffer, given))
1321                                return (1);
1322                        if (c == COMMA || c == 0)
1323                                return (0);
1324                        bp = buffer;
1325                        break;
1326                default:
1327                        if (bp < buffer + sizeof buffer)
1328                                *bp++ = c;
1329                }
1330        /* NOTREACHED */
[737]1331}
1332
1333namecmp(name1, name2)
[770]1334        register char *name1, *name2;
[737]1335{
[4538]1336        register int c1, c2;
[737]1337
[6474]1338        /* Do not permit matching on empty strings */
1339        if (*name1 == 0 || *name2 == 0)
1340                return (0);
1341       
[770]1342        for (;;) {
1343                c1 = *name1++;
1344                if (islower(c1))
1345                        c1 = toupper(c1);
1346                c2 = *name2++;
1347                if (islower(c2))
1348                        c2 = toupper(c2);
1349                if (c1 != c2)
1350                        break;
1351                if (c1 == 0)
1352                        return (1);
1353        }
1354        if (!c1) {
1355                for (name2--; isdigit(*name2); name2++);
1356                if (*name2 == 0)
1357                        return (1);
1358        }
[6474]1359        if (!c2) {
[770]1360                for (name1--; isdigit(*name1); name1++);
[6474]1361                if (*name1 == 0)
[770]1362                        return (1);
1363        }
1364        return (0);
[737]1365}
1366
1367netfinger(name)
[770]1368        char *name;
[737]1369{
[770]1370        char *host;
1371        struct hostent *hp;
1372        struct servent *sp;
1373        struct sockaddr_in sin;
1374        int s;
[7329]1375
[770]1376        register FILE *f;
1377        register int c;
1378        register int lastc;
[737]1379
[770]1380        if (name == NULL)
1381                return (0);
[7329]1382        host = strrchr(name, '@');
[770]1383        if (host == NULL) {
[7329]1384                host = strrchr(name, '%');
[770]1385                if (host != NULL)
1386                        *host = '@';
1387                else
1388                        return (0);
1389        }
1390        *host++ = 0;
1391        hp = gethostbyname(host);
1392        if (hp == NULL) {
1393                static struct hostent def;
1394                static struct in_addr defaddr;
1395                static char *alist[1];
1396                static char namebuf[128];
1397                u_long inet_addr();
[737]1398
[770]1399                defaddr.s_addr = inet_addr(host);
1400                if (defaddr.s_addr == -1) {
1401                        printf("unknown host: %s\n", host);
1402                        return (1);
1403                }
1404                (void) strcpy(namebuf, host);
1405                def.h_name = namebuf;
1406                def.h_addr_list = alist, def.h_addr = (char *) &defaddr;
1407                def.h_length = sizeof(struct in_addr);
1408                def.h_addrtype = AF_INET;
1409                def.h_aliases = 0;
1410                hp = &def;
[737]1411        }
[770]1412        printf("[%s]", hp->h_name);
[745]1413        (void) fflush(stdout);
[770]1414        sp = getservbyname("finger", "tcp");
1415        if (sp == 0) {
1416                printf("tcp/finger: unknown service\n");
1417                return (1);
1418        }
1419        sin.sin_family = hp->h_addrtype;
[8855]1420        memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
[770]1421        sin.sin_port = sp->s_port;
1422        s = socket(hp->h_addrtype, SOCK_STREAM, 0);
1423        if (s < 0) {
1424                (void) fflush(stdout);
1425                perror("socket");
1426                return (1);
1427        }
1428        if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
1429                (void) fflush(stdout);
1430                perror("connect");
1431                (void) close(s);
1432                return (1);
1433        }
1434        printf("\n");
1435        if (large)
1436                (void) write(s, "/W ", 3);
1437        (void) write(s, name, strlen(name));
1438        (void) write(s, "\r\n", 2);
1439        f = fdopen(s, "r");
1440        while ((c = getc(f)) != EOF) {
1441                switch (c) {
1442                case 0210:
1443                case 0211:
1444                case 0212:
1445                case 0214:
1446                        c -= 0200;
1447                        break;
1448                case 0215:
1449                        c = '\n';
1450                        break;
1451                }
1452                lastc = c;
1453                if (isprint(c) || isspace(c))
1454                        (void) putchar(c);
1455                else
1456                        (void) putchar(c ^ 100);
1457        }
1458        if (lastc != '\n')
1459                (void) putchar('\n');
1460        (void) fclose(f);
[745]1461        return (1);
[737]1462}
[770]1463
1464/*
1465 * Local Variables:
1466 * mode: c
1467 * c-indent-level: 8
1468 * c-continued-statement-offset: 8
1469 * c-brace-offset: -8
1470 * c-argdecl-indent: 8
1471 * c-label-offset: -8
1472 * End:
1473 */
Note: See TracBrowser for help on using the repository browser.