1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)lastcomm.c	5.2 (Berkeley) 5/4/86";
  15: #endif not lint
  16: 
  17: /*
  18:  * last command
  19:  */
  20: #include <sys/param.h>
  21: #include <sys/acct.h>
  22: #include <sys/file.h>
  23: 
  24: #include <stdio.h>
  25: #include <pwd.h>
  26: #include <sys/stat.h>
  27: #include <utmp.h>
  28: #include <struct.h>
  29: #include <ctype.h>
  30: 
  31: struct  acct buf[DEV_BSIZE / sizeof (struct acct)];
  32: 
  33: time_t  expand();
  34: char    *flagbits();
  35: char    *getname();
  36: char    *getdev();
  37: 
  38: main(argc, argv)
  39:     char *argv[];
  40: {
  41:     register int bn, cc;
  42:     register struct acct *acp;
  43:     int fd;
  44:     struct stat sb;
  45: 
  46:     fd = open("/usr/adm/acct", O_RDONLY);
  47:     if (fd < 0) {
  48:         perror("/usr/adm/acct");
  49:         exit(1);
  50:     }
  51:     fstat(fd, &sb);
  52:     for (bn = btodb(sb.st_size); bn >= 0; bn--) {
  53:         lseek(fd, dbtob(bn), L_SET);
  54:         cc = read(fd, buf, DEV_BSIZE);
  55:         if (cc < 0) {
  56:             perror("read");
  57:             break;
  58:         }
  59:         acp = buf + (cc / sizeof (buf[0])) - 1;
  60:         for (; acp >= buf; acp--) {
  61:             register char *cp;
  62:             time_t x;
  63: 
  64:             if (acp->ac_comm[0] == '\0')
  65:                 strcpy(acp->ac_comm, "?");
  66:             for (cp = &acp->ac_comm[0];
  67:                  cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp;
  68:                  cp++)
  69:                 if (!isascii(*cp) || iscntrl(*cp))
  70:                     *cp = '?';
  71:             if (argc > 1 && !ok(argc, argv, acp))
  72:                 continue;
  73:             x = expand(acp->ac_utime) + expand(acp->ac_stime);
  74:             printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n",
  75:                 fldsiz(acct, ac_comm), fldsiz(acct, ac_comm),
  76:                 acp->ac_comm,
  77:                 flagbits(acp->ac_flag),
  78:                 fldsiz(utmp, ut_name), getname(acp->ac_uid),
  79:                 fldsiz(utmp, ut_line), getdev(acp->ac_tty),
  80:                 x / (double)AHZ, ctime(&acp->ac_btime));
  81:         }
  82:     }
  83: }
  84: 
  85: time_t
  86: expand (t)
  87:     unsigned t;
  88: {
  89:     register time_t nt;
  90: 
  91:     nt = t & 017777;
  92:     t >>= 13;
  93:     while (t) {
  94:         t--;
  95:         nt <<= 3;
  96:     }
  97:     return (nt);
  98: }
  99: 
 100: char *
 101: flagbits(f)
 102:     register int f;
 103: {
 104:     register int i = 0;
 105:     static char flags[20];
 106: 
 107: #define BIT(flag, ch)   flags[i++] = (f & flag) ? ch : ' '
 108:     BIT(ASU, 'S');
 109:     BIT(AFORK, 'F');
 110:     BIT(ACOMPAT, 'C');
 111:     BIT(ACORE, 'D');
 112:     BIT(AXSIG, 'X');
 113:     flags[i] = '\0';
 114:     return (flags);
 115: }
 116: 
 117: ok(argc, argv, acp)
 118:     register int argc;
 119:     register char *argv[];
 120:     register struct acct *acp;
 121: {
 122:     register int j;
 123: 
 124:     for (j = 1; j < argc; j++)
 125:         if (strcmp(getname(acp->ac_uid), argv[j]) &&
 126:             strcmp(getdev(acp->ac_tty), argv[j]) &&
 127:             strncmp(acp->ac_comm, argv[j], fldsiz(acct, ac_comm)))
 128:             break;
 129:     return (j == argc);
 130: }
 131: 
 132: /* should be done with nameserver or database */
 133: 
 134: struct  utmp utmp;
 135: 
 136: #define NUID    2048
 137: #define NMAX    (sizeof (utmp.ut_name))
 138: 
 139: char    names[NUID][NMAX+1];
 140: char    outrangename[NMAX+1];
 141: int outrangeuid = -1;
 142: 
 143: char *
 144: getname(uid)
 145: {
 146:     register struct passwd *pw;
 147:     static init;
 148:     struct passwd *getpwent();
 149: 
 150:     if (uid >= 0 && uid < NUID && names[uid][0])
 151:         return (&names[uid][0]);
 152:     if (uid >= 0 && uid == outrangeuid)
 153:         return (outrangename);
 154:     if (init == 2) {
 155:         if (uid < NUID)
 156:             return (0);
 157:         setpwent();
 158:         while (pw = getpwent()) {
 159:             if (pw->pw_uid != uid)
 160:                 continue;
 161:             outrangeuid = pw->pw_uid;
 162:             strncpy(outrangename, pw->pw_name, NMAX);
 163:             endpwent();
 164:             return (outrangename);
 165:         }
 166:         endpwent();
 167:         return (0);
 168:     }
 169:     if (init == 0)
 170:         setpwent(), init = 1;
 171:     while (pw = getpwent()) {
 172:         if (pw->pw_uid < 0 || pw->pw_uid >= NUID) {
 173:             if (pw->pw_uid == uid) {
 174:                 outrangeuid = pw->pw_uid;
 175:                 strncpy(outrangename, pw->pw_name, NMAX);
 176:                 return (outrangename);
 177:             }
 178:             continue;
 179:         }
 180:         if (names[pw->pw_uid][0])
 181:             continue;
 182:         strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
 183:         if (pw->pw_uid == uid)
 184:             return (&names[uid][0]);
 185:     }
 186:     init = 2;
 187:     endpwent();
 188:     return (0);
 189: }
 190: 
 191: #include <sys/dir.h>
 192: 
 193: #define N_DEVS      43      /* hash value for device names */
 194: #define NDEVS       500     /* max number of file names in /dev */
 195: 
 196: struct  devhash {
 197:     dev_t   dev_dev;
 198:     char    dev_name [fldsiz(utmp, ut_line) + 1];
 199:     struct  devhash * dev_nxt;
 200: };
 201: struct  devhash *dev_hash[N_DEVS];
 202: struct  devhash *dev_chain;
 203: #define HASH(d) (((int) d) % N_DEVS)
 204: 
 205: setupdevs()
 206: {
 207:     register DIR * fd;
 208:     register struct devhash * hashtab;
 209:     register ndevs = NDEVS;
 210:     struct direct * dp;
 211: 
 212:     if ((fd = opendir("/dev")) == NULL) {
 213:         perror("/dev");
 214:         return;
 215:     }
 216:     hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
 217:     if (hashtab == (struct devhash *)0) {
 218:         fprintf(stderr, "No mem for dev table\n");
 219:         closedir(fd);
 220:         return;
 221:     }
 222:     while (dp = readdir(fd)) {
 223:         if (dp->d_ino == 0)
 224:             continue;
 225:         if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
 226:             continue;
 227:         strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
 228:         hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
 229:         hashtab->dev_nxt = dev_chain;
 230:         dev_chain = hashtab;
 231:         hashtab++;
 232:         if (--ndevs <= 0)
 233:             break;
 234:     }
 235:     closedir(fd);
 236: }
 237: 
 238: char *
 239: getdev(dev)
 240:     dev_t dev;
 241: {
 242:     register struct devhash *hp, *nhp;
 243:     struct stat statb;
 244:     char name[fldsiz(devhash, dev_name) + 6];
 245:     static dev_t lastdev = (dev_t) -1;
 246:     static char *lastname;
 247:     static int init = 0;
 248: 
 249:     if (dev == NODEV)
 250:         return ("__");
 251:     if (dev == lastdev)
 252:         return (lastname);
 253:     if (!init) {
 254:         setupdevs();
 255:         init++;
 256:     }
 257:     for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
 258:         if (hp->dev_dev == dev) {
 259:             lastdev = dev;
 260:             return (lastname = hp->dev_name);
 261:         }
 262:     for (hp = dev_chain; hp; hp = nhp) {
 263:         nhp = hp->dev_nxt;
 264:         strcpy(name, "/dev/");
 265:         strcat(name, hp->dev_name);
 266:         if (stat(name, &statb) < 0) /* name truncated usually */
 267:             continue;
 268:         if ((statb.st_mode & S_IFMT) != S_IFCHR)
 269:             continue;
 270:         hp->dev_dev = statb.st_rdev;
 271:         hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
 272:         dev_hash[HASH(hp->dev_dev)] = hp;
 273:         if (hp->dev_dev == dev) {
 274:             dev_chain = nhp;
 275:             lastdev = dev;
 276:             return (lastname = hp->dev_name);
 277:         }
 278:     }
 279:     dev_chain = (struct devhash *) 0;
 280:     return ("??");
 281: }

Defined functions

expand defined in line 85; used 3 times
flagbits defined in line 100; used 2 times
getdev defined in line 238; used 3 times
getname defined in line 143; used 3 times
main defined in line 38; never used
ok defined in line 117; used 1 times
  • in line 71
setupdevs defined in line 205; used 1 times

Defined variables

buf defined in line 31; used 4 times
copyright defined in line 8; never used
dev_chain defined in line 202; used 5 times
dev_hash defined in line 201; used 3 times
names defined in line 139; used 5 times
outrangename defined in line 140; used 5 times
outrangeuid defined in line 141; used 3 times
sccsid defined in line 14; never used
utmp defined in line 134; used 6 times

Defined struct's

devhash defined in line 196; used 18 times

Defined macros

BIT defined in line 107; used 5 times
HASH defined in line 203; used 3 times
NDEVS defined in line 194; used 2 times
NMAX defined in line 137; used 5 times
NUID defined in line 136; used 4 times
N_DEVS defined in line 193; used 2 times
Last modified: 1986-05-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1725
Valid CSS Valid XHTML 1.0 Strict