BSD 3 development
[unix-history] / usr / src / cmd / last.c
#
/*
* NAME: last
*
* SYNOPSIS: last [list]
*
* DESCRIPTION: Displays login history of named users or tty's.
* Last with no argument prints history for all users.
*
* AUTHOR - Howard P. Katseff
*/
# include <sys/types.h>
# include <stdio.h>
# include <stat.h>
# include <utmp.h>
char yes = 1,
no = 0,
*wtmp = "/usr/adm/wtmp",
b [512],
Arg [25] [9],
tty_names [48] [9],
*ctime (),
*move (),
*rmchar ();
long logouts [48],
bl,
rec,
nblock;
struct utmp buf [128]; /* buf takes exactly 5 blocks */
main (argc, argv)
char **argv;
{
char f,
narg,
*bend,
*p,
*q;
short n_byte,
n_record;
long i,
k,
ntime,
otime,
intrp ();
struct stat sbuf;
for (i = 1; i < argc; i++)
{
if
(
length (argv [i]) > 2 /* long tty or user name */
||
equal (argv [i], "~") /* tilde */
||
getpwnam (argv [i]) /* user name */
)
{
move (argv [i], Arg [narg++]);
}
else /* short tty name */
{
move (argv [i], move ("tty", Arg [narg++]));
}
}
f = open (wtmp, 0);
if (f < 0)
{
perror (wtmp);
fflush (stdout);
exit ();
}
if (fstat (f, &sbuf) < 0)
{
perror ("/usr/adm/wtmp");
fflush (stdout);
exit ();
}
nblock = (sbuf.st_size + 2559) / 2560;
signal (2, intrp);
for (bl = nblock - 1; bl >= 0; bl--)
{
lseek (f, bl * 2560, 0);
n_byte = read (f, buf, 2560);
n_record = n_byte / sizeof buf [0];
for (rec = n_record - 1; rec >= 0; rec--)
{
if (should_print ())
{
q = ctime (&buf[rec].ut_time);
printf
(
"%-8.8s %-8.8s %10.10s %5.5s ",
buf[rec].ut_name, buf[rec].ut_line, q, 11+q
);
otime = buf[rec].ut_time;
/*
* look up the logout time for the tty
*/
for (i = 0;; i++)
{
if (!*tty_names [i])
/* not in the table, therefore add it */
{
move
(
buf[rec].ut_line,
tty_names [i]
);
ntime = 0;
break;
}
if
(
equal
(
tty_names [i],
buf [rec].ut_line
)
)
{
ntime = logouts [i];
break;
}
}
if (ntime == 0)
{
printf (" still logged in\n");
}
else
{
if (ntime < 0)
{
ntime = -ntime;
printf ("- crash");
}
else
{
printf ("- %5.5s", ctime (&ntime) + 11);
}
/*
* calculate how long logged in
*/
otime = ntime - otime;
otime += 231220830 + 10800;
if (otime < 231220830 + 86400 + 10800)
{
printf
(
" (%5.5s)\n",
ctime (&otime) + 11
);
}
else
{
printf
(
" (%ld+%5.5s)\n",
(otime -
(231330830-86400-10800))/86400,
ctime (&otime) + 11
);
}
}
fflush (stdout);
}
if
(
equal (buf[rec].ut_line, "~")
||
equal (buf[rec].ut_line, "tty~")
)
{
for (i = 0; *tty_names [i]; i++)
{
logouts [i] = -buf[rec].ut_time;
}
}
else
{
for (k = 0;; k++)
{
if (!*tty_names [k])
{
move
(
buf[rec].ut_line,
tty_names [k]
);
logouts [k] = buf[rec].ut_time;
break;
}
if (equal (tty_names [k], buf[rec].ut_line))
{
logouts [k] = buf[rec].ut_time;
break;
}
}
}
}
}
q = ctime (&buf [0].ut_time);
printf
(
"\nwtmp begins %10.10s %5.5s \n",
q, q + 11
);
}
equal (a, b)
char *a, *b;
{
char i;
for (i = 0; i < 8; i++)
{
if (!*a) return (!*b);
if (*a++ != *b++) return (0);
}
return (1);
}
intrp ()
{
char *q;
signal (2, 1); /* ignore further interrupts */
q = ctime (&buf[rec].ut_time);
printf
(
"\ninterrupted %10.10s %5.5s \n",
q, q + 11
);
exit ();
}
char *
rmchar (c, s)
char c, *s;
{
for (; *s; s++)
{
if (*s == c)
{
*s = 0;
return (s);
}
}
return (0);
}
length (a)
char *a;
{
char *b;
for (b = a; *b; b++);
return (b - a);
}
char *
move (a, b)
char *a, *b;
{
while (*b++ = *a++);
return (b - 1);
}
should_print ()
{
short i;
if (buf [rec].ut_name [0] == no) return no; /* a logout entry */
if (!**Arg) return yes; /* no arguments? Print all login entries */
for (i = 0; i < *Arg [i]; i++)
{
if
(
equal (Arg [i], buf[rec].ut_name)
||
equal (Arg [i], buf[rec].ut_line)
)
return yes;
}
return no;
}