xref: /csrg-svn/usr.bin/lastcomm/lastcomm.c (revision 13188)
111839Ssam #ifndef lint
2*13188Ssam static char *sccsid = "@(#)lastcomm.c	4.6 (Berkeley) 06/18/83";
311839Ssam #endif
41037Sbill 
51037Sbill /*
61037Sbill  * last command
71037Sbill  */
811839Ssam #include <sys/param.h>
911839Ssam #include <sys/acct.h>
10*13188Ssam #include <sys/file.h>
11*13188Ssam 
12*13188Ssam #include <stdio.h>
1311839Ssam #include <pwd.h>
1411839Ssam #include <stat.h>
1511839Ssam #include <utmp.h>
1611839Ssam #include <struct.h>
1711839Ssam #include <ctype.h>
181037Sbill 
19*13188Ssam struct	acct buf[DEV_BSIZE / sizeof (struct acct)];
201037Sbill 
21*13188Ssam time_t	expand();
2211839Ssam char	*flagbits();
23*13188Ssam char	*getname();
24*13188Ssam char	*getdev();
251037Sbill 
2611839Ssam main(argc, argv)
2711839Ssam 	char *argv[];
281037Sbill {
29*13188Ssam 	register int bn, cc;
3011839Ssam 	register struct acct *acp;
31*13188Ssam 	int fd;
32*13188Ssam 	struct stat sb;
331037Sbill 
34*13188Ssam 	fd = open("/usr/adm/acct", O_RDONLY);
35*13188Ssam 	if (fd < 0) {
3611839Ssam 		perror("/usr/adm/acct");
3711839Ssam 		exit(1);
381037Sbill 	}
39*13188Ssam 	fstat(fd, &sb);
40*13188Ssam 	for (bn = btodb(sb.st_size) - 1; bn >= 0; bn--) {
41*13188Ssam 		lseek(fd, bn * DEV_BSIZE, L_SET);
42*13188Ssam 		cc = read(fd, buf, DEV_BSIZE);
43*13188Ssam 		if (cc < 0) {
44*13188Ssam 			perror("read");
45*13188Ssam 			break;
46*13188Ssam 		}
47*13188Ssam 		acp = buf + (cc / sizeof (buf[0])) - 1;
48*13188Ssam 		for (; acp >= buf; acp--) {
49*13188Ssam 			register char *cp;
50*13188Ssam 			time_t x =
51*13188Ssam 			    expand(acp->ac_utime) + expand(acp->ac_stime);
521037Sbill 
5311839Ssam 			acp->ac_comm[10] = '\0';
5411839Ssam 			if (*acp->ac_comm == '\0')
5511839Ssam 				strcpy(acp->ac_comm, "?");
56*13188Ssam 			for (cp = acp->ac_comm; *cp; cp++)
57*13188Ssam 				if (iscntrl(*cp))
58*13188Ssam 					*cp = '?';
5911839Ssam 			if (!ok(argc, argv, acp) && argc != 1)
6011839Ssam 				continue;
6111839Ssam 			printf("%-*s %s %-*s %-*s %4d sec%s %.16s\n",
6211839Ssam 				fldsiz(acct, ac_comm), acp->ac_comm,
6311839Ssam 				flagbits(acp->ac_flag),
64*13188Ssam 				fldsiz(utmp, ut_name), getname(acp->ac_uid),
65*13188Ssam 				fldsiz(utmp, ut_line), getdev(acp->ac_tty),
6611839Ssam 				x, x > 1 || x == 0 ? "s" : " ",
6711839Ssam 				ctime(&acp->ac_btime));
681037Sbill 		}
691037Sbill 	}
701037Sbill }
711037Sbill 
721037Sbill time_t
731037Sbill expand (t)
7411839Ssam 	unsigned t;
751037Sbill {
761037Sbill 	register time_t nt;
771037Sbill 
781037Sbill 	nt = t & 017777;
791037Sbill 	t >>= 13;
8011839Ssam 	while (t) {
811037Sbill 		t--;
821037Sbill 		nt <<= 3;
831037Sbill 	}
841037Sbill 	return (nt);
851037Sbill }
861037Sbill 
877457Skre char *
887457Skre flagbits(f)
8911839Ssam 	register int f;
901037Sbill {
917457Skre 	register int i = 0;
927457Skre 	static char flags[20];
937457Skre 
9411839Ssam #define BIT(flag, ch)	flags[i++] = (f & flag) ? ch : ' '
9511839Ssam 	BIT(ASU, 'S');
9611839Ssam 	BIT(AFORK, 'F');
9711839Ssam 	BIT(ACOMPAT, 'C');
9811839Ssam 	BIT(ACORE, 'D');
9911839Ssam 	BIT(AXSIG, 'X');
1007457Skre 	flags[i] = '\0';
10111839Ssam 	return (flags);
1027457Skre }
1037457Skre 
104*13188Ssam ok(argc, argv, acp)
105*13188Ssam 	register int argc;
106*13188Ssam 	register char *argv[];
107*13188Ssam 	register struct acct *acp;
108*13188Ssam {
109*13188Ssam 	register int j;
110*13188Ssam 
111*13188Ssam 	for (j = 1; j < argc; j++)
112*13188Ssam 		if (strcmp(getname(acp->ac_uid), argv[j]) &&
113*13188Ssam 		    strcmp(getdev(acp->ac_tty), argv[j]) &&
114*13188Ssam 		    strcmp(acp->ac_comm, argv[j]))
115*13188Ssam 			break;
116*13188Ssam 	return (j == argc);
117*13188Ssam }
118*13188Ssam 
119*13188Ssam /* should be done with nameserver or database */
120*13188Ssam 
121*13188Ssam struct	utmp utmp;
122*13188Ssam 
123*13188Ssam #define NUID	2048
124*13188Ssam #define	NMAX	(sizeof (utmp.ut_name))
125*13188Ssam 
126*13188Ssam char	names[NUID][NMAX+1];
127*13188Ssam char	outrangename[NMAX+1];
128*13188Ssam int	outrangeuid = -1;
129*13188Ssam 
130*13188Ssam char *
131*13188Ssam getname(uid)
132*13188Ssam {
133*13188Ssam 	register struct passwd *pw;
134*13188Ssam 	static init;
135*13188Ssam 	struct passwd *getpwent();
136*13188Ssam 
137*13188Ssam 	if (uid >= 0 && uid < NUID && names[uid][0])
138*13188Ssam 		return (&names[uid][0]);
139*13188Ssam 	if (uid >= 0 && uid == outrangeuid)
140*13188Ssam 		return (outrangename);
141*13188Ssam 	if (init == 2) {
142*13188Ssam 		if (uid < NUID)
143*13188Ssam 			return (0);
144*13188Ssam 		setpwent();
145*13188Ssam 		while (pw = getpwent()) {
146*13188Ssam 			if (pw->pw_uid != uid)
147*13188Ssam 				continue;
148*13188Ssam 			outrangeuid = pw->pw_uid;
149*13188Ssam 			strncpy(outrangename, pw->pw_name, NUID);
150*13188Ssam 			endpwent();
151*13188Ssam 			return (outrangename);
152*13188Ssam 		}
153*13188Ssam 		endpwent();
154*13188Ssam 		return (0);
155*13188Ssam 	}
156*13188Ssam 	if (init == 0)
157*13188Ssam 		setpwent(), init = 1;
158*13188Ssam 	while (pw = getpwent()) {
159*13188Ssam 		if (pw->pw_uid < 0 || pw->pw_uid >= NUID) {
160*13188Ssam 			if (pw->pw_uid == uid) {
161*13188Ssam 				outrangeuid = pw->pw_uid;
162*13188Ssam 				strncpy(outrangename, pw->pw_name, NUID);
163*13188Ssam 				return (outrangename);
164*13188Ssam 			}
165*13188Ssam 			continue;
166*13188Ssam 		}
167*13188Ssam 		if (names[pw->pw_uid][0])
168*13188Ssam 			continue;
169*13188Ssam 		strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
170*13188Ssam 		if (pw->pw_uid == uid)
171*13188Ssam 			return (&names[uid][0]);
172*13188Ssam 	}
173*13188Ssam 	init = 2;
174*13188Ssam 	endpwent();
175*13188Ssam 	return (0);
176*13188Ssam }
177*13188Ssam 
178*13188Ssam #include <sys/dir.h>
179*13188Ssam 
180*13188Ssam #define N_DEVS		43		/* hash value for device names */
181*13188Ssam #define NDEVS		500		/* max number of file names in /dev */
182*13188Ssam 
183*13188Ssam struct	devhash {
184*13188Ssam 	dev_t	dev_dev;
185*13188Ssam 	char	dev_name [fldsiz(utmp, ut_line) + 1];
186*13188Ssam 	struct	devhash * dev_nxt;
187*13188Ssam };
188*13188Ssam struct	devhash *dev_hash[N_DEVS];
189*13188Ssam struct	devhash *dev_chain;
190*13188Ssam #define HASH(d)	(((int) d) % N_DEVS)
191*13188Ssam 
1927457Skre setupdevs()
1937457Skre {
1947457Skre 	register DIR * fd;
1957457Skre 	register struct devhash * hashtab;
1967457Skre 	register ndevs = NDEVS;
1977457Skre 	struct direct * dp;
1987457Skre 
1997457Skre 	if ((fd = opendir("/dev")) == NULL) {
2007457Skre 		perror("/dev");
2017457Skre 		return;
2021037Sbill 	}
203*13188Ssam 	hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
204*13188Ssam 	if (hashtab == (struct devhash *)0) {
2057457Skre 		fprintf(stderr, "No mem for dev table\n");
2067457Skre 		return;
2077457Skre 	}
2087457Skre 	while (dp = readdir(fd)) {
2097457Skre 		if (dp->d_ino == 0)
2107457Skre 			continue;
2117457Skre 		if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
2127457Skre 			continue;
2137457Skre 		strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
2147457Skre 		hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
2157457Skre 		hashtab->dev_nxt = dev_chain;
2167457Skre 		dev_chain = hashtab;
2177457Skre 		hashtab++;
2187457Skre 		if (--ndevs <= 0)
2197457Skre 			break;
2207457Skre 	}
2217457Skre 	closedir(fd);
2221037Sbill }
2237457Skre 
2247457Skre char *
225*13188Ssam getdev(dev)
22611839Ssam 	dev_t dev;
2277457Skre {
2287457Skre 	register struct devhash *hp, *nhp;
2297457Skre 	struct stat statb;
23011839Ssam 	char name[fldsiz(devhash, dev_name) + 6];
2317457Skre 	static dev_t lastdev = (dev_t) -1;
2327457Skre 	static char *lastname;
233*13188Ssam 	int init = 0;
2347457Skre 
2357457Skre 	if (dev == NODEV)
23611839Ssam 		return ("__");
2377457Skre 	if (dev == lastdev)
23811839Ssam 		return (lastname);
239*13188Ssam 	if (!init) {
240*13188Ssam 		setupdevs();
241*13188Ssam 		init++;
242*13188Ssam 	}
2437457Skre 	for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
2447457Skre 		if (hp->dev_dev == dev) {
2457457Skre 			lastdev = dev;
24611839Ssam 			return (lastname = hp->dev_name);
2477457Skre 		}
2487457Skre 	for (hp = dev_chain; hp; hp = nhp) {
2497457Skre 		nhp = hp->dev_nxt;
2507457Skre 		strcpy(name, "/dev/");
2517457Skre 		strcat(name, hp->dev_name);
2527457Skre 		if (stat(name, &statb) < 0)	/* name truncated usually */
2537457Skre 			continue;
2547457Skre 		if ((statb.st_mode & S_IFMT) != S_IFCHR)
2557457Skre 			continue;
2567457Skre 		hp->dev_dev = statb.st_rdev;
2577457Skre 		hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
2587457Skre 		dev_hash[HASH(hp->dev_dev)] = hp;
2597457Skre 		if (hp->dev_dev == dev) {
2607457Skre 			dev_chain = nhp;
2617457Skre 			lastdev = dev;
26211839Ssam 			return (lastname = hp->dev_name);
2637457Skre 		}
2647457Skre 	}
2657457Skre 	dev_chain = (struct devhash *) 0;
26611839Ssam 	return ("??");
2677457Skre }
268