|
|
1.1 ! root 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 are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: char copyright[] = ! 20: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 21: All rights reserved.\n"; ! 22: #endif /* not lint */ ! 23: ! 24: #ifndef lint ! 25: static char sccsid[] = "@(#)lastcomm.c 5.6 (Berkeley) 6/29/88"; ! 26: #endif /* not lint */ ! 27: ! 28: /* ! 29: * last command ! 30: */ ! 31: #include <sys/param.h> ! 32: #include <sys/acct.h> ! 33: #include <sys/file.h> ! 34: #include <sys/stat.h> ! 35: #include <utmp.h> ! 36: #include <struct.h> ! 37: #include <ctype.h> ! 38: #include <stdio.h> ! 39: ! 40: struct acct buf[DEV_BSIZE / sizeof (struct acct)]; ! 41: ! 42: time_t expand(); ! 43: char *flagbits(); ! 44: char *getname(); ! 45: char *getdev(); ! 46: ! 47: main(argc, argv) ! 48: int argc; ! 49: char *argv[]; ! 50: { ! 51: extern int optind; ! 52: extern char *optarg; ! 53: register struct acct *acp; ! 54: register int bn, cc; ! 55: struct stat sb; ! 56: int ch, fd; ! 57: char *acctfile, *strcpy(), *ctime(); ! 58: long lseek(); ! 59: ! 60: acctfile = NULL; ! 61: while ((ch = getopt(argc, argv, "f:")) != EOF) ! 62: switch((char)ch) { ! 63: case 'f': ! 64: acctfile = optarg; ! 65: break; ! 66: case '?': ! 67: default: ! 68: fputs("lastcomm [ -f file ]\n", stderr); ! 69: exit(1); ! 70: } ! 71: argv += optind; ! 72: if (!acctfile) ! 73: acctfile = "/usr/adm/acct"; ! 74: fd = open(acctfile, O_RDONLY); ! 75: if (fd < 0) { ! 76: perror(acctfile); ! 77: exit(1); ! 78: } ! 79: (void)fstat(fd, &sb); ! 80: for (bn = btodb(sb.st_size); bn >= 0; bn--) { ! 81: (void)lseek(fd, (off_t)dbtob(bn), L_SET); ! 82: cc = read(fd, buf, DEV_BSIZE); ! 83: if (cc < 0) { ! 84: perror("read"); ! 85: break; ! 86: } ! 87: acp = buf + (cc / sizeof (buf[0])) - 1; ! 88: for (; acp >= buf; acp--) { ! 89: register char *cp; ! 90: time_t x; ! 91: ! 92: if (acp->ac_comm[0] == '\0') ! 93: (void)strcpy(acp->ac_comm, "?"); ! 94: for (cp = &acp->ac_comm[0]; ! 95: cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp; ! 96: cp++) ! 97: if (!isascii(*cp) || iscntrl(*cp)) ! 98: *cp = '?'; ! 99: if (*argv && !ok(argv, acp)) ! 100: continue; ! 101: x = expand(acp->ac_utime) + expand(acp->ac_stime); ! 102: printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n", ! 103: fldsiz(acct, ac_comm), ! 104: fldsiz(acct, ac_comm), ! 105: acp->ac_comm, flagbits(acp->ac_flag), ! 106: fldsiz(utmp, ut_name), ! 107: (cp = getname(acp->ac_uid)) ? cp : "", ! 108: fldsiz(utmp, ut_line), getdev(acp->ac_tty), ! 109: x / (double)AHZ, ctime(&acp->ac_btime)); ! 110: } ! 111: } ! 112: } ! 113: ! 114: time_t ! 115: expand (t) ! 116: unsigned t; ! 117: { ! 118: register time_t nt; ! 119: ! 120: nt = t & 017777; ! 121: t >>= 13; ! 122: while (t) { ! 123: t--; ! 124: nt <<= 3; ! 125: } ! 126: return (nt); ! 127: } ! 128: ! 129: char * ! 130: flagbits(f) ! 131: register int f; ! 132: { ! 133: static char flags[20]; ! 134: char *p, *strcpy(); ! 135: ! 136: #define BIT(flag, ch) if (f & flag) *p++ = ch; ! 137: p = strcpy(flags, "- "); ! 138: BIT(ASU, 'S'); ! 139: BIT(AFORK, 'F'); ! 140: BIT(ACOMPAT, 'C'); ! 141: BIT(ACORE, 'D'); ! 142: BIT(AXSIG, 'X'); ! 143: return (flags); ! 144: } ! 145: ! 146: ok(argv, acp) ! 147: register char *argv[]; ! 148: register struct acct *acp; ! 149: { ! 150: register char *cp; ! 151: ! 152: do { ! 153: if ((cp = getname(acp->ac_uid)) && !strcmp(cp, *argv) || ! 154: (cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv) || ! 155: !strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm))) ! 156: return(1); ! 157: } while (*++argv); ! 158: return(0); ! 159: } ! 160: ! 161: /* should be done with nameserver or database */ ! 162: ! 163: #include <pwd.h> ! 164: ! 165: struct utmp utmp; ! 166: #define NMAX (sizeof (utmp.ut_name)) ! 167: #define SCPYN(a, b) strncpy(a, b, NMAX) ! 168: ! 169: #define NCACHE 64 /* power of 2 */ ! 170: #define CAMASK NCACHE - 1 ! 171: ! 172: char * ! 173: getname(uid) ! 174: uid_t uid; ! 175: { ! 176: extern int _pw_stayopen; ! 177: static struct ncache { ! 178: uid_t uid; ! 179: char name[NMAX+1]; ! 180: } c_uid[NCACHE]; ! 181: register struct passwd *pw; ! 182: register struct ncache *cp; ! 183: ! 184: _pw_stayopen = 1; ! 185: cp = c_uid + (uid & CAMASK); ! 186: if (cp->uid == uid && *cp->name) ! 187: return(cp->name); ! 188: if (!(pw = getpwuid(uid))) ! 189: return((char *)0); ! 190: cp->uid = uid; ! 191: SCPYN(cp->name, pw->pw_name); ! 192: return(cp->name); ! 193: } ! 194: ! 195: #include <sys/dir.h> ! 196: ! 197: #define N_DEVS 43 /* hash value for device names */ ! 198: #define NDEVS 500 /* max number of file names in /dev */ ! 199: ! 200: struct devhash { ! 201: dev_t dev_dev; ! 202: char dev_name [fldsiz(utmp, ut_line) + 1]; ! 203: struct devhash * dev_nxt; ! 204: }; ! 205: struct devhash *dev_hash[N_DEVS]; ! 206: struct devhash *dev_chain; ! 207: #define HASH(d) (((int) d) % N_DEVS) ! 208: ! 209: setupdevs() ! 210: { ! 211: register DIR * fd; ! 212: register struct devhash * hashtab; ! 213: register ndevs = NDEVS; ! 214: struct direct * dp; ! 215: char *malloc(); ! 216: ! 217: /*NOSTRICT*/ ! 218: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)); ! 219: if (hashtab == (struct devhash *)0) { ! 220: fputs("No mem for dev table\n", stderr); ! 221: return; ! 222: } ! 223: if ((fd = opendir("/dev")) == NULL) { ! 224: perror("/dev"); ! 225: return; ! 226: } ! 227: while (dp = readdir(fd)) { ! 228: if (dp->d_ino == 0) ! 229: continue; ! 230: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console")) ! 231: continue; ! 232: strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line)); ! 233: hashtab->dev_name[fldsiz(utmp, ut_line)] = 0; ! 234: hashtab->dev_nxt = dev_chain; ! 235: dev_chain = hashtab; ! 236: hashtab++; ! 237: if (--ndevs <= 0) ! 238: break; ! 239: } ! 240: closedir(fd); ! 241: } ! 242: ! 243: char * ! 244: getdev(dev) ! 245: dev_t dev; ! 246: { ! 247: register struct devhash *hp, *nhp; ! 248: struct stat statb; ! 249: char name[fldsiz(devhash, dev_name) + 6]; ! 250: static dev_t lastdev = (dev_t) -1; ! 251: static char *lastname; ! 252: static int init = 0; ! 253: char *strcpy(), *strcat(); ! 254: ! 255: if (dev == NODEV) ! 256: return ("__"); ! 257: if (dev == lastdev) ! 258: return (lastname); ! 259: if (!init) { ! 260: setupdevs(); ! 261: init++; ! 262: } ! 263: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt) ! 264: if (hp->dev_dev == dev) { ! 265: lastdev = dev; ! 266: return (lastname = hp->dev_name); ! 267: } ! 268: for (hp = dev_chain; hp; hp = nhp) { ! 269: nhp = hp->dev_nxt; ! 270: strcpy(name, "/dev/"); ! 271: strcat(name, hp->dev_name); ! 272: if (stat(name, &statb) < 0) /* name truncated usually */ ! 273: continue; ! 274: if ((statb.st_mode & S_IFMT) != S_IFCHR) ! 275: continue; ! 276: hp->dev_dev = statb.st_rdev; ! 277: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)]; ! 278: dev_hash[HASH(hp->dev_dev)] = hp; ! 279: if (hp->dev_dev == dev) { ! 280: dev_chain = nhp; ! 281: lastdev = dev; ! 282: return (lastname = hp->dev_name); ! 283: } ! 284: } ! 285: dev_chain = (struct devhash *) 0; ! 286: return ("??"); ! 287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.