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