|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.