xref: /original-bsd/usr.bin/lastcomm/lastcomm.c (revision 6c57d260)
1 static char *sccsid = "@(#)lastcomm.c	4.3 (Berkeley) 12/14/80";
2 #
3 
4 /*
5  * last command
6  */
7 
8 # include <stdio.h>
9 # include <sys/types.h>
10 # include <sys/acct.h>
11 # include <signal.h>
12 # include <pwd.h>
13 # include <stat.h>
14 
15 # define N_USER		1000
16 
17 struct acct	acct_buff [BUFSIZ / sizeof (struct acct)];
18 
19 char	yes   = 1,
20 	no    = 0,
21 
22 	user_list [1000][9];
23 
24 time_t	expand ();
25 
26 struct passwd
27 	*passwd,
28 	*getpwent ();
29 
30 struct stat stat_buff;
31 
32 main (argc, argv)
33 char **argv;
34 {
35 	char	acct_desc,
36 		*p;
37 
38 	long	i,
39 		j,
40 		i_block,
41 		n_blocks,
42 		n_byte,
43 		n_entry;
44 
45 	float	x;
46 
47 /*
48  * set up user names
49  */
50 	while (passwd = getpwent ())
51 	{
52 		if (user_list[passwd->pw_uid][0]==0)
53 			move (passwd->pw_name, user_list [passwd->pw_uid]);
54 	}
55 
56 	acct_desc = open ("/usr/adm/acct", 0);
57 	if (acct_desc < 0)
58 	{
59 		perror ("/usr/adm/acct");
60 		return;
61 	}
62 	fstat (acct_desc, &stat_buff);
63 	n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ;
64 
65 	/*
66 	 * read one block's worth
67 	 */
68 	for (i_block = n_blocks - 1; i_block >= 0; i_block--)
69 	{
70 		lseek (acct_desc, i_block * BUFSIZ, 0);
71 		n_byte = read (acct_desc, acct_buff, BUFSIZ);
72 		n_entry = n_byte / sizeof acct_buff [0];
73 		for (i = n_entry - 1; i >= 0; i--)
74 		{
75 			if (!*user_list [acct_buff [i].ac_uid]) continue;
76 			/*
77 			 * get the times
78 			 */
79 			x =	expand (acct_buff [i].ac_utime)
80 				+
81 				expand (acct_buff [i].ac_stime);
82 			/*
83 			 * null terminate the command name
84 			 */
85 			acct_buff [i].ac_comm [10] = 0;
86 			/*
87 			 * replace missing command names with question marks
88 			 */
89 			if (!*acct_buff [i].ac_comm)
90 			{
91 				move ("?", acct_buff [i].ac_comm);
92 			}
93 			/*
94 			 * replace control characters with question marks
95 			 */
96 			for (p = acct_buff [i].ac_comm; *p; p++)
97 			{
98 				if (*p < '!' || '~' < *p) *p = '?';
99 			}
100 			for (j = 1; j < argc; j++)
101 			{
102 				if
103 				(
104 					equal (acct_buff [i].ac_comm, argv [j])
105 					||
106 					equal
107 					(
108 					user_list [acct_buff [i].ac_uid],
109 						argv [j]
110 					)
111 				)
112 				{
113 					break;
114 				}
115 			}
116 			if (argc == 1 || j != argc)
117 			{
118 				printf
119 				(
120 					"%-10s %-8s %6.2f     %.16s\n",
121 					acct_buff [i].ac_comm,
122 					user_list [acct_buff [i].ac_uid],
123 					x / 60.0,
124 					ctime (&acct_buff [i].ac_btime)
125 				);
126 			}
127 		}
128 	}
129 }
130 
131 time_t
132 expand (t)
133 unsigned t;
134 {
135 	register time_t nt;
136 
137 	nt = t & 017777;
138 	t >>= 13;
139 	while (t)
140 	{
141 		t--;
142 		nt <<= 3;
143 	}
144 	return (nt);
145 }
146 
147 move (a, b)
148 char *a, *b;
149 {
150 	while (*b++ = *a++);
151 }
152 
153 equal (a, b)
154 char *a, *b;
155 {
156 	for (;; a++, b++)
157 	{
158 		if (*a != *b) return no;
159 		if (!*a)      return yes;
160 	}
161 }
162