121563Sdist /* 221563Sdist * Copyright (c) 1980 Regents of the University of California. 334033Sbostic * All rights reserved. 434033Sbostic * 5*42735Sbostic * %sccs.include.redist.c% 621563Sdist */ 721563Sdist 811839Ssam #ifndef lint 921563Sdist char copyright[] = 1021563Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1121563Sdist All rights reserved.\n"; 1234033Sbostic #endif /* not lint */ 131037Sbill 1421563Sdist #ifndef lint 15*42735Sbostic static char sccsid[] = "@(#)lastcomm.c 5.11 (Berkeley) 06/01/90"; 1634033Sbostic #endif /* not lint */ 1721563Sdist 181037Sbill /* 191037Sbill * last command 201037Sbill */ 2111839Ssam #include <sys/param.h> 2211839Ssam #include <sys/acct.h> 2313188Ssam #include <sys/file.h> 2413541Ssam #include <sys/stat.h> 2511839Ssam #include <utmp.h> 2611839Ssam #include <struct.h> 2711839Ssam #include <ctype.h> 2834033Sbostic #include <stdio.h> 2937848Sbostic #include "pathnames.h" 301037Sbill 3113188Ssam struct acct buf[DEV_BSIZE / sizeof (struct acct)]; 321037Sbill 3313188Ssam time_t expand(); 3411839Ssam char *flagbits(); 3513188Ssam char *getdev(); 361037Sbill 3711839Ssam main(argc, argv) 3833688Sbostic int argc; 3911839Ssam char *argv[]; 401037Sbill { 4133688Sbostic extern int optind; 4233688Sbostic extern char *optarg; 4333688Sbostic register struct acct *acp; 4413188Ssam register int bn, cc; 4513188Ssam struct stat sb; 4633688Sbostic int ch, fd; 4740266Sbostic char *acctfile, *ctime(), *strcpy(), *user_from_uid(); 4831126Sbostic long lseek(); 491037Sbill 5037848Sbostic acctfile = _PATH_ACCT; 5133688Sbostic while ((ch = getopt(argc, argv, "f:")) != EOF) 5233688Sbostic switch((char)ch) { 5333688Sbostic case 'f': 5433688Sbostic acctfile = optarg; 5533688Sbostic break; 5633688Sbostic case '?': 5733688Sbostic default: 5833688Sbostic fputs("lastcomm [ -f file ]\n", stderr); 5933688Sbostic exit(1); 6033688Sbostic } 6133688Sbostic argv += optind; 6237848Sbostic 6333688Sbostic fd = open(acctfile, O_RDONLY); 6413188Ssam if (fd < 0) { 6533688Sbostic perror(acctfile); 6611839Ssam exit(1); 671037Sbill } 6833688Sbostic (void)fstat(fd, &sb); 6937076Sbostic setpassent(1); 7015634Sralph for (bn = btodb(sb.st_size); bn >= 0; bn--) { 7131126Sbostic (void)lseek(fd, (off_t)dbtob(bn), L_SET); 7213188Ssam cc = read(fd, buf, DEV_BSIZE); 7313188Ssam if (cc < 0) { 7413188Ssam perror("read"); 7513188Ssam break; 7613188Ssam } 7713188Ssam acp = buf + (cc / sizeof (buf[0])) - 1; 7813188Ssam for (; acp >= buf; acp--) { 7913188Ssam register char *cp; 8017764Sralph time_t x; 811037Sbill 8217905Sralph if (acp->ac_comm[0] == '\0') 8333688Sbostic (void)strcpy(acp->ac_comm, "?"); 8417905Sralph for (cp = &acp->ac_comm[0]; 8517905Sralph cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp; 8617905Sralph cp++) 8717905Sralph if (!isascii(*cp) || iscntrl(*cp)) 8813188Ssam *cp = '?'; 8933688Sbostic if (*argv && !ok(argv, acp)) 9011839Ssam continue; 9117764Sralph x = expand(acp->ac_utime) + expand(acp->ac_stime); 9227699Slepreau printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n", 9340266Sbostic fldsiz(acct, ac_comm), fldsiz(acct, ac_comm), 9431126Sbostic acp->ac_comm, flagbits(acp->ac_flag), 9540480Sbostic UT_NAMESIZE, user_from_uid(acp->ac_uid, 0), 9640266Sbostic UT_LINESIZE, getdev(acp->ac_tty), 9717503Skarels x / (double)AHZ, ctime(&acp->ac_btime)); 981037Sbill } 991037Sbill } 1001037Sbill } 1011037Sbill 1021037Sbill time_t 1031037Sbill expand (t) 10411839Ssam unsigned t; 1051037Sbill { 1061037Sbill register time_t nt; 1071037Sbill 1081037Sbill nt = t & 017777; 1091037Sbill t >>= 13; 11011839Ssam while (t) { 1111037Sbill t--; 1121037Sbill nt <<= 3; 1131037Sbill } 1141037Sbill return (nt); 1151037Sbill } 1161037Sbill 1177457Skre char * 1187457Skre flagbits(f) 11911839Ssam register int f; 1201037Sbill { 1217457Skre static char flags[20]; 12234033Sbostic char *p, *strcpy(); 1237457Skre 12434033Sbostic #define BIT(flag, ch) if (f & flag) *p++ = ch; 12534033Sbostic p = strcpy(flags, "- "); 12611839Ssam BIT(ASU, 'S'); 12711839Ssam BIT(AFORK, 'F'); 12811839Ssam BIT(ACOMPAT, 'C'); 12911839Ssam BIT(ACORE, 'D'); 13011839Ssam BIT(AXSIG, 'X'); 13111839Ssam return (flags); 1327457Skre } 1337457Skre 13433688Sbostic ok(argv, acp) 13513188Ssam register char *argv[]; 13613188Ssam register struct acct *acp; 13713188Ssam { 13831126Sbostic register char *cp; 13940266Sbostic char *user_from_uid(); 14013188Ssam 14133688Sbostic do { 14240480Sbostic cp = user_from_uid(acp->ac_uid, 0); 14340266Sbostic if (!strcmp(cp, *argv)) 14433688Sbostic return(1); 14540266Sbostic if ((cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv)) 14640266Sbostic return(1); 14740266Sbostic if (!strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm))) 14840266Sbostic return(1); 14933688Sbostic } while (*++argv); 15033688Sbostic return(0); 15113188Ssam } 15213188Ssam 15313188Ssam #include <sys/dir.h> 15413188Ssam 15513188Ssam #define N_DEVS 43 /* hash value for device names */ 15613188Ssam #define NDEVS 500 /* max number of file names in /dev */ 15713188Ssam 15813188Ssam struct devhash { 15913188Ssam dev_t dev_dev; 16040266Sbostic char dev_name [UT_LINESIZE + 1]; 16113188Ssam struct devhash * dev_nxt; 16213188Ssam }; 16313188Ssam struct devhash *dev_hash[N_DEVS]; 16413188Ssam struct devhash *dev_chain; 16513188Ssam #define HASH(d) (((int) d) % N_DEVS) 16613188Ssam 1677457Skre setupdevs() 1687457Skre { 1697457Skre register DIR * fd; 1707457Skre register struct devhash * hashtab; 1717457Skre register ndevs = NDEVS; 1727457Skre struct direct * dp; 17331126Sbostic char *malloc(); 1747457Skre 17531126Sbostic /*NOSTRICT*/ 17631126Sbostic hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)); 17731126Sbostic if (hashtab == (struct devhash *)0) { 17831126Sbostic fputs("No mem for dev table\n", stderr); 17931126Sbostic return; 18031126Sbostic } 18137848Sbostic if ((fd = opendir(_PATH_DEV)) == NULL) { 18237848Sbostic perror(_PATH_DEV); 1837457Skre return; 1841037Sbill } 1857457Skre while (dp = readdir(fd)) { 1867457Skre if (dp->d_ino == 0) 1877457Skre continue; 1887457Skre if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console")) 1897457Skre continue; 19040266Sbostic (void)strncpy(hashtab->dev_name, dp->d_name, UT_LINESIZE); 19140266Sbostic hashtab->dev_name[UT_LINESIZE] = 0; 1927457Skre hashtab->dev_nxt = dev_chain; 1937457Skre dev_chain = hashtab; 1947457Skre hashtab++; 1957457Skre if (--ndevs <= 0) 1967457Skre break; 1977457Skre } 1987457Skre closedir(fd); 1991037Sbill } 2007457Skre 2017457Skre char * 20213188Ssam getdev(dev) 20311839Ssam dev_t dev; 2047457Skre { 2057457Skre register struct devhash *hp, *nhp; 2067457Skre struct stat statb; 20711839Ssam char name[fldsiz(devhash, dev_name) + 6]; 2087457Skre static dev_t lastdev = (dev_t) -1; 2097457Skre static char *lastname; 21014925Sralph static int init = 0; 21131126Sbostic char *strcpy(), *strcat(); 2127457Skre 2137457Skre if (dev == NODEV) 21411839Ssam return ("__"); 2157457Skre if (dev == lastdev) 21611839Ssam return (lastname); 21713188Ssam if (!init) { 21813188Ssam setupdevs(); 21913188Ssam init++; 22013188Ssam } 2217457Skre for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt) 2227457Skre if (hp->dev_dev == dev) { 2237457Skre lastdev = dev; 22411839Ssam return (lastname = hp->dev_name); 2257457Skre } 2267457Skre for (hp = dev_chain; hp; hp = nhp) { 2277457Skre nhp = hp->dev_nxt; 22840266Sbostic (void)strcpy(name, _PATH_DEV); 2297457Skre strcat(name, hp->dev_name); 2307457Skre if (stat(name, &statb) < 0) /* name truncated usually */ 2317457Skre continue; 2327457Skre if ((statb.st_mode & S_IFMT) != S_IFCHR) 2337457Skre continue; 2347457Skre hp->dev_dev = statb.st_rdev; 2357457Skre hp->dev_nxt = dev_hash[HASH(hp->dev_dev)]; 2367457Skre dev_hash[HASH(hp->dev_dev)] = hp; 2377457Skre if (hp->dev_dev == dev) { 2387457Skre dev_chain = nhp; 2397457Skre lastdev = dev; 24011839Ssam return (lastname = hp->dev_name); 2417457Skre } 2427457Skre } 2437457Skre dev_chain = (struct devhash *) 0; 24411839Ssam return ("??"); 2457457Skre } 246