home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / lastcomm / lastcomm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-17  |  6.6 KB  |  272 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)lastcomm.c    5.11 (Berkeley) 6/1/90";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * last command
  46.  */
  47. #include <sys/param.h>
  48. #include <sys/acct.h>
  49. #include <sys/file.h>
  50. #include <sys/stat.h>
  51. #include <utmp.h>
  52. #include <struct.h>
  53. #include <ctype.h>
  54. #include <stdio.h>
  55. #include "pathnames.h"
  56.  
  57. struct    acct buf[DEV_BSIZE / sizeof (struct acct)];
  58.  
  59. time_t    expand();
  60. char    *flagbits();
  61. char    *getdev();
  62.  
  63. main(argc, argv)
  64.     int argc;
  65.     char *argv[];
  66. {
  67.     extern int optind;
  68.     extern char *optarg;
  69.     register struct acct *acp;
  70.     register int bn, cc;
  71.     struct stat sb;
  72.     int ch, fd;
  73.     char *acctfile, *ctime(), *strcpy(), *user_from_uid();
  74.     long lseek();
  75.  
  76.     acctfile = _PATH_ACCT;
  77.     while ((ch = getopt(argc, argv, "f:")) != EOF)
  78.         switch((char)ch) {
  79.         case 'f':
  80.             acctfile = optarg;
  81.             break;
  82.         case '?':
  83.         default:
  84.             fputs("lastcomm [ -f file ]\n", stderr);
  85.             exit(1);
  86.         }
  87.     argv += optind;
  88.  
  89.     fd = open(acctfile, O_RDONLY);
  90.     if (fd < 0) {
  91.         perror(acctfile);
  92.         exit(1);
  93.     }
  94.     (void)fstat(fd, &sb);
  95.     setpassent(1);
  96.     for (bn = btodb(sb.st_size); bn >= 0; bn--) {
  97.         (void)lseek(fd, (off_t)dbtob(bn), L_SET);
  98.         cc = read(fd, buf, DEV_BSIZE);
  99.         if (cc < 0) {
  100.             perror("read");
  101.             break;
  102.         }
  103.         acp = buf + (cc / sizeof (buf[0])) - 1;
  104.         for (; acp >= buf; acp--) {
  105.             register char *cp;
  106.             time_t x;
  107.  
  108.             if (acp->ac_comm[0] == '\0')
  109.                 (void)strcpy(acp->ac_comm, "?");
  110.             for (cp = &acp->ac_comm[0];
  111.                  cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp;
  112.                  cp++)
  113.                 if (!isascii(*cp) || iscntrl(*cp))
  114.                     *cp = '?';
  115.             if (*argv && !ok(argv, acp))
  116.                 continue;
  117.             x = expand(acp->ac_utime) + expand(acp->ac_stime);
  118.             printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n",
  119.                 fldsiz(acct, ac_comm), fldsiz(acct, ac_comm),
  120.                 acp->ac_comm, flagbits(acp->ac_flag),
  121.                 UT_NAMESIZE, user_from_uid(acp->ac_uid, 0),
  122.                 UT_LINESIZE, getdev(acp->ac_tty),
  123.                 x / (double)AHZ, ctime(&acp->ac_btime));
  124.         }
  125.     }
  126. }
  127.  
  128. time_t
  129. expand (t)
  130.     unsigned t;
  131. {
  132.     register time_t nt;
  133.  
  134.     nt = t & 017777;
  135.     t >>= 13;
  136.     while (t) {
  137.         t--;
  138.         nt <<= 3;
  139.     }
  140.     return (nt);
  141. }
  142.  
  143. char *
  144. flagbits(f)
  145.     register int f;
  146. {
  147.     static char flags[20];
  148.     char *p, *strcpy();
  149.  
  150. #define    BIT(flag, ch)    if (f & flag) *p++ = ch;
  151.     p = strcpy(flags, "-    ");
  152.     BIT(ASU, 'S');
  153.     BIT(AFORK, 'F');
  154.     BIT(ACOMPAT, 'C');
  155.     BIT(ACORE, 'D');
  156.     BIT(AXSIG, 'X');
  157.     return (flags);
  158. }
  159.  
  160. ok(argv, acp)
  161.     register char *argv[];
  162.     register struct acct *acp;
  163. {
  164.     register char *cp;
  165.     char *user_from_uid();
  166.  
  167.     do {
  168.         cp = user_from_uid(acp->ac_uid, 0);
  169.         if (!strcmp(cp, *argv)) 
  170.             return(1);
  171.         if ((cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv))
  172.             return(1);
  173.         if (!strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm)))
  174.             return(1);
  175.     } while (*++argv);
  176.     return(0);
  177. }
  178.  
  179. #include <sys/dir.h>
  180.  
  181. #define N_DEVS        43        /* hash value for device names */
  182. #define NDEVS        500        /* max number of file names in /dev */
  183.  
  184. struct    devhash {
  185.     dev_t    dev_dev;
  186.     char    dev_name [UT_LINESIZE + 1];
  187.     struct    devhash * dev_nxt;
  188. };
  189. struct    devhash *dev_hash[N_DEVS];
  190. struct    devhash *dev_chain;
  191. #define HASH(d)    (((int) d) % N_DEVS)
  192.  
  193. setupdevs()
  194. {
  195.     register DIR * fd;
  196.     register struct devhash * hashtab;
  197.     register ndevs = NDEVS;
  198.     struct direct * dp;
  199.     char *malloc();
  200.  
  201.     /*NOSTRICT*/
  202.     hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
  203.     if (hashtab == (struct devhash *)0) {
  204.         fputs("No mem for dev table\n", stderr);
  205.         return;
  206.     }
  207.     if ((fd = opendir(_PATH_DEV)) == NULL) {
  208.         perror(_PATH_DEV);
  209.         return;
  210.     }
  211.     while (dp = readdir(fd)) {
  212.         if (dp->d_ino == 0)
  213.             continue;
  214.         if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
  215.             continue;
  216.         (void)strncpy(hashtab->dev_name, dp->d_name, UT_LINESIZE);
  217.         hashtab->dev_name[UT_LINESIZE] = 0;
  218.         hashtab->dev_nxt = dev_chain;
  219.         dev_chain = hashtab;
  220.         hashtab++;
  221.         if (--ndevs <= 0)
  222.             break;
  223.     }
  224.     closedir(fd);
  225. }
  226.  
  227. char *
  228. getdev(dev)
  229.     dev_t dev;
  230. {
  231.     register struct devhash *hp, *nhp;
  232.     struct stat statb;
  233.     char name[fldsiz(devhash, dev_name) + 6];
  234.     static dev_t lastdev = (dev_t) -1;
  235.     static char *lastname;
  236.     static int init = 0;
  237.     char *strcpy(), *strcat();
  238.  
  239.     if (dev == NODEV)
  240.         return ("__");
  241.     if (dev == lastdev)
  242.         return (lastname);
  243.     if (!init) {
  244.         setupdevs();
  245.         init++;
  246.     }
  247.     for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
  248.         if (hp->dev_dev == dev) {
  249.             lastdev = dev;
  250.             return (lastname = hp->dev_name);
  251.         }
  252.     for (hp = dev_chain; hp; hp = nhp) {
  253.         nhp = hp->dev_nxt;
  254.         (void)strcpy(name, _PATH_DEV);
  255.         strcat(name, hp->dev_name);
  256.         if (stat(name, &statb) < 0)    /* name truncated usually */
  257.             continue;
  258.         if ((statb.st_mode & S_IFMT) != S_IFCHR)
  259.             continue;
  260.         hp->dev_dev = statb.st_rdev;
  261.         hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
  262.         dev_hash[HASH(hp->dev_dev)] = hp;
  263.         if (hp->dev_dev == dev) {
  264.             dev_chain = nhp;
  265.             lastdev = dev;
  266.             return (lastname = hp->dev_name);
  267.         }
  268.     }
  269.     dev_chain = (struct devhash *) 0;
  270.     return ("??");
  271. }
  272.