finger.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1980 Regents of the University of California.
00003  * All rights reserved.  The Berkeley software License Agreement
00004  * specifies the terms and conditions for redistribution.
00005  */
00006 
00007 #ifndef lint
00008 static char sccsid[] = "@(#)finger.c 1.1 87/12/21 SMI"; /* from 5.8 3/13/86 */
00009 #endif /* not lint */
00010 
00011 /*
00012  * This is a finger program.  It prints out useful information about users
00013  * by digging it up from various system files.
00014  *
00015  * There are three output formats, all of which give login name, teletype
00016  * line number, and login time.  The short output format is reminiscent
00017  * of finger on ITS, and gives one line of information per user containing
00018  * in addition to the minimum basic requirements (MBR), the full name of
00019  * the user, his idle time and location.  The
00020  * quick style output is UNIX who-like, giving only name, teletype and
00021  * login time.  Finally, the long style output give the same information
00022  * as the short (in more legible format), the home directory and shell
00023  * of the user, and, if it exits, a copy of the file .plan in the users
00024  * home directory.  Finger may be called with or without a list of people
00025  * to finger -- if no list is given, all the people currently logged in
00026  * are fingered.
00027  *
00028  * The program is validly called by one of the following:
00029  *
00030  *      finger                  {short form list of users}
00031  *      finger -l               {long form list of users}
00032  *      finger -b               {briefer long form list of users}
00033  *      finger -q               {quick list of users}
00034  *      finger -i               {quick list of users with idle times}
00035  *      finger namelist         {long format list of specified users}
00036  *      finger -s namelist      {short format list of specified users}
00037  *      finger -w namelist      {narrow short format list of specified users}
00038  *
00039  * where 'namelist' is a list of users login names.
00040  * The other options can all be given after one '-', or each can have its
00041  * own '-'.  The -f option disables the printing of headers for short and
00042  * quick outputs.  The -b option briefens long format outputs.  The -p
00043  * option turns off plans for long format outputs.
00044  */
00045 
00046 #include <sys/types.h>
00047 #include <ctype.h>
00048 #include <errno.h>
00049 #include <fcntl.h>
00050 #include <pwd.h>
00051 #include <stdio.h>
00052 #include <stdlib.h>
00053 #include <string.h>
00054 #include <time.h>
00055 #include <unistd.h>
00056 #include <utmp.h>
00057 #include <sys/ioctl.h>
00058 #include <sys/stat.h>
00059 #include <net/gen/in.h>
00060 #include <net/gen/inet.h>
00061 #include <net/gen/netdb.h>
00062 #include <net/gen/socket.h>
00063 #include <net/gen/tcp.h>
00064 #include <net/gen/tcp_hdr.h>
00065 #include <net/gen/tcp_io.h>
00066 #include <net/hton.h>
00067 #include <net/netlib.h>
00068 
00069 #define NONOTHING       1               /* don't say "No plan", or "No mail" */
00070 
00071 #define NONET   0
00072 
00073 #define ASTERISK        '*'             /* ignore this in real name */
00074 #define COMMA           ','             /* separator in pw_gecos field */
00075 #define COMMAND         '-'             /* command line flag char */
00076 #define SAMENAME        '&'             /* repeat login name in real name */
00077 #define TALKABLE        0220            /* tty is writable if this mode */
00078 
00079 struct utmp user;
00080 #define NMAX sizeof(user.ut_name)
00081 #define LMAX sizeof(user.ut_line)
00082 #define HMAX sizeof(user.ut_host)
00083 
00084 struct person {                 /* one for each person fingered */
00085         char *name;                     /* name */
00086         char tty[LMAX+1];               /* null terminated tty line */
00087         char host[HMAX+1];              /* null terminated remote host name */
00088         long loginat;                   /* time of (last) login */
00089         long idletime;                  /* how long idle (if logged in) */
00090         char *realname;                 /* pointer to full name */
00091         struct passwd *pwd;             /* structure of /etc/passwd stuff */
00092         char loggedin;                  /* person is logged in */
00093         char writable;                  /* tty is writable */
00094         char original;                  /* this is not a duplicate entry */
00095         struct person *link;            /* link to next person */
00096         char *where;                    /* terminal location */
00097         char hostt[HMAX+1];             /* login host */
00098 };
00099 
00100 #include <minix/paths.h>
00101 
00102 char LASTLOG[] = _PATH_LASTLOG; /* last login info */
00103 char USERLOG[] = _PATH_UTMP;            /* who is logged in */
00104 char PLAN[] = "/.plan";                 /* what plan file is */
00105 char PROJ[] = "/.project";              /* what project file */
00106         
00107 int unbrief = 1;                        /* -b option default */
00108 int header = 1;                         /* -f option default */
00109 int hack = 1;                           /* -h option default */
00110 int idle = 0;                           /* -i option default */
00111 int large = 0;                          /* -l option default */
00112 int match = 1;                          /* -m option default */
00113 int plan = 1;                           /* -p option default */
00114 int unquick = 1;                        /* -q option default */
00115 int small = 0;                          /* -s option default */
00116 int wide = 1;                           /* -w option default */
00117 
00118 int unshort;
00119 int lf;                                 /* LASTLOG file descriptor */
00120 struct person *person1;                 /* list of people */
00121 long tloc;                              /* current time */
00122 
00123 #if !_MINIX
00124 char *strcpy();
00125 char *ctime();
00126 #endif
00127 
00128 char *prog_name;
00129 
00130 int main (int argc, char *argv[]);
00131 static void doall(void);
00132 static void donames(char **args);
00133 static void print(void);
00134 static void fwopen(void);
00135 static void decode(struct person *pers);
00136 static void fwclose(void);
00137 static int netfinger (char *name);
00138 static int matchcmp (char *gname, char *login, char *given);
00139 static void quickprint (struct person *pers);
00140 static void shortprint (struct person *pers);
00141 static void personprint (struct person *pers);
00142 static int AlreadyPrinted(int uid);
00143 static int AnyMail (char *name);
00144 static struct passwd *pwdcopy(struct passwd *pfrom);
00145 static void findidle (struct person *pers);
00146 static int ltimeprint (char *dt, long *before, char *after);
00147 static void stimeprint (long *dt);
00148 static void findwhen (struct person *pers);
00149 static int namecmp (char *name1, char *name2);
00150 
00151 main(argc, argv)
00152         int argc;
00153         register char **argv;
00154 {
00155         FILE *fp;
00156         register char *s;
00157 
00158         prog_name= argv[0];
00159 
00160         /* parse command line for (optional) arguments */
00161         while (*++argv && **argv == COMMAND)
00162                 for (s = *argv + 1; *s; s++)
00163                         switch (*s) {
00164                         case 'b':
00165                                 unbrief = 0;
00166                                 break;
00167                         case 'f':
00168                                 header = 0;
00169                                 break;
00170                         case 'h':
00171                                 hack = 0;
00172                                 break;
00173                         case 'i':
00174                                 idle = 1;
00175                                 unquick = 0;
00176                                 break;
00177                         case 'l':
00178                                 large = 1;
00179                                 break;
00180                         case 'm':
00181                                 match = 0;
00182                                 break;
00183                         case 'p':
00184                                 plan = 0;
00185                                 break;
00186                         case 'q':
00187                                 unquick = 0;
00188                                 break;
00189                         case 's':
00190                                 small = 1;
00191                                 break;
00192                         case 'w':
00193                                 wide = 0;
00194                                 break;
00195                         default:
00196                                 fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");
00197                                 exit(1);
00198                         }
00199         if (unquick || idle)
00200                 time(&tloc);
00201         /*
00202          * *argv == 0 means no names given
00203          */
00204         if (*argv == 0)
00205                 doall();
00206         else
00207                 donames(argv);
00208         if (person1)
00209                 print();
00210         exit(0);
00211 }
00212 
00213 static void doall()
00214 {
00215         register struct person *p;
00216         register struct passwd *pw;
00217         int uf;
00218         char name[NMAX + 1];
00219 
00220         unshort = large;
00221         if ((uf = open(USERLOG, 0)) < 0) {
00222                 fprintf(stderr, "finger: error opening %s\n", USERLOG);
00223                 exit(2);
00224         }
00225         if (unquick) {
00226                 setpwent();
00227                 fwopen();
00228         }
00229         while (read(uf, (char *)&user, sizeof user) == sizeof user) {
00230                 if (user.ut_name[0] == 0)
00231                         continue;
00232                 if (person1 == 0)
00233                         p = person1 = (struct person *) malloc(sizeof *p);
00234                 else {
00235                         p->link = (struct person *) malloc(sizeof *p);
00236                         p = p->link;
00237                 }
00238                 bcopy(user.ut_name, name, NMAX);
00239                 name[NMAX] = 0;
00240                 bcopy(user.ut_line, p->tty, LMAX);
00241                 p->tty[LMAX] = 0;
00242                 bcopy(user.ut_host, p->host, HMAX);
00243                 p->host[HMAX] = 0;
00244                 p->loginat = user.ut_time;
00245                 p->pwd = 0;
00246                 p->loggedin = 1;
00247                 p->where = NULL;
00248                 if (unquick && (pw = getpwnam(name))) {
00249                         p->pwd = pwdcopy(pw);
00250                         decode(p);
00251                         p->name = p->pwd->pw_name;
00252                 } else
00253                         p->name = strcpy(malloc(strlen(name) + 1), name);
00254         }
00255         if (unquick) {
00256                 fwclose();
00257                 endpwent();
00258         }
00259         close(uf);
00260         if (person1 == 0) {
00261                 printf("No one logged on\n");
00262                 return;
00263         }
00264         p->link = 0;
00265 }
00266 
00267 static void donames(argv)
00268         char **argv;
00269 {
00270         register struct person *p;
00271         register struct passwd *pw;
00272         int uf;
00273 
00274         /*
00275          * get names from command line and check to see if they're
00276          * logged in
00277          */
00278         unshort = !small;
00279         for (; *argv != 0; argv++) {
00280                 if (netfinger(*argv))
00281                         continue;
00282                 if (person1 == 0)
00283                         p = person1 = (struct person *) malloc(sizeof *p);
00284                 else {
00285                         p->link = (struct person *) malloc(sizeof *p);
00286                         p = p->link;
00287                 }
00288                 p->name = *argv;
00289                 p->loggedin = 0;
00290                 p->original = 1;
00291                 p->pwd = 0;
00292         }
00293         if (person1 == 0)
00294                 return;
00295         p->link = 0;
00296         /*
00297          * if we are doing it, read /etc/passwd for the useful info
00298          */
00299         if (unquick) {
00300                 setpwent();
00301                 if (!match) {
00302                         for (p = person1; p != 0; p = p->link)
00303                                 if (pw = getpwnam(p->name))
00304                                         p->pwd = pwdcopy(pw);
00305                 } else while ((pw = getpwent()) != 0) {
00306                         for (p = person1; p != 0; p = p->link) {
00307                                 if (!p->original)
00308                                         continue;
00309                                 if (strcmp(p->name, pw->pw_name) != 0 &&
00310                                     !matchcmp(pw->pw_gecos, pw->pw_name, p->name))
00311                                         continue;
00312                                 if (p->pwd == 0)
00313                                         p->pwd = pwdcopy(pw);
00314                                 else {
00315                                         struct person *new;
00316                                         /*
00317                                          * handle multiple login names, insert
00318                                          * new "duplicate" entry behind
00319                                          */
00320                                         new = (struct person *)
00321                                                 malloc(sizeof *new);
00322                                         new->pwd = pwdcopy(pw);
00323                                         new->name = p->name;
00324                                         new->original = 1;
00325                                         new->loggedin = 0;
00326                                         new->link = p->link;
00327                                         p->original = 0;
00328                                         p->link = new;
00329                                         p = new;
00330                                 }
00331                         }
00332                 }
00333                 endpwent();
00334         }
00335         /* Now get login information */
00336         if ((uf = open(USERLOG, 0)) < 0) {
00337                 fprintf(stderr, "finger: error opening %s\n", USERLOG);
00338                 exit(2);
00339         }
00340         while (read(uf, (char *)&user, sizeof user) == sizeof user) {
00341                 if (*user.ut_name == 0)
00342                         continue;
00343                 for (p = person1; p != 0; p = p->link) {
00344                         if (p->loggedin == 2)
00345                                 continue;
00346                         if (strncmp(p->pwd ? p->pwd->pw_name : p->name,
00347                                     user.ut_name, NMAX) != 0)
00348                                 continue;
00349                         if (p->loggedin == 0) {
00350                                 bcopy(user.ut_line, p->tty, LMAX);
00351                                 p->tty[LMAX] = 0;
00352                                 bcopy(user.ut_host, p->host, HMAX);
00353                                 p->host[HMAX] = 0;
00354                                 p->loginat = user.ut_time;
00355                                 p->loggedin = 1;
00356                         } else {        /* p->loggedin == 1 */
00357                                 struct person *new;
00358                                 new = (struct person *) malloc(sizeof *new);
00359                                 new->name = p->name;
00360                                 bcopy(user.ut_line, new->tty, LMAX);
00361                                 new->tty[LMAX] = 0;
00362                                 bcopy(user.ut_host, new->host, HMAX);
00363                                 new->host[HMAX] = 0;
00364                                 new->loginat = user.ut_time;
00365                                 new->pwd = p->pwd;
00366                                 new->loggedin = 1;
00367                                 new->original = 0;
00368                                 new->link = p->link;
00369                                 p->loggedin = 2;
00370                                 p->link = new;
00371                                 p = new;
00372                         }
00373                 }
00374         }
00375         close(uf);
00376         if (unquick) {
00377                 fwopen();
00378                 for (p = person1; p != 0; p = p->link)
00379                         decode(p);
00380                 fwclose();
00381         }
00382 }
00383 
00384 static void print()
00385 {
00386         register FILE *fp;
00387         register struct person *p;
00388         register char *s;
00389         register c;
00390 
00391         /*
00392          * print out what we got
00393          */
00394         if (header) {
00395                 if (unquick) {
00396                         if (!unshort)
00397                                 if (wide)
00398                                         printf("Login       Name              TTY Idle    When            Where\n");
00399                                 else
00400                                         printf("Login    TTY Idle    When            Where\n");
00401                 } else {
00402                         printf("Login      TTY            When");
00403                         if (idle)
00404                                 printf("             Idle");
00405                         putchar('\n');
00406                 }
00407         }
00408         for (p = person1; p != 0; p = p->link) {
00409                 if (!unquick) {
00410                         quickprint(p);
00411                         continue;
00412                 }
00413                 if (!unshort) {
00414                         shortprint(p);
00415                         continue;
00416                 }
00417                 personprint(p);
00418                 if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) {
00419                         AnyMail(p->pwd->pw_name);
00420                         if (hack) {
00421                                 s = malloc(strlen(p->pwd->pw_dir) +
00422                                         sizeof PROJ);
00423                                 strcpy(s, p->pwd->pw_dir);
00424                                 strcat(s, PROJ);
00425                                 if ((fp = fopen(s, "r")) != 0) {
00426                                         printf("Project: ");
00427                                         while ((c = getc(fp)) != EOF) {
00428                                                 if (c == '\n')
00429                                                         break;
00430                                                 if (isprint(c) || isspace(c))
00431                                                         putchar(c);
00432                                                 else
00433                                                         putchar(c ^ 100);
00434                                         }
00435                                         fclose(fp);
00436                                         putchar('\n');
00437                                 }
00438                                 free(s);
00439                         }
00440                         if (plan) {
00441                                 s = malloc(strlen(p->pwd->pw_dir) +
00442                                         sizeof PLAN);
00443                                 strcpy(s, p->pwd->pw_dir);
00444                                 strcat(s, PLAN);
00445                                 if ((fp = fopen(s, "r")) == 0) {
00446                                         if (!NONOTHING) printf("No Plan.\n");
00447                                 } else {
00448                                         printf("Plan:\n");
00449                                         while ((c = getc(fp)) != EOF)
00450                                                 if (isprint(c) || isspace(c))
00451                                                         putchar(c);
00452                                                 else
00453                                                         putchar(c ^ 100);
00454                                         fclose(fp);
00455                                 }
00456                                 free(s);
00457                         }
00458                 }
00459                 if (p->link != 0)
00460                         putchar('\n');
00461         }
00462 }
00463 
00464 /*
00465  * Duplicate a pwd entry.
00466  * Note: Only the useful things (what the program currently uses) are copied.
00467  */
00468 static struct passwd *
00469 pwdcopy(pfrom)
00470         register struct passwd *pfrom;
00471 {
00472         register struct passwd *pto;
00473 
00474         pto = (struct passwd *) malloc(sizeof *pto);
00475 #define savestr(s) strcpy(malloc(strlen(s) + 1), s)
00476         pto->pw_name = savestr(pfrom->pw_name);
00477         pto->pw_uid = pfrom->pw_uid;
00478         pto->pw_gecos = savestr(pfrom->pw_gecos);
00479         pto->pw_dir = savestr(pfrom->pw_dir);
00480         pto->pw_shell = savestr(pfrom->pw_shell);
00481 #undef savestr
00482         return pto;
00483 }
00484 
00485 /*
00486  * print out information on quick format giving just name, tty, login time
00487  * and idle time if idle is set.
00488  */
00489 static void quickprint(pers)
00490         register struct person *pers;
00491 {
00492         printf("%-*.*s  ", NMAX, NMAX, pers->name);
00493         if (pers->loggedin) {
00494                 if (idle) {
00495                         findidle(pers);
00496                         printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*',
00497                                 LMAX, pers->tty, ctime(&pers->loginat));
00498                         ltimeprint("   ", &pers->idletime, "");
00499                 } else
00500                         printf(" %-*s %-16.16s", LMAX,
00501                                 pers->tty, ctime(&pers->loginat));
00502                 putchar('\n');
00503         } else
00504                 printf("          Not Logged In\n");
00505 }
00506 
00507 /*
00508  * print out information in short format, giving login name, full name,
00509  * tty, idle time, login time, and host.
00510  */
00511 static void shortprint(pers)
00512         register struct person *pers;
00513 {
00514         char *p;
00515         char dialup;
00516 
00517         if (pers->pwd == 0) {
00518                 printf("%-15s       ???\n", pers->name);
00519                 return;
00520         }
00521         printf("%-*s", NMAX, pers->pwd->pw_name);
00522         dialup = 0;
00523         if (wide) {
00524                 if (pers->realname)
00525                         printf(" %-20.20s", pers->realname);
00526                 else
00527                         printf("        ???          ");
00528         }
00529         putchar(' ');
00530         if (pers->loggedin && !pers->writable)
00531                 putchar('*');
00532         else
00533                 putchar(' ');
00534         if (*pers->tty) {
00535                 if (pers->tty[0] == 't' && pers->tty[1] == 't' &&
00536                     pers->tty[2] == 'y') {
00537                         if (pers->tty[3] == 'd' && pers->loggedin)
00538                                 dialup = 1;
00539                         printf("%-2.2s ", pers->tty + 3);
00540                 } else
00541                         printf("%-2.2s ", pers->tty);
00542         } else
00543                 printf("   ");
00544         p = ctime(&pers->loginat);
00545         if (pers->loggedin) {
00546                 stimeprint(&pers->idletime);
00547                 printf(" %3.3s %-5.5s ", p, p + 11);
00548         } else if (pers->loginat == 0)
00549                 printf(" < .  .  .  . >");
00550         else if (tloc - pers->loginat >= 180L * 24 * 60 * 60)
00551                 printf(" <%-6.6s, %-4.4s>", p + 4, p + 20);
00552         else
00553                 printf(" <%-12.12s>", p + 4);
00554         if (pers->host[0])
00555                 printf(" %-20.20s", pers->host);
00556         putchar('\n');
00557 }
00558 
00559 
00560 /*
00561  * print out a person in long format giving all possible information.
00562  * directory and shell are inhibited if unbrief is clear.
00563  */
00564 static void
00565 personprint(pers)
00566         register struct person *pers;
00567 {
00568         if (pers->pwd == 0) {
00569                 printf("Login name: %-10s\t\t\tIn real life: ???\n",
00570                         pers->name);
00571                 return;
00572         }
00573         printf("Login name: %-10s", pers->pwd->pw_name);
00574         if (pers->loggedin && !pers->writable)
00575                 printf("        (messages off)  ");
00576         else
00577                 printf("                        ");
00578         if (pers->realname)
00579                 printf("In real life: %s", pers->realname);
00580         if (unbrief) {
00581                 printf("\nDirectory: %-25s", pers->pwd->pw_dir);
00582                 if (*pers->pwd->pw_shell)
00583                         printf("\tShell: %-s", pers->pwd->pw_shell);
00584         }
00585         if (pers->loggedin) {
00586                 register char *ep = ctime(&pers->loginat);
00587                 if (*pers->host) {
00588                         printf("\nOn since %15.15s on %s from %s",
00589                                 &ep[4], pers->tty, pers->host);
00590                         ltimeprint("\n", &pers->idletime, " Idle Time");
00591                 } else {
00592                         printf("\nOn since %15.15s on %-*s",
00593                                 &ep[4], LMAX, pers->tty);
00594                         ltimeprint("\t", &pers->idletime, " Idle Time");
00595                 }
00596         } else if (pers->loginat == 0) {
00597                 if (lf >= 0) printf("\nNever logged in.");
00598         } else if (tloc - pers->loginat > 180L * 24 * 60 * 60) {
00599                 register char *ep = ctime(&pers->loginat);
00600                 printf("\nLast login %10.10s, %4.4s on %s",
00601                         ep, ep+20, pers->tty);
00602                 if (*pers->host)
00603                         printf(" from %s", pers->host);
00604         } else {
00605                 register char *ep = ctime(&pers->loginat);
00606                 printf("\nLast login %16.16s on %s", ep, pers->tty);
00607                 if (*pers->host)
00608                         printf(" from %s", pers->host);
00609         }
00610         putchar('\n');
00611 }
00612 
00613 
00614 /*
00615  * decode the information in the gecos field of /etc/passwd
00616  */
00617 static void
00618 decode(pers)
00619         register struct person *pers;
00620 {
00621         char buffer[256];
00622         register char *bp, *gp, *lp;
00623         int alldigits;
00624         int hasspace;
00625         int len;
00626 
00627         pers->realname = 0;
00628         if (pers->pwd == 0)
00629                 return;
00630         gp = pers->pwd->pw_gecos;
00631         bp = buffer;
00632         if (*gp == ASTERISK)
00633                 gp++;
00634         while (*gp && *gp != COMMA)                     /* name */
00635                 if (*gp == SAMENAME) {
00636                         lp = pers->pwd->pw_name;
00637                         if (islower(*lp))
00638                                 *bp++ = toupper(*lp++);
00639                         while (*bp++ = *lp++)
00640                                 ;
00641                         bp--;
00642                         gp++;
00643                 } else
00644                         *bp++ = *gp++;
00645         *bp++ = 0;
00646         if ((len = bp - buffer) > 1)
00647                 pers->realname = strcpy(malloc(len), buffer);
00648         if (pers->loggedin)
00649                 findidle(pers);
00650         else
00651                 findwhen(pers);
00652 }
00653 
00654 /*
00655  * find the last log in of a user by checking the LASTLOG file.
00656  * the entry is indexed by the uid, so this can only be done if
00657  * the uid is known (which it isn't in quick mode)
00658  */
00659 
00660 static void
00661 fwopen()
00662 {
00663         if ((lf = open(LASTLOG, 0)) < 0) {
00664                 if (errno == ENOENT) return;
00665                 fprintf(stderr, "finger: %s open error\n", LASTLOG);
00666         }
00667 }
00668 
00669 static void
00670 findwhen(pers)
00671         register struct person *pers;
00672 {
00673         struct utmp ll;
00674 #define ll_line ut_line
00675 #define ll_host ut_host
00676 #define ll_time ut_time
00677 
00678         int i;
00679 
00680         if (lf >= 0) {
00681                 lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0);
00682                 if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) {
00683                         bcopy(ll.ll_line, pers->tty, LMAX);
00684                         pers->tty[LMAX] = 0;
00685                         bcopy(ll.ll_host, pers->host, HMAX);
00686                         pers->host[HMAX] = 0;
00687                         pers->loginat = ll.ll_time;
00688                 } else {
00689                         if (i != 0)
00690                                 fprintf(stderr, "finger: %s read error\n",
00691                                         LASTLOG);
00692                         pers->tty[0] = 0;
00693                         pers->host[0] = 0;
00694                         pers->loginat = 0L;
00695                 }
00696         } else {
00697                 pers->tty[0] = 0;
00698                 pers->host[0] = 0;
00699                 pers->loginat = 0L;
00700         }
00701 }
00702 
00703 static void fwclose()
00704 {
00705         if (lf >= 0)
00706                 close(lf);
00707 }
00708 
00709 /*
00710  * find the idle time of a user by doing a stat on /dev/tty??,
00711  * where tty?? has been gotten from USERLOG, supposedly.
00712  */
00713 static void
00714 findidle(pers)
00715         register struct person *pers;
00716 {
00717         struct stat ttystatus;
00718         static char buffer[20] = "/dev/";
00719         long t;
00720 #define TTYLEN 5
00721 
00722         strcpy(buffer + TTYLEN, pers->tty);
00723         buffer[TTYLEN+LMAX] = 0;
00724         if (stat(buffer, &ttystatus) < 0) {
00725                 fprintf(stderr, "finger: Can't stat %s\n", buffer);
00726                 exit(4);
00727         }
00728         time(&t);
00729         if (t < ttystatus.st_atime)
00730                 pers->idletime = 0L;
00731         else
00732                 pers->idletime = t - ttystatus.st_atime;
00733         pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE;
00734 }
00735 
00736 /*
00737  * print idle time in short format; this program always prints 4 characters;
00738  * if the idle time is zero, it prints 4 blanks.
00739  */
00740 static void
00741 stimeprint(dt)
00742         long *dt;
00743 {
00744         register struct tm *delta;
00745 
00746         delta = gmtime(dt);
00747         if (delta->tm_yday == 0)
00748                 if (delta->tm_hour == 0)
00749                         if (delta->tm_min == 0)
00750                                 printf("    ");
00751                         else
00752                                 printf("  %2d", delta->tm_min);
00753                 else
00754                         if (delta->tm_hour >= 10)
00755                                 printf("%3d:", delta->tm_hour);
00756                         else
00757                                 printf("%1d:%02d",
00758                                         delta->tm_hour, delta->tm_min);
00759         else
00760                 printf("%3dd", delta->tm_yday);
00761 }
00762 
00763 /*
00764  * print idle time in long format with care being taken not to pluralize
00765  * 1 minutes or 1 hours or 1 days.
00766  * print "prefix" first.
00767  */
00768 static int
00769 ltimeprint(before, dt, after)
00770         long *dt;
00771         char *before, *after;
00772 {
00773         register struct tm *delta;
00774 
00775         delta = gmtime(dt);
00776         if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 &&
00777             delta->tm_sec <= 10)
00778                 return (0);
00779         printf("%s", before);
00780         if (delta->tm_yday >= 10)
00781                 printf("%d days", delta->tm_yday);
00782         else if (delta->tm_yday > 0)
00783                 printf("%d day%s %d hour%s",
00784                         delta->tm_yday, delta->tm_yday == 1 ? "" : "s",
00785                         delta->tm_hour, delta->tm_hour == 1 ? "" : "s");
00786         else
00787                 if (delta->tm_hour >= 10)
00788                         printf("%d hours", delta->tm_hour);
00789                 else if (delta->tm_hour > 0)
00790                         printf("%d hour%s %d minute%s",
00791                                 delta->tm_hour, delta->tm_hour == 1 ? "" : "s",
00792                                 delta->tm_min, delta->tm_min == 1 ? "" : "s");
00793                 else
00794                         if (delta->tm_min >= 10)
00795                                 printf("%2d minutes", delta->tm_min);
00796                         else if (delta->tm_min == 0)
00797                                 printf("%2d seconds", delta->tm_sec);
00798                         else
00799                                 printf("%d minute%s %d second%s",
00800                                         delta->tm_min,
00801                                         delta->tm_min == 1 ? "" : "s",
00802                                         delta->tm_sec,
00803                                         delta->tm_sec == 1 ? "" : "s");
00804         printf("%s", after);
00805 }
00806 
00807 static int
00808 matchcmp(gname, login, given)
00809         register char *gname;
00810         char *login;
00811         char *given;
00812 {
00813         char buffer[100];
00814         register char *bp, *lp;
00815         register c;
00816 
00817         if (*gname == ASTERISK)
00818                 gname++;
00819         lp = 0;
00820         bp = buffer;
00821         for (;;)
00822                 switch (c = *gname++) {
00823                 case SAMENAME:
00824                         for (lp = login; bp < buffer + sizeof buffer
00825                                          && (*bp++ = *lp++);)
00826                                 ;
00827                         bp--;
00828                         break;
00829                 case ' ':
00830                 case COMMA:
00831                 case '\0':
00832                         *bp = 0;
00833                         if (namecmp(buffer, given))
00834                                 return (1);
00835                         if (c == COMMA || c == 0)
00836                                 return (0);
00837                         bp = buffer;
00838                         break;
00839                 default:
00840                         if (bp < buffer + sizeof buffer)
00841                                 *bp++ = c;
00842                 }
00843         /*NOTREACHED*/
00844 }
00845 
00846 static int
00847 namecmp(name1, name2)
00848         register char *name1, *name2;
00849 {
00850         register c1, c2;
00851 
00852         for (;;) {
00853                 c1 = *name1++;
00854                 if (islower(c1))
00855                         c1 = toupper(c1);
00856                 c2 = *name2++;
00857                 if (islower(c2))
00858                         c2 = toupper(c2);
00859                 if (c1 != c2)
00860                         break;
00861                 if (c1 == 0)
00862                         return (1);
00863         }
00864         if (!c1) {
00865                 for (name2--; isdigit(*name2); name2++)
00866                         ;
00867                 if (*name2 == 0)
00868                         return (1);
00869         } else if (!c2) {
00870                 for (name1--; isdigit(*name1); name1++)
00871                         ;
00872                 if (*name2 == 0)
00873                         return (1);
00874         }
00875         return (0);
00876 }
00877 
00878 #if NONET
00879 static int
00880 netfinger(name)
00881 char *name;
00882 {
00883         return 0;
00884 }
00885 #else
00886 static int
00887 netfinger(name)
00888         char *name;
00889 {
00890         char *host;
00891         char fname[100];
00892         struct hostent *hp;
00893         struct servent *sp;
00894         int s, result;
00895 #if !_MINIX
00896         char *rindex();
00897 #endif
00898         register FILE *f;
00899         register int c;
00900         register int lastc;
00901         nwio_tcpconf_t tcpconf;
00902         nwio_tcpcl_t tcpconnopt;
00903         char *tcp_device;
00904 
00905         if (name == NULL)
00906                 return (0);
00907         host = rindex(name, '@');
00908         if (host == NULL)
00909                 return (0);
00910         *host++ = 0;
00911         hp = gethostbyname(host);
00912         if (hp == NULL) {
00913                 static struct hostent def;
00914                 static ipaddr_t defaddr;
00915                 static char namebuf[128];
00916 
00917                 defaddr = inet_addr(host);
00918                 if (defaddr == -1) {
00919                         printf("unknown host: %s\n", host);
00920                         return (1);
00921                 }
00922                 strcpy(namebuf, host);
00923                 def.h_name = namebuf;
00924                 def.h_addr = (char *)&defaddr;
00925                 def.h_length = sizeof (ipaddr_t);
00926                 def.h_addrtype = AF_INET;
00927                 def.h_aliases = 0;
00928                 hp = &def;
00929         }
00930         printf("[%s] ", hp->h_name);
00931         fflush(stdout);
00932 
00933         tcp_device= getenv("TCP_DEVICE");
00934         if (tcp_device == NULL)
00935                 tcp_device= TCP_DEVICE;
00936         s= open (tcp_device, O_RDWR);
00937         if (s == -1)
00938         {
00939                 fprintf(stderr, "%s: unable to open %s (%s)\n",
00940                         prog_name, tcp_device, strerror(errno));
00941                 exit(1);
00942         }
00943         tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
00944         tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
00945         tcpconf.nwtc_remport= htons(TCPPORT_FINGER);
00946 
00947         result= ioctl (s, NWIOSTCPCONF, &tcpconf);
00948         if (result<0)
00949         {
00950                 fprintf(stderr, "%s\n", strerror(errno));
00951                 exit(1);
00952         }
00953 
00954         tcpconnopt.nwtcl_flags= 0;
00955 
00956         do
00957         {
00958                 result= ioctl (s, NWIOTCPCONN, &tcpconnopt);
00959                 if (result<0 && errno== EAGAIN)
00960                 {
00961                         fprintf(stderr, "got EAGAIN error, sleeping 2s\n");
00962                         sleep(2);
00963                 }
00964         } while (result<0 && errno == EAGAIN);
00965         if (result<0)
00966         {
00967                 fprintf(stderr, "%s\n", strerror(errno));
00968                 exit(1);
00969         }
00970         printf("\r\n");
00971         if (large) write(s, "/W ", 3);
00972         write(s, name, strlen(name));
00973         write(s, "\r\n", 2);
00974         f = fdopen(s, "r");
00975         while ((c = getc(f)) != EOF) {
00976 /*
00977                 switch(c) {
00978                 case 0210:
00979                 case 0211:
00980                 case 0212:
00981                 case 0214:
00982                         c -= 0200;
00983                         break;
00984                 case 0215:
00985                         c = '\n';
00986                         break;
00987                 }
00988 */
00989                 c &= ~0200;
00990                 if (c == '\r')
00991                 {
00992                         c= getc(f) & ~0200;
00993                         if (c == '\012')
00994                         {
00995                                 lastc= c;
00996                                 putchar('\n');
00997                                 continue;
00998                         }
00999                         else
01000                                 putchar('\r');
01001                 }
01002                 lastc = c;
01003                 if (isprint(c) || isspace(c))
01004                         putchar(c);
01005                 else
01006                         putchar(c ^ 100);
01007         }
01008         if (lastc != '\n')
01009                 putchar('\n');
01010         (void)fclose(f);
01011         return (1);
01012 }
01013 #endif
01014 
01015 /*
01016  *      AnyMail - takes a username (string pointer thereto), and
01017  *      prints on standard output whether there is any unread mail,
01018  *      and if so, how old it is.       (JCM@Shasta 15 March 80)
01019  */
01020 #define preamble "/usr/spool/mail/"     /* mailboxes are there */
01021 static int
01022 AnyMail(name)
01023 char *name;
01024 {
01025         struct stat buf;                /* space for file status buffer */
01026         char *mbxdir = preamble;        /* string with path preamble */
01027         char *mbxpath;                  /* space for entire pathname */
01028 
01029 #if !_MINIX
01030         char *ctime();                  /* convert longword time to ascii */
01031 #endif
01032         char *timestr;
01033 
01034         mbxpath = malloc(strlen(name) + strlen(preamble) + 1);
01035 
01036         strcpy(mbxpath, mbxdir);        /* copy preamble into path name */
01037         strcat(mbxpath, name);          /* concatenate user name to path */
01038 
01039         if (stat(mbxpath, &buf) == -1 || buf.st_size == 0) {
01040             /* Mailbox is empty or nonexistent */
01041             if (!NONOTHING) printf("No unread mail\n");
01042         } else {
01043             if (buf.st_mtime == buf.st_atime) {
01044                 /* There is something in the mailbox, but we can't really
01045                  *   be sure whether it is mail held there by the user
01046                  *   or a (single) new message that was placed in a newly
01047                  *   recreated mailbox, so we punt and call it "unread mail."
01048                  */
01049                 printf("Unread mail since ");
01050                 printf(ctime(&buf.st_mtime));
01051             } else {
01052                 /* New mail has definitely arrived since the last time
01053                  *   mail was read.  mtime is the time the most recent
01054                  *   message arrived; atime is either the time the oldest
01055                  *   unread message arrived, or the last time the mail
01056                  *   was read.
01057                  */
01058                 printf("New mail received ");
01059                 timestr = ctime(&buf.st_mtime); /* time last modified */
01060                 timestr[24] = '\0';             /* suppress newline (ugh) */
01061                 printf(timestr);
01062                 printf(";\n  unread since ");
01063                 printf(ctime(&buf.st_atime));   /* time last accessed */
01064             }
01065         }
01066         
01067         free(mbxpath);
01068 }
01069 
01070 /*
01071  * return true iff we've already printed project/plan for this uid;
01072  * if not, enter this uid into table (so this function has a side-effect.)
01073  */
01074 #define PPMAX   200             /* assume no more than 200 logged-in users */
01075 int     PlanPrinted[PPMAX+1];
01076 int     PPIndex = 0;            /* index of next unused table entry */
01077 
01078 static int
01079 AlreadyPrinted(uid)
01080 int uid;
01081 {
01082         int i = 0;
01083         
01084         while (i++ < PPIndex) {
01085             if (PlanPrinted[i] == uid)
01086                 return(1);
01087         }
01088         if (i < PPMAX) {
01089             PlanPrinted[i] = uid;
01090             PPIndex++;
01091         }
01092         return(0);
01093 }

Generated on Fri Apr 14 22:57:06 2006 for minix by  doxygen 1.4.6