xref: /original-bsd/usr.bin/lastcomm/lastcomm.c (revision d25e1985)
1 static char *sccsid = "@(#)lastcomm.c	4.1 (Berkeley) 10/01/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 		move (passwd->pw_name, user_list [passwd->pw_uid]);
53 	}
54 
55 	acct_desc = open ("/usr/adm/acct", 0);
56 	if (acct_desc < 0)
57 	{
58 		perror ("/usr/adm/acct");
59 		return;
60 	}
61 	fstat (acct_desc, &stat_buff);
62 	n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ;
63 
64 	/*
65 	 * read one block's worth
66 	 */
67 	for (i_block = n_blocks - 1; i_block >= 0; i_block--)
68 	{
69 		lseek (acct_desc, i_block * BUFSIZ, 0);
70 		n_byte = read (acct_desc, acct_buff, BUFSIZ);
71 		n_entry = n_byte / sizeof acct_buff [0];
72 		for (i = n_entry - 1; i >= 0; i--)
73 		{
74 			if (!*user_list [acct_buff [i].ac_uid]) continue;
75 			/*
76 			 * get the times
77 			 */
78 			x =	expand (acct_buff [i].ac_utime)
79 				+
80 				expand (acct_buff [i].ac_stime);
81 			/*
82 			 * null terminate the command name
83 			 */
84 			acct_buff [i].ac_comm [10] = 0;
85 			/*
86 			 * replace missing command names with question marks
87 			 */
88 			if (!*acct_buff [i].ac_comm)
89 			{
90 				move ("?", acct_buff [i].ac_comm);
91 			}
92 			/*
93 			 * replace control characters with question marks
94 			 */
95 			for (p = acct_buff [i].ac_comm; *p; p++)
96 			{
97 				if (*p < '!' || '~' < *p) *p = '?';
98 			}
99 			for (j = 1; j < argc; j++)
100 			{
101 				if
102 				(
103 					equal (acct_buff [i].ac_comm, argv [j])
104 					||
105 					equal
106 					(
107 					user_list [acct_buff [i].ac_uid],
108 						argv [j]
109 					)
110 				)
111 				{
112 					break;
113 				}
114 			}
115 			if (argc == 1 || j != argc)
116 			{
117 				printf
118 				(
119 					"%-10s %-8s %6.2f     %.16s\n",
120 					acct_buff [i].ac_comm,
121 					user_list [acct_buff [i].ac_uid],
122 					x / 60.0,
123 					ctime (&acct_buff [i].ac_btime)
124 				);
125 			}
126 		}
127 	}
128 }
129 
130 time_t
131 expand (t)
132 unsigned t;
133 {
134 	register time_t nt;
135 
136 	nt = t & 017777;
137 	t >>= 13;
138 	while (t)
139 	{
140 		t--;
141 		nt <<= 3;
142 	}
143 	return (nt);
144 }
145 
146 move (a, b)
147 char *a, *b;
148 {
149 	while (*b++ = *a++);
150 }
151 
152 equal (a, b)
153 char *a, *b;
154 {
155 	for (;; a++, b++)
156 	{
157 		if (*a != *b) return no;
158 		if (!*a)      return yes;
159 	}
160 }
161