]>
git.saurik.com Git - apple/system_cmds.git/blob - ac.tproj/ac.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1994 Christopher G. Demetriou.
26 * @(#)Copyright (c) 1994, Simon J. Gerraty.
28 * This is free software. It comes with NO WARRANTY.
29 * Permission to use, modify and distribute this source code
30 * is granted subject to the following conditions.
31 * 1/ that the above copyright notice and this notice
32 * are preserved in all copies and that due credit be given
34 * 2/ that any changes to this code are clearly commented
35 * as such so that the author does not get blamed for bugs
40 static char rcsid
[] = "$Id: ac.c,v 1.1.1.2 2000/01/11 02:09:57 wsanchez Exp $";
43 #include <sys/types.h>
56 * this is for our list of currently logged in sessions
59 struct utmp_list
*next
;
64 * this is for our list of users that are accumulating time.
67 struct user_list
*next
;
68 char name
[UT_NAMESIZE
+1];
73 * this is for chosing whether to ignore a login
76 struct tty_list
*next
;
77 char name
[UT_LINESIZE
+3];
86 static char *Console
= CONSOLE_TTY
;
88 static time_t Total
= 0;
89 static time_t FirstTime
= 0;
91 static struct user_list
*Users
= NULL
;
92 static struct tty_list
*Ttys
= NULL
;
94 #define NEW(type) (type *)malloc(sizeof (type))
96 #define AC_W 1 /* not _PATH_WTMP */
97 #define AC_D 2 /* daily totals (ignore -p) */
98 #define AC_P 4 /* per-user totals */
99 #define AC_U 8 /* specified users only */
100 #define AC_T 16 /* specified ttys only */
103 static int Debug
= 0;
106 int main
__P((int, char **));
107 int ac
__P((FILE *));
108 struct tty_list
*add_tty
__P((char *));
109 int do_tty
__P((char *));
110 FILE *file
__P((char *));
111 struct utmp_list
*log_in
__P((struct utmp_list
*, struct utmp
*));
112 struct utmp_list
*log_out
__P((struct utmp_list
*, struct utmp
*));
113 int on_console
__P((struct utmp_list
*));
114 void show
__P((char *, time_t));
115 void show_today
__P((struct user_list
*, struct utmp_list
*,
117 void show_users
__P((struct user_list
*));
118 struct user_list
*update_user
__P((struct user_list
*, char *, time_t));
119 void usage
__P((void));
130 if ((fp
= fopen(name
, "r")) == NULL
)
132 /* in case we want to discriminate */
133 if (strcmp(_PATH_WTMP
, name
))
147 if ((tp
= NEW(struct tty_list
)) == NULL
)
149 tp
->len
= 0; /* full match */
150 tp
->ret
= 1; /* do if match */
151 if (*name
== '!') { /* don't do if match */
155 (void)strncpy(tp
->name
, name
, sizeof (tp
->name
) - 1);
156 tp
->name
[sizeof (tp
->name
) - 1] = '\0';
157 if ((rcp
= strchr(tp
->name
, '*')) != NULL
) { /* wild card */
159 tp
->len
= strlen(tp
->name
); /* match len bytes only */
167 * should we process the named tty?
176 for (tp
= Ttys
; tp
!= NULL
; tp
= tp
->next
) {
177 if (tp
->ret
== 0) /* specific don't */
178 def_ret
= 1; /* default do */
180 if (strncmp(name
, tp
->name
, tp
->len
) == 0)
183 if (strncmp(name
, tp
->name
, sizeof (tp
->name
)) == 0)
192 * is someone logged in on Console?
196 struct utmp_list
*head
;
198 struct utmp_list
*up
;
200 for (up
= head
; up
; up
= up
->next
) {
201 if (strncmp(up
->usr
.ut_line
, Console
,
202 sizeof (up
->usr
.ut_line
)) == 0)
210 * update user's login time
213 update_user(head
, name
, secs
)
214 struct user_list
*head
;
218 struct user_list
*up
;
220 for (up
= head
; up
!= NULL
; up
= up
->next
) {
221 if (strncmp(up
->name
, name
, sizeof (up
->name
)) == 0) {
228 * not found so add new user unless specified users only
233 if ((up
= NEW(struct user_list
)) == NULL
)
236 (void)strncpy(up
->name
, name
, sizeof (up
->name
) - 1);
237 up
->name
[sizeof (up
->name
) - 1] = '\0'; /* paranoid! */
252 while ((c
= getopt(argc
, argv
, "Dc:dpt:w:")) != EOF
) {
272 case 't': /* only do specified ttys */
286 * initialize user list
288 for (; optind
< argc
; optind
++) {
289 Users
= update_user(Users
, argv
[optind
], 0L);
291 Flags
|= AC_U
; /* freeze user list */
297 * if _PATH_WTMP does not exist, exit quietly
299 if (access(_PATH_WTMP
, 0) != 0 && errno
== ENOENT
)
302 fp
= file(_PATH_WTMP
);
310 * print login time in decimal hours
317 (void)printf("\t%-*s %8.2f\n", UT_NAMESIZE
, name
,
318 ((double)secs
/ 3600));
323 struct user_list
*list
;
325 struct user_list
*lp
;
327 for (lp
= list
; lp
; lp
= lp
->next
)
328 show(lp
->name
, lp
->secs
);
332 * print total login time for 24hr period in decimal hours
335 show_today(users
, logins
, secs
)
336 struct user_list
*users
;
337 struct utmp_list
*logins
;
340 struct user_list
*up
;
341 struct utmp_list
*lp
;
343 time_t yesterday
= secs
- 1;
345 (void)strftime(date
, sizeof (date
), "%b %e total",
346 localtime(&yesterday
));
348 /* restore the missing second */
351 for (lp
= logins
; lp
!= NULL
; lp
= lp
->next
) {
352 secs
= yesterday
- lp
->usr
.ut_time
;
353 Users
= update_user(Users
, lp
->usr
.ut_name
, secs
);
354 lp
->usr
.ut_time
= yesterday
; /* as if they just logged in */
357 for (up
= users
; up
!= NULL
; up
= up
->next
) {
359 up
->secs
= 0; /* for next day */
362 (void)printf("%s %11.2f\n", date
, ((double)secs
/ 3600));
366 * log a user out and update their times.
367 * if ut_line is "~", we log all users out as the system has
372 struct utmp_list
*head
;
375 struct utmp_list
*lp
, *lp2
, *tlp
;
378 for (lp
= head
, lp2
= NULL
; lp
!= NULL
; )
379 if (*up
->ut_line
== '~' || strncmp(lp
->usr
.ut_line
, up
->ut_line
,
380 sizeof (up
->ut_line
)) == 0) {
381 secs
= up
->ut_time
- lp
->usr
.ut_time
;
382 Users
= update_user(Users
, lp
->usr
.ut_name
, secs
);
385 printf("%-.*s %-.*s: %-.*s logged out (%2d:%02d:%02d)\n",
386 19, ctime(&up
->ut_time
),
387 sizeof (lp
->usr
.ut_line
), lp
->usr
.ut_line
,
388 sizeof (lp
->usr
.ut_name
), lp
->usr
.ut_name
,
389 secs
/ 3600, (secs
% 3600) / 60, secs
% 60);
398 else if (lp2
!= NULL
)
410 * if do_tty says ok, login a user
414 struct utmp_list
*head
;
417 struct utmp_list
*lp
;
420 * this could be a login. if we're not dealing with
421 * the console name, say it is.
423 * If we are, and if ut_host==":0.0" we know that it
424 * isn't a real login. _But_ if we have not yet recorded
425 * someone being logged in on Console - due to the wtmp
426 * file starting after they logged in, we'll pretend they
427 * logged in, at the start of the wtmp file.
431 if (up
->ut_host
[0] == ':') {
433 * SunOS 4.0.2 does not treat ":0.0" as special but we
436 if (on_console(head
))
439 * ok, no recorded login, so they were here when wtmp
440 * started! Adjust ut_time!
442 up
->ut_time
= FirstTime
;
444 * this allows us to pick the right logout
446 (void)strncpy(up
->ut_line
, Console
, sizeof (up
->ut_line
) - 1);
447 up
->ut_line
[sizeof (up
->ut_line
) - 1] = '\0'; /* paranoid! */
451 * If we are doing specified ttys only, we ignore
455 if (!do_tty(up
->ut_line
))
459 * go ahead and log them in
461 if ((lp
= NEW(struct utmp_list
)) == NULL
)
465 memmove((char *)&lp
->usr
, (char *)up
, sizeof (struct utmp
));
468 printf("%-.*s %-.*s: %-.*s logged in", 19,
469 ctime(&lp
->usr
.ut_time
), sizeof (up
->ut_line
),
470 up
->ut_line
, sizeof (up
->ut_name
), up
->ut_name
);
472 printf(" (%-.*s)", sizeof (up
->ut_host
), up
->ut_host
);
483 struct utmp_list
*lp
, *head
= NULL
;
489 while (fread((char *)&usr
, sizeof(usr
), 1, fp
) == 1) {
491 FirstTime
= usr
.ut_time
;
493 ltm
= localtime(&usr
.ut_time
);
494 if (day
>= 0 && day
!= ltm
->tm_yday
) {
497 * print yesterday's total
501 secs
-= 60 * ltm
->tm_min
;
502 secs
-= 3600 * ltm
->tm_hour
;
503 show_today(Users
, head
, secs
);
507 switch(*usr
.ut_line
) {
514 * adjust time for those logged in
516 for (lp
= head
; lp
!= NULL
; lp
= lp
->next
)
517 lp
->usr
.ut_time
-= secs
;
519 case '~': /* reboot or shutdown */
520 head
= log_out(head
, &usr
);
521 FirstTime
= usr
.ut_time
; /* shouldn't be needed */
525 * if they came in on tty[p-y]*, then it is only
526 * a login session if the ut_host field is non-empty
529 if (strncmp(usr
.ut_line
, "tty", 3) != 0 ||
530 strchr("pqrstuvwxy", usr
.ut_line
[3]) == 0 ||
531 *usr
.ut_host
!= '\0')
532 head
= log_in(head
, &usr
);
534 head
= log_out(head
, &usr
);
539 usr
.ut_time
= time((time_t *)0);
540 (void)strcpy(usr
.ut_line
, "~");
543 ltm
= localtime(&usr
.ut_time
);
544 if (day
>= 0 && day
!= ltm
->tm_yday
) {
546 * print yesterday's total
550 secs
-= 60 * ltm
->tm_min
;
551 secs
-= 3600 * ltm
->tm_hour
;
552 show_today(Users
, head
, secs
);
556 * anyone still logged in gets time up to now
558 head
= log_out(head
, &usr
);
561 show_today(Users
, head
, time((time_t *)0));
565 show("total", Total
);
573 (void)fprintf(stderr
,
575 "ac [-dp] [-c console] [-t tty] [-w wtmp] [users ...]\n");
577 "ac [-dp] [-t tty] [-w wtmp] [users ...]\n");