summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-10-17 18:26:43 +0000
committerdg <dg@FreeBSD.org>1995-10-17 18:26:43 +0000
commitfb897fab5396fa2b16511052125aa59e2058604a (patch)
tree746c8318bb269f48282b683a4b718674f6a68a29 /usr.bin
parent85b40e7947ac4f883d699d92d617a998830b3592 (diff)
downloadFreeBSD-src-fb897fab5396fa2b16511052125aa59e2058604a.zip
FreeBSD-src-fb897fab5396fa2b16511052125aa59e2058604a.tar.gz
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).
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/last/last.15
-rw-r--r--usr.bin/last/last.c161
2 files changed, 83 insertions, 83 deletions
diff --git a/usr.bin/last/last.1 b/usr.bin/last/last.1
index 27a214d..c746d5b 100644
--- a/usr.bin/last/last.1
+++ b/usr.bin/last/last.1
@@ -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
diff --git a/usr.bin/last/last.c b/usr.bin/last/last.c
index 1d18600..ba7214f 100644
--- a/usr.bin/last/last.c
+++ b/usr.bin/last/last.c
@@ -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 (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;
+ }
+ if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE))
+ 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]) {
+ /*
+ * 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);
}
- 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);
+ 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);
@@ -327,24 +340,6 @@ addarg(type, arg)
}
/*
- * 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
* has a domain attached that is the same as the current domain, rip
OpenPOWER on IntegriCloud