ac(8) utility, brought over from FreeBSD 1.1.5.
This commit is contained in:
parent
4991d6158d
commit
742678181c
18
usr.sbin/ac/Makefile
Normal file
18
usr.sbin/ac/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
# $Id: Makefile,v 1.1.1.1 1994/05/18 08:00:44 csgr Exp $
|
||||
|
||||
PROG= ac
|
||||
MAN8= ac.8
|
||||
|
||||
# If "CONSOLE_TTY" is not defined, this program is compatible with the
|
||||
# traditional implementation (using SunOS 4.x as the sample traditional
|
||||
# implementation). This is the default.
|
||||
#
|
||||
# If "CONSOLE_TTY" is defined, it must be defined to the appropriate
|
||||
# console name, e.g. "vga". Additionally, the various commented-out
|
||||
# sections of the man page should be uncommented. This is not the
|
||||
# default because of the inability to detect the proper console name
|
||||
# easily, especially on m68k systems, which can share binaries.
|
||||
#
|
||||
#CFLAGS+=-DCONSOLE_TTY=\"vga\"
|
||||
|
||||
.include <bsd.prog.mk>
|
166
usr.sbin/ac/ac.8
166
usr.sbin/ac/ac.8
@ -1,5 +1,7 @@
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Copyright (c) 1994 Simon J. Gerraty
|
||||
.\" Copyright (c) 1994 Christopher G. Demetriou
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -11,88 +13,118 @@
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\" This product includes software developed by Christopher G. Demetriou.
|
||||
.\" 3. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)ac.8 8.2 (Berkeley) 4/19/94
|
||||
.\" $Id: ac.8,v 1.1.1.1 1994/05/18 08:00:45 csgr Exp $
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dd March 15, 1994
|
||||
.Dt AC 8
|
||||
.Os BSD 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ac
|
||||
.Nd display connect time accounting
|
||||
.Nd connect time accounting
|
||||
.Sh SYNOPSIS
|
||||
.Nm ac
|
||||
.Op Fl d
|
||||
.Op Fl p
|
||||
.Op Fl w Ar file
|
||||
.Op Fl dp
|
||||
.\".Op Fl c Ar console
|
||||
.Op Fl t Ar tty
|
||||
.Op Fl w Ar wtmp
|
||||
.Op Ar users ...
|
||||
.Sh DESCRIPTION
|
||||
If the file
|
||||
If the file
|
||||
.Pa /var/log/wtmp
|
||||
exists,
|
||||
a record of individual
|
||||
login and logout times are written to it by
|
||||
.Xr init 8
|
||||
and
|
||||
exists, a record of individual login and logout
|
||||
times are written to it by
|
||||
.Xr login 8
|
||||
and
|
||||
.Xr init 8 ,
|
||||
respectively.
|
||||
The program
|
||||
.Nm ac
|
||||
examines these
|
||||
records and writes the accumulated connect time for all logins to the
|
||||
standard output.
|
||||
.Nm \&Ac
|
||||
examines these records and writes the accumulated connect time
|
||||
for all logins to the standard output.
|
||||
.Pp
|
||||
Options available:
|
||||
.Bl -tag -width people
|
||||
The options are as follows:
|
||||
.Bl -tag -width indentXXX
|
||||
.It Fl d
|
||||
Display the connect times in 24 hour chunks.
|
||||
.\" .It Fl c Ar console
|
||||
.\" Use
|
||||
.\" .Ar console
|
||||
.\" as the name of the device that local X sessions (ut_host of ":0.0")
|
||||
.\" originate from. If any login has been recorded on
|
||||
.\" .Ar console
|
||||
.\" then these X sessions are ignored unless COMPAT_SUNOS was defined at
|
||||
.\" compile time.
|
||||
.It Fl p
|
||||
Display individual user totals.
|
||||
.It Fl w Ar file
|
||||
Read raw connect time data from
|
||||
.Ar file
|
||||
instead of the default file
|
||||
Print individual users' totals.
|
||||
.It Fl t Ar tty
|
||||
Only do accounting logins on certain ttys. The
|
||||
.Ar tty
|
||||
specification can start with '!' to indicate not this
|
||||
.Ar tty
|
||||
and end with '*' to indicate all similarly named ttys.
|
||||
Multiple
|
||||
.Fl t
|
||||
flags may be specified.
|
||||
.It Fl w Ar wtmp
|
||||
Read connect time data from
|
||||
.Ar wtmp
|
||||
instead of the default file,
|
||||
.Pa /var/log/wtmp .
|
||||
.It Ar users ...
|
||||
Display totals for the given individuals
|
||||
only.
|
||||
Display totals for the given individuals only.
|
||||
.El
|
||||
.Pp
|
||||
If no arguments are given,
|
||||
.Nm
|
||||
displays the total amount of login time for all active accounts on the
|
||||
system.
|
||||
.Nm ac
|
||||
displays the total connect time for all
|
||||
accounts with login sessions recorded in
|
||||
.Pa wtmp .
|
||||
.Pp
|
||||
The default
|
||||
.Pa wtmp
|
||||
file is an infinitely increasing file
|
||||
unless frequently truncated. This is normally
|
||||
done by the daily daemon scripts scheduled by
|
||||
.Xr cron 8
|
||||
file will increase without bound unless it is truncated.
|
||||
It is normally truncated by the daily scripts run
|
||||
by
|
||||
.Xr cron 8 ,
|
||||
which rename and rotate the
|
||||
.Pa wtmp
|
||||
files before truncating them (and keeping about a weeks worth on hand).
|
||||
No login times are collected however, if the file does not exist.
|
||||
files, keeping a week's worth of data on
|
||||
hand. No login or connect time accounting is performed if
|
||||
.Pa /var/log/wtmp
|
||||
does not exist.
|
||||
.Pp
|
||||
For example,
|
||||
.Bd -literal -offset
|
||||
ac -p -t "ttyd*" > modems
|
||||
ac -p -t "!ttyd*" > other
|
||||
.Ed
|
||||
.Pp
|
||||
allows times recorded in
|
||||
.Pa modems
|
||||
to be charged out at a different rate than
|
||||
.Pa other .
|
||||
.Pp
|
||||
The
|
||||
.Nm ac
|
||||
utility exits 0 on success, and >0 if a fatal error occurs.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/log/wtmp.[0-7] -compact
|
||||
.It Pa /var/log/wtmp
|
||||
connect time accounting file
|
||||
.It Pa /var/log/wtmp.[0-7]
|
||||
rotated files
|
||||
.El
|
||||
@ -100,8 +132,24 @@ rotated files
|
||||
.Xr init 8 ,
|
||||
.Xr sa 8 ,
|
||||
.Xr login 1 ,
|
||||
.Xr utmp 5 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in Version 6 AT&T UNIX.
|
||||
.Xr utmp
|
||||
.\" .Sh NOTES
|
||||
.\" If COMPAT_SUNOS is defined
|
||||
.\" .Nm ac
|
||||
.\" ignores the fact that entries with ut_host of ":0.0" are not real
|
||||
.\" login sessions. Normally such entries are ignored except in the case
|
||||
.\" of a user being logged in when the
|
||||
.\" .Pa wtmp
|
||||
.\" file was rotated, in which case a login with ut_host of ":0.0" may
|
||||
.\" appear without any preceeding console logins.
|
||||
.\" If no one is logged in on the console, the user is deemed to have
|
||||
.\" logged in on at the earliest time stamp found in
|
||||
.\" .Pa wtmp .
|
||||
.\" Use of
|
||||
.\" .Pa console
|
||||
.\" allows
|
||||
.\" .Nm ac
|
||||
.\" to identify and correcty process a logout for the user. The default
|
||||
.\" value for
|
||||
.\" .Pa console
|
||||
.\" is usually correct at compile time.
|
||||
|
557
usr.sbin/ac/ac.c
Normal file
557
usr.sbin/ac/ac.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright (c) 1994 Christopher G. Demetriou.
|
||||
* @(#)Copyright (c) 1994, Simon J. Gerraty.
|
||||
*
|
||||
* This is free software. It comes with NO WARRANTY.
|
||||
* Permission to use, modify and distribute this source code
|
||||
* is granted subject to the following conditions.
|
||||
* 1/ that the above copyright notice and this notice
|
||||
* are preserved in all copies and that due credit be given
|
||||
* to the author.
|
||||
* 2/ that any changes to this code are clearly commented
|
||||
* as such so that the author does not get blamed for bugs
|
||||
* other than his own.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: ac.c,v 1.1.1.1 1994/05/18 08:00:45 csgr Exp $";
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utmp.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* this is for our list of currently logged in sessions
|
||||
*/
|
||||
struct utmp_list {
|
||||
struct utmp_list *next;
|
||||
struct utmp usr;
|
||||
};
|
||||
|
||||
/*
|
||||
* this is for our list of users that are accumulating time.
|
||||
*/
|
||||
struct user_list {
|
||||
struct user_list *next;
|
||||
char name[UT_NAMESIZE+1];
|
||||
time_t secs;
|
||||
};
|
||||
|
||||
/*
|
||||
* this is for chosing whether to ignore a login
|
||||
*/
|
||||
struct tty_list {
|
||||
struct tty_list *next;
|
||||
char name[UT_LINESIZE+3];
|
||||
int len;
|
||||
int ret;
|
||||
};
|
||||
|
||||
/*
|
||||
* globals - yes yuk
|
||||
*/
|
||||
#ifdef CONSOLE_TTY
|
||||
static char *Console = CONSOLE_TTY;
|
||||
#endif
|
||||
static time_t Total = 0;
|
||||
static time_t FirstTime = 0;
|
||||
static int Flags = 0;
|
||||
static struct user_list *Users = NULL;
|
||||
static struct tty_list *Ttys = NULL;
|
||||
|
||||
#define NEW(type) (type *)malloc(sizeof (type))
|
||||
|
||||
#define AC_W 1 /* not _PATH_WTMP */
|
||||
#define AC_D 2 /* daily totals (ignore -p) */
|
||||
#define AC_P 4 /* per-user totals */
|
||||
#define AC_U 8 /* specified users only */
|
||||
#define AC_T 16 /* specified ttys only */
|
||||
|
||||
#ifdef DEBUG
|
||||
static int Debug = 0;
|
||||
#endif
|
||||
|
||||
int main __P((int, char **));
|
||||
int ac __P((FILE *));
|
||||
struct tty_list *add_tty __P((char *));
|
||||
int do_tty __P((char *));
|
||||
FILE *file __P((char *));
|
||||
struct utmp_list *log_in __P((struct utmp_list *, struct utmp *));
|
||||
struct utmp_list *log_out __P((struct utmp_list *, struct utmp *));
|
||||
int on_console __P((struct utmp_list *));
|
||||
void show __P((char *, time_t));
|
||||
void show_today __P((struct user_list *, struct utmp_list *,
|
||||
time_t));
|
||||
void show_users __P((struct user_list *));
|
||||
struct user_list *update_user __P((struct user_list *, char *, time_t));
|
||||
void usage __P((void));
|
||||
|
||||
/*
|
||||
* open wtmp or die
|
||||
*/
|
||||
FILE *
|
||||
file(name)
|
||||
char *name;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL)
|
||||
err(1, "%s", name);
|
||||
/* in case we want to discriminate */
|
||||
if (strcmp(_PATH_WTMP, name))
|
||||
Flags |= AC_W;
|
||||
return fp;
|
||||
}
|
||||
|
||||
struct tty_list *
|
||||
add_tty(name)
|
||||
char *name;
|
||||
{
|
||||
struct tty_list *tp;
|
||||
register char *rcp;
|
||||
|
||||
Flags |= AC_T;
|
||||
|
||||
if ((tp = NEW(struct tty_list)) == NULL)
|
||||
err(1, "malloc");
|
||||
tp->len = 0; /* full match */
|
||||
tp->ret = 1; /* do if match */
|
||||
if (*name == '!') { /* don't do if match */
|
||||
tp->ret = 0;
|
||||
name++;
|
||||
}
|
||||
(void)strncpy(tp->name, name, sizeof (tp->name) - 1);
|
||||
tp->name[sizeof (tp->name) - 1] = '\0';
|
||||
if ((rcp = strchr(tp->name, '*')) != NULL) { /* wild card */
|
||||
*rcp = '\0';
|
||||
tp->len = strlen(tp->name); /* match len bytes only */
|
||||
}
|
||||
tp->next = Ttys;
|
||||
Ttys = tp;
|
||||
return Ttys;
|
||||
}
|
||||
|
||||
/*
|
||||
* should we process the named tty?
|
||||
*/
|
||||
int
|
||||
do_tty(name)
|
||||
char *name;
|
||||
{
|
||||
struct tty_list *tp;
|
||||
int def_ret = 0;
|
||||
|
||||
for (tp = Ttys; tp != NULL; tp = tp->next) {
|
||||
if (tp->ret == 0) /* specific don't */
|
||||
def_ret = 1; /* default do */
|
||||
if (tp->len != 0) {
|
||||
if (strncmp(name, tp->name, tp->len) == 0)
|
||||
return tp->ret;
|
||||
} else {
|
||||
if (strncmp(name, tp->name, sizeof (tp->name)) == 0)
|
||||
return tp->ret;
|
||||
}
|
||||
}
|
||||
return def_ret;
|
||||
}
|
||||
|
||||
#ifdef CONSOLE_TTY
|
||||
/*
|
||||
* is someone logged in on Console?
|
||||
*/
|
||||
int
|
||||
on_console(head)
|
||||
struct utmp_list *head;
|
||||
{
|
||||
struct utmp_list *up;
|
||||
|
||||
for (up = head; up; up = up->next) {
|
||||
if (strncmp(up->usr.ut_line, Console,
|
||||
sizeof (up->usr.ut_line)) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update user's login time
|
||||
*/
|
||||
struct user_list *
|
||||
update_user(head, name, secs)
|
||||
struct user_list *head;
|
||||
char *name;
|
||||
time_t secs;
|
||||
{
|
||||
struct user_list *up;
|
||||
|
||||
for (up = head; up != NULL; up = up->next) {
|
||||
if (strncmp(up->name, name, sizeof (up->name)) == 0) {
|
||||
up->secs += secs;
|
||||
Total += secs;
|
||||
return head;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* not found so add new user unless specified users only
|
||||
*/
|
||||
if (Flags & AC_U)
|
||||
return head;
|
||||
|
||||
if ((up = NEW(struct user_list)) == NULL)
|
||||
err(1, "malloc");
|
||||
up->next = head;
|
||||
(void)strncpy(up->name, name, sizeof (up->name) - 1);
|
||||
up->name[sizeof (up->name) - 1] = '\0'; /* paranoid! */
|
||||
up->secs = secs;
|
||||
Total += secs;
|
||||
return up;
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
FILE *fp;
|
||||
int c;
|
||||
|
||||
fp = NULL;
|
||||
while ((c = getopt(argc, argv, "Dc:dpt:w:")) != EOF) {
|
||||
switch (c) {
|
||||
#ifdef DEBUG
|
||||
case 'D':
|
||||
Debug++;
|
||||
break;
|
||||
#endif
|
||||
case 'c':
|
||||
#ifdef CONSOLE_TTY
|
||||
Console = optarg;
|
||||
#else
|
||||
usage(); /* XXX */
|
||||
#endif
|
||||
break;
|
||||
case 'd':
|
||||
Flags |= AC_D;
|
||||
break;
|
||||
case 'p':
|
||||
Flags |= AC_P;
|
||||
break;
|
||||
case 't': /* only do specified ttys */
|
||||
add_tty(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
fp = file(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
/*
|
||||
* initialize user list
|
||||
*/
|
||||
for (; optind < argc; optind++) {
|
||||
Users = update_user(Users, argv[optind], 0L);
|
||||
}
|
||||
Flags |= AC_U; /* freeze user list */
|
||||
}
|
||||
if (Flags & AC_D)
|
||||
Flags &= ~AC_P;
|
||||
if (fp == NULL) {
|
||||
/*
|
||||
* if _PATH_WTMP does not exist, exit quietly
|
||||
*/
|
||||
if (access(_PATH_WTMP, 0) != 0 && errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
fp = file(_PATH_WTMP);
|
||||
}
|
||||
ac(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* print login time in decimal hours
|
||||
*/
|
||||
void
|
||||
show(name, secs)
|
||||
char *name;
|
||||
time_t secs;
|
||||
{
|
||||
(void)printf("\t%-*s %8.2f\n", UT_NAMESIZE, name,
|
||||
((double)secs / 3600));
|
||||
}
|
||||
|
||||
void
|
||||
show_users(list)
|
||||
struct user_list *list;
|
||||
{
|
||||
struct user_list *lp;
|
||||
|
||||
for (lp = list; lp; lp = lp->next)
|
||||
show(lp->name, lp->secs);
|
||||
}
|
||||
|
||||
/*
|
||||
* print total login time for 24hr period in decimal hours
|
||||
*/
|
||||
void
|
||||
show_today(users, logins, secs)
|
||||
struct user_list *users;
|
||||
struct utmp_list *logins;
|
||||
time_t secs;
|
||||
{
|
||||
struct user_list *up;
|
||||
struct utmp_list *lp;
|
||||
char date[64];
|
||||
time_t yesterday = secs - 1;
|
||||
|
||||
(void)strftime(date, sizeof (date), "%b %e total",
|
||||
localtime(&yesterday));
|
||||
|
||||
/* restore the missing second */
|
||||
yesterday++;
|
||||
|
||||
for (lp = logins; lp != NULL; lp = lp->next) {
|
||||
secs = yesterday - lp->usr.ut_time;
|
||||
Users = update_user(Users, lp->usr.ut_name, secs);
|
||||
lp->usr.ut_time = yesterday; /* as if they just logged in */
|
||||
}
|
||||
secs = 0;
|
||||
for (up = users; up != NULL; up = up->next) {
|
||||
secs += up->secs;
|
||||
up->secs = 0; /* for next day */
|
||||
}
|
||||
if (secs)
|
||||
(void)printf("%s %11.2f\n", date, ((double)secs / 3600));
|
||||
}
|
||||
|
||||
/*
|
||||
* log a user out and update their times.
|
||||
* if ut_line is "~", we log all users out as the system has
|
||||
* been shut down.
|
||||
*/
|
||||
struct utmp_list *
|
||||
log_out(head, up)
|
||||
struct utmp_list *head;
|
||||
struct utmp *up;
|
||||
{
|
||||
struct utmp_list *lp, *lp2, *tlp;
|
||||
time_t secs;
|
||||
|
||||
for (lp = head, lp2 = NULL; lp != NULL; )
|
||||
if (*up->ut_line == '~' || strncmp(lp->usr.ut_line, up->ut_line,
|
||||
sizeof (up->ut_line)) == 0) {
|
||||
secs = up->ut_time - lp->usr.ut_time;
|
||||
Users = update_user(Users, lp->usr.ut_name, secs);
|
||||
#ifdef DEBUG
|
||||
if (Debug)
|
||||
printf("%-.*s %-.*s: %-.*s logged out (%2d:%02d:%02d)\n",
|
||||
19, ctime(&up->ut_time),
|
||||
sizeof (lp->usr.ut_line), lp->usr.ut_line,
|
||||
sizeof (lp->usr.ut_name), lp->usr.ut_name,
|
||||
secs / 3600, (secs % 3600) / 60, secs % 60);
|
||||
#endif
|
||||
/*
|
||||
* now lose it
|
||||
*/
|
||||
tlp = lp;
|
||||
lp = lp->next;
|
||||
if (tlp == head)
|
||||
head = lp;
|
||||
else if (lp2 != NULL)
|
||||
lp2->next = lp;
|
||||
free(tlp);
|
||||
} else {
|
||||
lp2 = lp;
|
||||
lp = lp->next;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if do_tty says ok, login a user
|
||||
*/
|
||||
struct utmp_list *
|
||||
log_in(head, up)
|
||||
struct utmp_list *head;
|
||||
struct utmp *up;
|
||||
{
|
||||
struct utmp_list *lp;
|
||||
|
||||
/*
|
||||
* this could be a login. if we're not dealing with
|
||||
* the console name, say it is.
|
||||
*
|
||||
* If we are, and if ut_host==":0.0" we know that it
|
||||
* isn't a real login. _But_ if we have not yet recorded
|
||||
* someone being logged in on Console - due to the wtmp
|
||||
* file starting after they logged in, we'll pretend they
|
||||
* logged in, at the start of the wtmp file.
|
||||
*/
|
||||
|
||||
#ifdef CONSOLE_TTY
|
||||
if (up->ut_host[0] == ':') {
|
||||
/*
|
||||
* SunOS 4.0.2 does not treat ":0.0" as special but we
|
||||
* do.
|
||||
*/
|
||||
if (on_console(head))
|
||||
return head;
|
||||
/*
|
||||
* ok, no recorded login, so they were here when wtmp
|
||||
* started! Adjust ut_time!
|
||||
*/
|
||||
up->ut_time = FirstTime;
|
||||
/*
|
||||
* this allows us to pick the right logout
|
||||
*/
|
||||
(void)strncpy(up->ut_line, Console, sizeof (up->ut_line) - 1);
|
||||
up->ut_line[sizeof (up->ut_line) - 1] = '\0'; /* paranoid! */
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If we are doing specified ttys only, we ignore
|
||||
* anything else.
|
||||
*/
|
||||
if (Flags & AC_T)
|
||||
if (!do_tty(up->ut_line))
|
||||
return head;
|
||||
|
||||
/*
|
||||
* go ahead and log them in
|
||||
*/
|
||||
if ((lp = NEW(struct utmp_list)) == NULL)
|
||||
err(1, "malloc");
|
||||
lp->next = head;
|
||||
head = lp;
|
||||
memmove((char *)&lp->usr, (char *)up, sizeof (struct utmp));
|
||||
#ifdef DEBUG
|
||||
if (Debug) {
|
||||
printf("%-.*s %-.*s: %-.*s logged in", 19,
|
||||
ctime(&lp->usr.ut_time), sizeof (up->ut_line),
|
||||
up->ut_line, sizeof (up->ut_name), up->ut_name);
|
||||
if (*up->ut_host)
|
||||
printf(" (%-.*s)", sizeof (up->ut_host), up->ut_host);
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
return head;
|
||||
}
|
||||
|
||||
int
|
||||
ac(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
struct utmp_list *lp, *head = NULL;
|
||||
struct utmp usr;
|
||||
struct tm *ltm;
|
||||
time_t secs;
|
||||
int day = -1;
|
||||
|
||||
while (fread((char *)&usr, sizeof(usr), 1, fp) == 1) {
|
||||
if (!FirstTime)
|
||||
FirstTime = usr.ut_time;
|
||||
if (Flags & AC_D) {
|
||||
ltm = localtime(&usr.ut_time);
|
||||
if (day >= 0 && day != ltm->tm_yday) {
|
||||
day = ltm->tm_yday;
|
||||
/*
|
||||
* print yesterday's total
|
||||
*/
|
||||
secs = usr.ut_time;
|
||||
secs -= ltm->tm_sec;
|
||||
secs -= 60 * ltm->tm_min;
|
||||
secs -= 3600 * ltm->tm_hour;
|
||||
show_today(Users, head, secs);
|
||||
} else
|
||||
day = ltm->tm_yday;
|
||||
}
|
||||
switch(*usr.ut_line) {
|
||||
case '|':
|
||||
secs = usr.ut_time;
|
||||
break;
|
||||
case '{':
|
||||
secs -= usr.ut_time;
|
||||
/*
|
||||
* adjust time for those logged in
|
||||
*/
|
||||
for (lp = head; lp != NULL; lp = lp->next)
|
||||
lp->usr.ut_time -= secs;
|
||||
break;
|
||||
case '~': /* reboot or shutdown */
|
||||
head = log_out(head, &usr);
|
||||
FirstTime = usr.ut_time; /* shouldn't be needed */
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* if they came in on tty[p-y]*, then it is only
|
||||
* a login session if the ut_host field is non-empty
|
||||
*/
|
||||
if (*usr.ut_name) {
|
||||
if (strncmp(usr.ut_line, "tty", 3) != 0 ||
|
||||
strchr("pqrstuvwxy", usr.ut_line[3]) == 0 ||
|
||||
*usr.ut_host != '\0')
|
||||
head = log_in(head, &usr);
|
||||
} else
|
||||
head = log_out(head, &usr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void)fclose(fp);
|
||||
usr.ut_time = time((time_t *)0);
|
||||
(void)strcpy(usr.ut_line, "~");
|
||||
|
||||
if (Flags & AC_D) {
|
||||
ltm = localtime(&usr.ut_time);
|
||||
if (day >= 0 && day != ltm->tm_yday) {
|
||||
/*
|
||||
* print yesterday's total
|
||||
*/
|
||||
secs = usr.ut_time;
|
||||
secs -= ltm->tm_sec;
|
||||
secs -= 60 * ltm->tm_min;
|
||||
secs -= 3600 * ltm->tm_hour;
|
||||
show_today(Users, head, secs);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* anyone still logged in gets time up to now
|
||||
*/
|
||||
head = log_out(head, &usr);
|
||||
|
||||
if (Flags & AC_D)
|
||||
show_today(Users, head, time((time_t *)0));
|
||||
else {
|
||||
if (Flags & AC_P)
|
||||
show_users(Users);
|
||||
show("total", Total);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
#ifdef CONSOLE_TTY
|
||||
"ac [-dp] [-c console] [-t tty] [-w wtmp] [users ...]\n");
|
||||
#else
|
||||
"ac [-dp] [-t tty] [-w wtmp] [users ...]\n");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user