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