1 /*-
2 * Copyright (c) 1982, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1982, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)ac.c 8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17
18 /*
19 * ac [ -w wtmp ] [ -d ] [ -p ] [ people ]
20 */
21
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <sys/timeb.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <utmp.h>
28
29 #define NMAX UT_NAMESIZE
30 #define LMAX UT_LINESIZE
31
32 /*
33 #define TSIZE 1000
34 */
35 #define TSIZE 6242
36 #define USIZE 500
37 struct utmp ibuf;
38
39 struct ubuf {
40 char uname[NMAX];
41 long utime;
42 } ubuf[USIZE];
43
44 struct tbuf {
45 struct ubuf *userp;
46 long ttime;
47 } tbuf[TSIZE];
48
49 char *wtmp;
50 int pflag, byday;
51 long dtime;
52 long midnight;
53 long lastime;
54 long day = 86400L;
55 int pcount;
56 char **pptr;
57
main(argc,argv)58 main(argc, argv)
59 char **argv;
60 {
61 int c, fl;
62 register i;
63 FILE *wf;
64
65 wtmp = _PATH_WTMP;
66 while (--argc > 0 && **++argv == '-')
67 switch(*++*argv) {
68 case 'd':
69 byday++;
70 continue;
71
72 case 'w':
73 if (--argc>0)
74 wtmp = *++argv;
75 continue;
76
77 case 'p':
78 pflag++;
79 continue;
80 }
81 pcount = argc;
82 pptr = argv;
83 if ((wf = fopen(wtmp, "r")) == NULL) {
84 printf("No %s\n", wtmp);
85 exit(1);
86 }
87 for(;;) {
88 if (fread((char *)&ibuf, sizeof(ibuf), 1, wf) != 1)
89 break;
90 fl = 0;
91 for (i=0; i<NMAX; i++) {
92 c = ibuf.ut_name[i];
93 if (isprint(c) && c != ' ') {
94 if (fl)
95 goto skip;
96 continue;
97 }
98 if (c==' ' || c=='\0') {
99 fl++;
100 ibuf.ut_name[i] = '\0';
101 } else
102 goto skip;
103 }
104 loop();
105 skip:;
106 }
107 ibuf.ut_name[0] = '\0';
108 ibuf.ut_line[0] = '~';
109 time(&ibuf.ut_time);
110 loop();
111 print();
112 exit(0);
113 }
114
loop()115 loop()
116 {
117 register i;
118 register struct tbuf *tp;
119 register struct ubuf *up;
120
121 if(ibuf.ut_line[0] == '|') {
122 dtime = ibuf.ut_time;
123 return;
124 }
125 if(ibuf.ut_line[0] == '{') {
126 if(dtime == 0)
127 return;
128 for(tp = tbuf; tp < &tbuf[TSIZE]; tp++)
129 tp->ttime += ibuf.ut_time-dtime;
130 dtime = 0;
131 return;
132 }
133 if (lastime>ibuf.ut_time || lastime+(1.5*day)<ibuf.ut_time)
134 midnight = 0;
135 if (midnight==0)
136 newday();
137 lastime = ibuf.ut_time;
138 if (byday && ibuf.ut_time > midnight) {
139 upall(1);
140 print();
141 newday();
142 for (up=ubuf; up < &ubuf[USIZE]; up++)
143 up->utime = 0;
144 }
145 if (ibuf.ut_line[0] == '~') {
146 ibuf.ut_name[0] = '\0';
147 upall(0);
148 return;
149 }
150 /*
151 if (ibuf.ut_line[0]=='t')
152 i = (ibuf.ut_line[3]-'0')*10 + (ibuf.ut_line[4]-'0');
153 else
154 i = TSIZE-1;
155 if (i<0 || i>=TSIZE)
156 i = TSIZE-1;
157 */
158
159 /*
160 * Correction contributed by Phyllis Kantar @ Rand-unix
161 *
162 * Fixes long standing problem with tty names other than 00-99
163 */
164 if (ibuf.ut_line[0]=='t') {
165 i = (ibuf.ut_line[3]-'0');
166 if(ibuf.ut_line[4])
167 i = i*79 + (ibuf.ut_line[4]-'0');
168 } else
169 i = TSIZE-1;
170 if (i<0 || i>=TSIZE) {
171 i = TSIZE-1;
172 printf("ac: Bad tty name: %s\n", ibuf.ut_line);
173 }
174
175 tp = &tbuf[i];
176 update(tp, 0);
177 }
178
print()179 print()
180 {
181 int i;
182 long ttime, t;
183
184 ttime = 0;
185 for (i=0; i<USIZE; i++) {
186 if(!among(i))
187 continue;
188 t = ubuf[i].utime;
189 if (t>0)
190 ttime += t;
191 if (pflag && ubuf[i].utime > 0) {
192 printf("\t%-*.*s %6.2f\n", NMAX, NMAX,
193 ubuf[i].uname, ubuf[i].utime/3600.);
194 }
195 }
196 if (ttime > 0) {
197 pdate();
198 printf("\ttotal %9.2f\n", ttime/3600.);
199 }
200 }
201
upall(f)202 upall(f)
203 {
204 register struct tbuf *tp;
205
206 for (tp=tbuf; tp < &tbuf[TSIZE]; tp++)
207 update(tp, f);
208 }
209
210 update(tp, f)
211 struct tbuf *tp;
212 {
213 int j;
214 struct ubuf *up;
215 long t, t1;
216
217 if (f)
218 t = midnight;
219 else
220 t = ibuf.ut_time;
221 if (tp->userp) {
222 t1 = t - tp->ttime;
223 if (t1 > 0)
224 tp->userp->utime += t1;
225 }
226 tp->ttime = t;
227 if (f)
228 return;
229 if (ibuf.ut_name[0]=='\0') {
230 tp->userp = 0;
231 return;
232 }
233 for (up=ubuf; up < &ubuf[USIZE]; up++) {
234 if (up->uname[0] == '\0')
235 break;
236 for (j=0; j<NMAX && up->uname[j]==ibuf.ut_name[j]; j++);
237 if (j>=NMAX)
238 break;
239 }
240 for (j=0; j<NMAX; j++)
241 up->uname[j] = ibuf.ut_name[j];
242 tp->userp = up;
243 }
244
among(i)245 among(i)
246 {
247 register j, k;
248 register char *p;
249
250 if (pcount==0)
251 return(1);
252 for (j=0; j<pcount; j++) {
253 p = pptr[j];
254 for (k=0; k<NMAX; k++) {
255 if (*p == ubuf[i].uname[k]) {
256 if (*p++ == '\0' || k == NMAX-1)
257 return(1);
258 } else
259 break;
260 }
261 }
262 return(0);
263 }
264
newday()265 newday()
266 {
267 long ttime;
268 struct timeb tb;
269 struct tm *localtime();
270
271 time(&ttime);
272 if (midnight == 0) {
273 ftime(&tb);
274 midnight = 60*(long)tb.timezone;
275 if (localtime(&ttime)->tm_isdst)
276 midnight -= 3600;
277 }
278 while (midnight <= ibuf.ut_time)
279 midnight += day;
280 }
281
pdate()282 pdate()
283 {
284 long x;
285 char *ctime();
286
287 if (byday==0)
288 return;
289 x = midnight-1;
290 printf("%.6s", ctime(&x)+4);
291 }
292