xref: /csrg-svn/usr.bin/lastcomm/lastcomm.c (revision 42735)
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