|
|
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(ACOMPAT, 'C'); ! 98: BIT(ACORE, 'D'); ! 99: BIT(AXSIG, 'X'); ! 100: flags[i] = '\0'; ! 101: return (flags); ! 102: } ! 103: ! 104: ok(argc, argv, acp) ! 105: register int argc; ! 106: register char *argv[]; ! 107: register struct acct *acp; ! 108: { ! 109: register int j; ! 110: ! 111: for (j = 1; j < argc; j++) ! 112: if (strcmp(getname(acp->ac_uid), argv[j]) && ! 113: strcmp(getdev(acp->ac_tty), argv[j]) && ! 114: strcmp(acp->ac_comm, argv[j])) ! 115: break; ! 116: return (j == argc); ! 117: } ! 118: ! 119: /* should be done with nameserver or database */ ! 120: ! 121: struct utmp utmp; ! 122: ! 123: #define NUID 2048 ! 124: #define NMAX (sizeof (utmp.ut_name)) ! 125: ! 126: char names[NUID][NMAX+1]; ! 127: char outrangename[NMAX+1]; ! 128: int outrangeuid = -1; ! 129: ! 130: char * ! 131: getname(uid) ! 132: { ! 133: register struct passwd *pw; ! 134: static init; ! 135: struct passwd *getpwent(); ! 136: ! 137: if (uid >= 0 && uid < NUID && names[uid][0]) ! 138: return (&names[uid][0]); ! 139: if (uid >= 0 && uid == outrangeuid) ! 140: return (outrangename); ! 141: if (init == 2) { ! 142: if (uid < NUID) ! 143: return (0); ! 144: setpwent(); ! 145: while (pw = getpwent()) { ! 146: if (pw->pw_uid != uid) ! 147: continue; ! 148: outrangeuid = pw->pw_uid; ! 149: strncpy(outrangename, pw->pw_name, NMAX); ! 150: endpwent(); ! 151: return (outrangename); ! 152: } ! 153: endpwent(); ! 154: return (0); ! 155: } ! 156: if (init == 0) ! 157: setpwent(), init = 1; ! 158: while (pw = getpwent()) { ! 159: if (pw->pw_uid < 0 || pw->pw_uid >= NUID) { ! 160: if (pw->pw_uid == uid) { ! 161: outrangeuid = pw->pw_uid; ! 162: strncpy(outrangename, pw->pw_name, NMAX); ! 163: return (outrangename); ! 164: } ! 165: continue; ! 166: } ! 167: if (names[pw->pw_uid][0]) ! 168: continue; ! 169: strncpy(names[pw->pw_uid], pw->pw_name, NMAX); ! 170: if (pw->pw_uid == uid) ! 171: return (&names[uid][0]); ! 172: } ! 173: init = 2; ! 174: endpwent(); ! 175: return (0); ! 176: } ! 177: ! 178: #include <sys/dir.h> ! 179: ! 180: #define N_DEVS 43 /* hash value for device names */ ! 181: #define NDEVS 500 /* max number of file names in /dev */ ! 182: ! 183: struct devhash { ! 184: dev_t dev_dev; ! 185: char dev_name [fldsiz(utmp, ut_line) + 1]; ! 186: struct devhash * dev_nxt; ! 187: }; ! 188: struct devhash *dev_hash[N_DEVS]; ! 189: struct devhash *dev_chain; ! 190: #define HASH(d) (((int) d) % N_DEVS) ! 191: ! 192: setupdevs() ! 193: { ! 194: register DIR * fd; ! 195: register struct devhash * hashtab; ! 196: register ndevs = NDEVS; ! 197: struct direct * dp; ! 198: ! 199: if ((fd = opendir("/dev")) == NULL) { ! 200: perror("/dev"); ! 201: return; ! 202: } ! 203: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)); ! 204: if (hashtab == (struct devhash *)0) { ! 205: fprintf(stderr, "No mem for dev table\n"); ! 206: closedir(fd); ! 207: return; ! 208: } ! 209: while (dp = readdir(fd)) { ! 210: if (dp->d_ino == 0) ! 211: continue; ! 212: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console")) ! 213: continue; ! 214: strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line)); ! 215: hashtab->dev_name[fldsiz(utmp, ut_line)] = 0; ! 216: hashtab->dev_nxt = dev_chain; ! 217: dev_chain = hashtab; ! 218: hashtab++; ! 219: if (--ndevs <= 0) ! 220: break; ! 221: } ! 222: closedir(fd); ! 223: } ! 224: ! 225: char * ! 226: getdev(dev) ! 227: dev_t dev; ! 228: { ! 229: register struct devhash *hp, *nhp; ! 230: struct stat statb; ! 231: char name[fldsiz(devhash, dev_name) + 6]; ! 232: static dev_t lastdev = (dev_t) -1; ! 233: static char *lastname; ! 234: static int init = 0; ! 235: ! 236: if (dev == NODEV) ! 237: return ("__"); ! 238: if (dev == lastdev) ! 239: return (lastname); ! 240: if (!init) { ! 241: setupdevs(); ! 242: init++; ! 243: } ! 244: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt) ! 245: if (hp->dev_dev == dev) { ! 246: lastdev = dev; ! 247: return (lastname = hp->dev_name); ! 248: } ! 249: for (hp = dev_chain; hp; hp = nhp) { ! 250: nhp = hp->dev_nxt; ! 251: strcpy(name, "/dev/"); ! 252: strcat(name, hp->dev_name); ! 253: if (stat(name, &statb) < 0) /* name truncated usually */ ! 254: continue; ! 255: if ((statb.st_mode & S_IFMT) != S_IFCHR) ! 256: continue; ! 257: hp->dev_dev = statb.st_rdev; ! 258: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)]; ! 259: dev_hash[HASH(hp->dev_dev)] = hp; ! 260: if (hp->dev_dev == dev) { ! 261: dev_chain = nhp; ! 262: lastdev = dev; ! 263: return (lastname = hp->dev_name); ! 264: } ! 265: } ! 266: dev_chain = (struct devhash *) 0; ! 267: return ("??"); ! 268: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.