xref: /original-bsd/usr.sbin/ac/ac.c (revision f955cb91)
1 /*-
2  * Copyright (c) 1982 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1982 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)ac.c	4.10 (Berkeley) 04/18/91";
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 
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 
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 
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 
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 
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 
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 
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