1*1886Smark static char *sccsid = "@(#)lastcomm.c	4.2 (Berkeley) 12/14/80";
21037Sbill #
31037Sbill 
41037Sbill /*
51037Sbill  * last command
61037Sbill  */
71037Sbill 
81037Sbill # include <stdio.h>
91037Sbill # include <sys/types.h>
101037Sbill # include <sys/acct.h>
111037Sbill # include <signal.h>
121037Sbill # include <pwd.h>
131037Sbill # include <stat.h>
141037Sbill 
151037Sbill # define N_USER		1000
161037Sbill 
171037Sbill struct acct	acct_buff [BUFSIZ / sizeof (struct acct)];
181037Sbill 
191037Sbill char	yes   = 1,
201037Sbill 	no    = 0,
211037Sbill 
221037Sbill 	user_list [1000][9];
231037Sbill 
241037Sbill time_t	expand ();
251037Sbill 
261037Sbill struct passwd
271037Sbill 	*passwd,
281037Sbill 	*getpwent ();
291037Sbill 
301037Sbill struct stat stat_buff;
311037Sbill 
321037Sbill main (argc, argv)
331037Sbill char **argv;
341037Sbill {
351037Sbill 	char	acct_desc,
361037Sbill 		*p;
371037Sbill 
381037Sbill 	long	i,
391037Sbill 		j,
401037Sbill 		i_block,
411037Sbill 		n_blocks,
421037Sbill 		n_byte,
431037Sbill 		n_entry;
441037Sbill 
451037Sbill 	float	x;
461037Sbill 
471037Sbill /*
481037Sbill  * set up user names
491037Sbill  */
501037Sbill 	while (passwd = getpwent ())
511037Sbill 	{
52*1886Smark 		if (user_list[passwd->pw_uid][0])
53*1886Smark 			move (passwd->pw_name, user_list [passwd->pw_uid]);
541037Sbill 	}
551037Sbill 
561037Sbill 	acct_desc = open ("/usr/adm/acct", 0);
571037Sbill 	if (acct_desc < 0)
581037Sbill 	{
591037Sbill 		perror ("/usr/adm/acct");
601037Sbill 		return;
611037Sbill 	}
621037Sbill 	fstat (acct_desc, &stat_buff);
631037Sbill 	n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ;
641037Sbill 
651037Sbill 	/*
661037Sbill 	 * read one block's worth
671037Sbill 	 */
681037Sbill 	for (i_block = n_blocks - 1; i_block >= 0; i_block--)
691037Sbill 	{
701037Sbill 		lseek (acct_desc, i_block * BUFSIZ, 0);
711037Sbill 		n_byte = read (acct_desc, acct_buff, BUFSIZ);
721037Sbill 		n_entry = n_byte / sizeof acct_buff [0];
731037Sbill 		for (i = n_entry - 1; i >= 0; i--)
741037Sbill 		{
751037Sbill 			if (!*user_list [acct_buff [i].ac_uid]) continue;
761037Sbill 			/*
771037Sbill 			 * get the times
781037Sbill 			 */
791037Sbill 			x =	expand (acct_buff [i].ac_utime)
801037Sbill 				+
811037Sbill 				expand (acct_buff [i].ac_stime);
821037Sbill 			/*
831037Sbill 			 * null terminate the command name
841037Sbill 			 */
851037Sbill 			acct_buff [i].ac_comm [10] = 0;
861037Sbill 			/*
871037Sbill 			 * replace missing command names with question marks
881037Sbill 			 */
891037Sbill 			if (!*acct_buff [i].ac_comm)
901037Sbill 			{
911037Sbill 				move ("?", acct_buff [i].ac_comm);
921037Sbill 			}
931037Sbill 			/*
941037Sbill 			 * replace control characters with question marks
951037Sbill 			 */
961037Sbill 			for (p = acct_buff [i].ac_comm; *p; p++)
971037Sbill 			{
981037Sbill 				if (*p < '!' || '~' < *p) *p = '?';
991037Sbill 			}
1001037Sbill 			for (j = 1; j < argc; j++)
1011037Sbill 			{
1021037Sbill 				if
1031037Sbill 				(
1041037Sbill 					equal (acct_buff [i].ac_comm, argv [j])
1051037Sbill 					||
1061037Sbill 					equal
1071037Sbill 					(
1081037Sbill 					user_list [acct_buff [i].ac_uid],
1091037Sbill 						argv [j]
1101037Sbill 					)
1111037Sbill 				)
1121037Sbill 				{
1131037Sbill 					break;
1141037Sbill 				}
1151037Sbill 			}
1161037Sbill 			if (argc == 1 || j != argc)
1171037Sbill 			{
1181037Sbill 				printf
1191037Sbill 				(
1201037Sbill 					"%-10s %-8s %6.2f     %.16s\n",
1211037Sbill 					acct_buff [i].ac_comm,
1221037Sbill 					user_list [acct_buff [i].ac_uid],
1231037Sbill 					x / 60.0,
1241037Sbill 					ctime (&acct_buff [i].ac_btime)
1251037Sbill 				);
1261037Sbill 			}
1271037Sbill 		}
1281037Sbill 	}
1291037Sbill }
1301037Sbill 
1311037Sbill time_t
1321037Sbill expand (t)
1331037Sbill unsigned t;
1341037Sbill {
1351037Sbill 	register time_t nt;
1361037Sbill 
1371037Sbill 	nt = t & 017777;
1381037Sbill 	t >>= 13;
1391037Sbill 	while (t)
1401037Sbill 	{
1411037Sbill 		t--;
1421037Sbill 		nt <<= 3;
1431037Sbill 	}
1441037Sbill 	return (nt);
1451037Sbill }
1461037Sbill 
1471037Sbill move (a, b)
1481037Sbill char *a, *b;
1491037Sbill {
1501037Sbill 	while (*b++ = *a++);
1511037Sbill }
1521037Sbill 
1531037Sbill equal (a, b)
1541037Sbill char *a, *b;
1551037Sbill {
1561037Sbill 	for (;; a++, b++)
1571037Sbill 	{
1581037Sbill 		if (*a != *b) return no;
1591037Sbill 		if (!*a)      return yes;
1601037Sbill 	}
1611037Sbill }
162