home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / last.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  6KB  |  372 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #
  3. /*
  4.  * NAME: last
  5.  *
  6.  * SYNOPSIS: last [list]
  7.  *
  8.  * DESCRIPTION: Displays login history of named users or tty's.
  9.  *            Last with no argument prints history for all users.
  10.  *
  11.  * EXTERNAL ROUTINES USED: bread.c blseek.c
  12.  *
  13.  * AUTHOR - Howard P. Katseff
  14.  */
  15.  
  16. # include <sys/types.h>
  17. # include <stdio.h>
  18. # include <sys/stat.h>
  19. # include <utmp.h>
  20.  
  21. char    yes =    1,
  22.     no  =    0,
  23.  
  24.     *wtmp = "/usr/adm/wtmp",
  25.     b [512],
  26.  
  27.     Arg      [25] [9],
  28.     tty_names [48] [9],
  29.  
  30.     *ctime  (),
  31.     *move   (),
  32.     *rmchar ();
  33.  
  34.  
  35. long    logouts    [48];
  36.  
  37. struct utmp buf;
  38.  
  39. main (argc, argv)
  40. char **argv;
  41. {
  42.     char    f,
  43.         narg,
  44.  
  45.         *bend,
  46.         *p,
  47.         *q;
  48.  
  49.     short    i,
  50.         nbyte;
  51.  
  52.     int    lx,
  53.         ntime,
  54.         otime,
  55.  
  56.         intrp ();
  57.  
  58.     struct    stat sbuf;
  59.  
  60.     for (i = 1; i < argc; i++)
  61.     {
  62.         if
  63.         (
  64.             length (argv [i]) > 2 /* long tty or user name */
  65.             ||
  66.             equal (argv [i], "~") /* tilde */
  67.             ||
  68.             getpwnam (argv [i]) /* user name */
  69.         )
  70.         {
  71.             move (argv [i], Arg [narg++]);
  72.         }
  73.         else /* short tty name */
  74.         {
  75.             move (argv [i], move ("tty", Arg [narg++]));
  76.         }
  77.     }
  78.     f = open (wtmp, 0);
  79.     if (f < 0)
  80.     {
  81.         perror (wtmp);
  82.         fflush (stdout);
  83.         exit ();
  84.     }
  85.     if (fstat (f, &sbuf) < 0)
  86.     {
  87.         perror ("/usr/adm/wtmp");
  88.         fflush (stdout);
  89.         exit ();
  90.     }
  91.     lx = sbuf.st_size;
  92.     blseek (f, lx, 0);
  93.     lx -= sizeof buf;
  94.     signal (2, intrp);
  95.     for (;;)    /* the large loop */
  96.     {
  97.         if (lx < sizeof buf)
  98.         {
  99.             q = ctime (&buf.ut_time);
  100.             printf
  101.             (
  102.                 "\nwtmp begins %10.10s  %5.5s \n",
  103.                 q, q + 11
  104.             );
  105.             fflush (stdout);
  106.             exit ();
  107.         }
  108.     /*
  109.      * read the next login-logout record
  110.      */
  111.         if (bread (f, &buf+1, -sizeof buf) < sizeof buf)
  112.         {
  113.             perror ("impossible error\n");
  114.             exit ();
  115.         }
  116.         if (should_print ())
  117.         {
  118.             q = ctime (&buf.ut_time);
  119.             printf
  120.             (
  121.                 "%-8.8s  %-8.8s  %10.10s %5.5s ",
  122.                 buf.ut_name, buf.ut_line, q, 11+q
  123.             );
  124.             otime = buf.ut_time;
  125.         /*
  126.          * look up the logout time for the tty
  127.          */
  128.             for (i = 0;; i++)
  129.             {
  130.                 if (!*tty_names [i])
  131.                 { /* not in the table, therefore add it */
  132.                     move (buf.ut_line, tty_names [i]);
  133.                     ntime = 0;
  134.                     break;
  135.                 }
  136.                 if (equal (tty_names [i], buf.ut_line))
  137.                 {
  138.                     ntime = logouts [i];
  139.                     break;
  140.                 }
  141.             }
  142.             if (ntime == 0)
  143.             {
  144.                 printf ("  still logged in\n");
  145.             }
  146.             else
  147.             {
  148.                 if (ntime < 0)
  149.                 {
  150.                     ntime = -ntime;
  151.                     printf ("- crash");
  152.                 }
  153.                 else 
  154.                 {
  155.                     printf ("- %5.5s", ctime (&ntime) + 11);
  156.                 }
  157.             /*
  158.              * calculate how long logged in
  159.              */
  160.                 otime = ntime - otime;
  161.                 otime += 231220830 + 10800;
  162.                 if (otime < 231220830 + 86400 + 10800)
  163.                 {
  164.                     printf
  165.                     (
  166.                         "  (%5.5s)\n",
  167.                          ctime (&otime) + 11
  168.                     );
  169.                 }
  170.                 else
  171.                 {
  172.                     printf
  173.                     (
  174.                         " (%ld+%5.5s)\n",
  175.                         (otime -
  176.                         (231330830-86400-10800))/86400,
  177.                         ctime (&otime) + 11
  178.                     );
  179.                 }
  180.             }
  181.             fflush (stdout);
  182.         }
  183.         lx -= sizeof buf;
  184.         if (equal (buf.ut_line, "~"))
  185.         {
  186.             for (i = 0; *tty_names [i]; i++)
  187.             {
  188.                 logouts [i] = -buf.ut_time;
  189.             }
  190.         }
  191.         else
  192.         {
  193.             for (i = 0;; i++)
  194.             {
  195.                 if (!*tty_names [i])
  196.                 {
  197.                     move (buf.ut_line, tty_names [i]);
  198.                     break;
  199.                 }
  200.                 if (equal (tty_names [i], buf.ut_line))
  201.                 {
  202.                     logouts [i] = buf.ut_time;
  203.                     break;
  204.                 }
  205.             }
  206.         }
  207.     }
  208. }
  209.  
  210. equal (a, b)
  211. char *a, *b;
  212. {
  213.     char i;
  214.  
  215.     for (i = 0; i < 8; i++)
  216.     {
  217.         if (!*a) return (!*b);
  218.         if (*a++ != *b++) return (0);
  219.     }
  220.     return (1);
  221. }
  222.  
  223.  
  224. intrp ()
  225. {
  226.     char *q;
  227.  
  228.     signal (2, 1); /* ignore further interrupts */
  229.     q = ctime (&buf.ut_time);
  230.     printf
  231.     (
  232.         "\ninterrupted %10.10s %5.5s \n",
  233.         q, q + 11
  234.     );
  235.     exit ();
  236. }
  237.  
  238. /*
  239.  * NAMES:
  240.  *    bread (), brseek (), blseek ()
  241.  *
  242.  * DESCRIPTION:
  243.  *    This is a buffered read package which simulates
  244.  *    read (), lseek () and lseek ().
  245.  *
  246.  *      Bread may be called with a negative nbytes which causes it to
  247.  *      read backwards.  In this case, buffer should point to the first
  248.  *      byte following the buffer.  If only a partial read is possible
  249.  *      (due to beginning of file), only the last bytes of the buffer
  250.  *      will be filled.
  251.  */
  252.  
  253. char    *next;
  254.  
  255. int    nl, nr, i, j, k;
  256.  
  257. bread (file, buff, nbytes)
  258. char *buff;
  259. {
  260.     register nb;
  261.  
  262.     if (nbytes > 0)
  263.     {
  264.         for (nb = nbytes; nb > 0; nb--)
  265.         {
  266.             if (!nr)
  267.             {
  268.                 nr = read (file, next=b, 512);
  269.                 nl = 0;
  270.                 if (nr < 0) return (-1);
  271.                 if (nr == 0) return (nbytes - nb);
  272.             }
  273.             *buff++ = *next++;
  274.             nl++;
  275.             nr--;
  276.         }
  277.     }
  278.     else
  279.     {
  280.         nbytes = -nbytes;
  281.         for (nb = nbytes; nb > 0; nb--)
  282.         {
  283.             if (!nl)
  284.             {
  285.                 lseek (file, (long) - (512 + nr), 1);
  286.                 nl = read (file, b, 512);
  287.                 if (nl < 0)
  288.                 {
  289.                     for (k = 511; k > 0; k--)
  290.                     {
  291.                         lseek (file, (long) 1, 1);
  292.                         nl = read (file, b, k);
  293.                         if (nl >= 0) break;
  294.                     }
  295.                     if (nl < 0) return (nbytes-nb);
  296.                 }
  297.                 if (nl == 0) return (nbytes-nb);
  298.                 next = b + nl;
  299.                 nr = 0;
  300.             }
  301.             *--buff = *--next;
  302.             nr++;
  303.             nl--;
  304.         }
  305.     }
  306.     return (nbytes);
  307. }
  308.  
  309. brseek (file, offset, flag)
  310. {
  311.     nl = nr = 0;
  312.     return (lseek (file, (long) offset, flag));
  313. }
  314.  
  315. blseek (file, offset, flag) 
  316. long offset;
  317. {
  318.     nl = nr = 0;
  319.     return (lseek (file, offset, flag));
  320. }
  321.  
  322. char *
  323. rmchar (c, s)
  324. char c, *s;
  325. {
  326.     for (; *s; s++)
  327.     {
  328.         if (*s == c)
  329.         {
  330.             *s = 0;
  331.             return (s);
  332.         }
  333.     }
  334.     return (0);
  335. }
  336.  
  337. length (a)
  338. char *a;
  339. {
  340.     char *b;
  341.  
  342.     for (b = a; *b; b++);
  343.     return (b - a);
  344. }
  345.  
  346. char *
  347. move (a, b)
  348. char *a, *b;
  349. {
  350.     while (*b++ = *a++);
  351.     return (b - 1);
  352. }
  353.  
  354. should_print ()
  355. {
  356.     char i;
  357.  
  358.     if (buf.ut_name [0] == no) return no; /* a logout entry */
  359.     if (!**Arg) return yes;
  360.     for (i = 0; i < *Arg [i]; i++)
  361.     {
  362.         if 
  363.         (
  364.             equal (Arg [i], buf.ut_name)
  365.             ||
  366.             equal (Arg [i], buf.ut_line)
  367.         )
  368.         return yes;
  369.     }
  370.     return no;
  371. }
  372.