Fixed a bug that caused last(1) to be extremely slow in some cases, and

made other performance improving changes. This improves the performance
of last(1) by as much as 32 times in some cases, and in more typical cases
is about twice as fast.
Added a BUGS section to the manual page to describe the behavior of last(1)
when a login shell terminates abnormally (and thus doesn't write a logout
record to the wtmp file).
This commit is contained in:
David Greenman 1995-10-17 18:26:43 +00:00
parent 9123d7efcf
commit c83d3f4574
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=11547
2 changed files with 84 additions and 84 deletions

View file

@ -117,6 +117,11 @@ login data base
.Xr lastcomm 1 ,
.Xr utmp 5 ,
.Xr ac 8
.Sh BUGS
If a login shell should terminate abnormally for some reason, it is likely
that a logout record won't be written to the wtmp file. In this case,
.Nm last
will indicate the logout time as "shutdown".
.Sh HISTORY
.Nm Last
appeared in

View file

@ -54,6 +54,7 @@ static char sccsid[] = "@(#)last.c 8.2 (Berkeley) 4/2/94";
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#include <sys/queue.h>
#define NO 0 /* false/no */
#define YES 1 /* true/yes */
@ -70,23 +71,23 @@ typedef struct arg {
} ARG;
ARG *arglist; /* head of linked list */
typedef struct ttytab {
LIST_HEAD(ttylisthead, ttytab) ttylist;
struct ttytab {
long logout; /* log out time */
char tty[UT_LINESIZE + 1]; /* terminal name */
struct ttytab *next; /* linked list pointer */
} TTY;
TTY *ttylist; /* head of linked list */
LIST_ENTRY(ttytab) list;
};
static long currentout, /* current logout value */
maxrec; /* records to display */
static char *file = _PATH_WTMP; /* wtmp file */
void addarg __P((int, char *));
TTY *addtty __P((char *));
void hostconv __P((char *));
void onintr __P((int));
char *ttyconv __P((char *));
int want __P((struct utmp *, int));
int want __P((struct utmp *));
void wtmp __P((void));
int
@ -158,12 +159,14 @@ void
wtmp()
{
struct utmp *bp; /* current structure */
TTY *T; /* tty list entry */
struct ttytab *tt; /* ttylist entry */
struct stat stb; /* stat of file for size */
long bl, delta; /* time difference */
int bytes, wfd;
char *ct, *crmsg;
LIST_INIT(&ttylist);
if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
err(1, "%s", file);
bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
@ -183,14 +186,16 @@ wtmp()
*/
if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
/* everybody just logged out */
for (T = ttylist; T; T = T->next)
T->logout = -bp->ut_time;
for (tt = ttylist.lh_first; tt; tt = tt->list.le_next) {
LIST_REMOVE(tt, list);
free(tt);
}
currentout = -bp->ut_time;
crmsg = strncmp(bp->ut_name, "shutdown",
UT_NAMESIZE) ? "crash" : "shutdown";
if (want(bp, NO)) {
if (want(bp)) {
ct = ctime(&bp->ut_time);
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n",
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n",
UT_NAMESIZE, UT_NAMESIZE,
bp->ut_name, UT_LINESIZE,
UT_LINESIZE, bp->ut_line,
@ -207,58 +212,77 @@ wtmp()
*/
if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
&& !bp->ut_line[1]) {
if (want(bp, NO)) {
if (want(bp)) {
ct = ctime(&bp->ut_time);
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n",
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
UT_LINESIZE, UT_LINESIZE, bp->ut_line,
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
ct, ct + 11);
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n",
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
UT_LINESIZE, UT_LINESIZE, bp->ut_line,
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
ct, ct + 11);
if (maxrec && !--maxrec)
return;
}
continue;
}
/* find associated tty */
for (T = ttylist;; T = T->next) {
if (!T) {
/* add new one */
T = addtty(bp->ut_line);
break;
}
if (!strncmp(T->tty, bp->ut_line, UT_LINESIZE))
break;
}
if (bp->ut_name[0] && want(bp, YES)) {
ct = ctime(&bp->ut_time);
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
UT_LINESIZE, UT_LINESIZE, bp->ut_line,
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
ct, ct + 11);
if (!T->logout)
puts(" still logged in");
else {
if (T->logout < 0) {
T->logout = -T->logout;
printf("- %s", crmsg);
if (bp->ut_name[0] == '\0' || want(bp)) {
/* find associated tty */
for (tt = ttylist.lh_first; ; tt = tt->list.le_next) {
if (tt == NULL) {
/* add new one */
tt = malloc(sizeof(struct ttytab));
if (tt == NULL)
err(1, "malloc failure");
tt->logout = currentout;
strncpy(tt->tty, bp->ut_line, UT_LINESIZE);
LIST_INSERT_HEAD(&ttylist, tt, list);
break;
}
else
printf("- %5.5s",
ctime(&T->logout)+11);
delta = T->logout - bp->ut_time;
if (delta < 86400)
printf(" (%5.5s)\n",
asctime(gmtime(&delta))+11);
else
printf(" (%ld+%5.5s)\n",
delta / 86400,
asctime(gmtime(&delta))+11);
if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE))
break;
}
if (bp->ut_name[0]) {
/*
* when uucp and ftp log in over a network, the entry in
* the utmp file is the name plus their process id. See
* etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
*/
if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
bp->ut_line[3] = '\0';
else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
bp->ut_line[4] = '\0';
ct = ctime(&bp->ut_time);
printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
UT_LINESIZE, UT_LINESIZE, bp->ut_line,
UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
ct, ct + 11);
if (!tt->logout)
puts(" still logged in");
else {
if (tt->logout < 0) {
tt->logout = -tt->logout;
printf("- %s", crmsg);
}
else
printf("- %5.5s",
ctime(&tt->logout)+11);
delta = tt->logout - bp->ut_time;
if (delta < 86400)
printf(" (%5.5s)\n",
asctime(gmtime(&delta))+11);
else
printf(" (%ld+%5.5s)\n",
delta / 86400,
asctime(gmtime(&delta))+11);
}
LIST_REMOVE(tt, list);
free(tt);
if (maxrec != -1 && !--maxrec)
return;
} else {
tt->logout = bp->ut_time;
}
if (maxrec != -1 && !--maxrec)
return;
}
T->logout = bp->ut_time;
}
}
ct = ctime(&buf[0].ut_time);
@ -270,22 +294,11 @@ wtmp()
* see if want this entry
*/
int
want(bp, check)
want(bp)
struct utmp *bp;
int check;
{
ARG *step;
if (check)
/*
* when uucp and ftp log in over a network, the entry in
* the utmp file is the name plus their process id. See
* etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
*/
if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
bp->ut_line[3] = '\0';
else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
bp->ut_line[4] = '\0';
if (!arglist)
return (YES);
@ -326,24 +339,6 @@ addarg(type, arg)
arglist = cur;
}
/*
* addtty --
* add an entry to a linked list of ttys
*/
TTY *
addtty(ttyname)
char *ttyname;
{
TTY *cur;
if (!(cur = (TTY *)malloc((u_int)sizeof(TTY))))
err(1, "malloc failure");
cur->next = ttylist;
cur->logout = currentout;
memmove(cur->tty, ttyname, UT_LINESIZE);
return (ttylist = cur);
}
/*
* hostconv --
* convert the hostname to search pattern; if the supplied host name