Initial commit of last utility

This commit is contained in:
taubert 1998-02-09 08:58:52 +00:00
parent 6bd94b0884
commit 829e7d0929
5 changed files with 594 additions and 0 deletions

6
usr.bin/last/Makefile Normal file
View File

@ -0,0 +1,6 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $Id: Makefile,v 1.1 1998/02/09 08:58:47 taubert Exp $
PROG= last
.INCLUDE: /src/gno/prog.mk

123
usr.bin/last/last.1 Normal file
View File

@ -0,0 +1,123 @@
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" 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 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.
.\"
.\" @(#)last.1 8.1 (Berkeley) 6/6/93
.\"
.Dd June 6, 1993
.Dt LAST 1
.Os BSD 4
.Sh NAME
.Nm last
.Nd indicate last logins of users and ttys
.Sh SYNOPSIS
.Nm last
.Op Fl Ns Ar n
.Op Fl f Ar file
.Op Fl h Ar host
.Op Fl t Ar tty
.Op user ...
.Sh DESCRIPTION
.Nm Last
will list the sessions of specified
.Ar users ,
.Ar ttys ,
and
.Ar hosts ,
in reverse time order. Each line of output contains
the user name, the tty from which the session was conducted, any
hostname, the start and stop times for the session, and the duration
of the session. If the session is still continuing or was cut short by
a crash or shutdown,
.Nm last
will so indicate.
.Pp
.Bl -tag -width indent-two
.It Fl f Ar file
.Nm Last
reads the file
.Ar file
instead of the default,
.Pa /var/log/wtmp .
.It Fl Ar n
Limits the report to
.Ar n
lines.
.It Fl t Ar tty
Specify the
.Ar tty .
Tty names may be given fully or abbreviated, for example,
.Dq Li "last -t 03"
is
equivalent to
.Dq Li "last -t tty03" .
.It Fl h Ar host
.Ar Host
names may be names or internet numbers.
.El
.Pp
If
multiple arguments are given, the information which applies to any of the
arguments is printed, e.g.,
.Dq Li "last root -t console"
would list all of
.Dq Li root Ns 's
sessions as well as all sessions on the console terminal. If no
users, hostnames or terminals are specified,
.Nm last
prints a record of
all logins and logouts.
.Pp
The pseudo-user
.Ar reboot
logs in at reboots of the system, thus
.Dq Li last reboot
will give an indication of mean time between reboot.
.Pp
If
.Nm last
is interrupted, it indicates to what date the search has
progressed. If interrupted with a quit signal
.Nm last
indicates how
far the search has progressed and then continues.
.Sh FILES
.Bl -tag -width /var/log/wtmp -compact
.It Pa /var/log/wtmp
login data base
.El
.Sh SEE ALSO
.Xr lastcomm 1 ,
.Xr utmp 5 ,
.Xr ac 8
.Sh HISTORY
.Nm Last
appeared in
.Bx 3.0 .

425
usr.bin/last/last.c Normal file
View File

@ -0,0 +1,425 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 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 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1987, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)last.c 8.2 (Berkeley) 4/2/94";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#define NO 0 /* false/no */
#define YES 1 /* true/yes */
#ifdef __GNO__
static struct utmp buf[512]; /* utmp read buffer */
#else
static struct utmp buf[1024]; /* utmp read buffer */
#endif
typedef struct arg {
char *name; /* argument */
#define HOST_TYPE -2
#define TTY_TYPE -3
#define USER_TYPE -4
int type; /* type of arg */
struct arg *next; /* linked list pointer */
} ARG;
ARG *arglist; /* head of linked list */
typedef 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 */
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, int));
char *ttyconv __P((char *));
int want __P((struct utmp *, int));
void wtmp __P((void));
int
main(int argc, char **argv)
{
extern int optind;
extern char *optarg;
int ch;
char *p;
maxrec = -1;
while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/*
* kludge: last was originally designed to take
* a number after a dash.
*/
if (maxrec == -1) {
p = argv[optind - 1];
if (p[0] == '-' && p[1] == ch && !p[2])
maxrec = atol(++p);
else
maxrec = atol(argv[optind] + 1);
if (!maxrec)
exit(0);
}
break;
case 'f':
file = optarg;
break;
case 'h':
hostconv(optarg);
addarg(HOST_TYPE, optarg);
break;
case 't':
addarg(TTY_TYPE, ttyconv(optarg));
break;
case '?':
default:
(void)fprintf(stderr,
"usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n");
exit(1);
}
if (argc) {
setlinebuf(stdout);
for (argv += optind; *argv; ++argv) {
#define COMPATIBILITY
#ifdef COMPATIBILITY
/* code to allow "last p5" to work */
addarg(TTY_TYPE, ttyconv(*argv));
#endif
addarg(USER_TYPE, *argv);
}
}
wtmp();
exit(0);
}
/*
* wtmp --
* read through the wtmp file
*/
void
wtmp(void)
{
struct utmp *bp; /* current structure */
TTY *T; /* tty list entry */
static struct stat stb; /* stat of file for size */
long bl, delta; /* time difference */
int bytes, wfd;
char *ct, *crmsg;
#ifdef __ORCAC__
if ((wfd = open(file, O_RDONLY)) < 0 || fstat(wfd, &stb) == -1)
#else
if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
#endif
err(1, "%s", file);
bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
(void)time(&buf[0].ut_time);
(void)signal(SIGINT, onintr);
(void)signal(SIGQUIT, onintr);
while (--bl >= 0) {
if (lseek(wfd, (off_t)(bl * sizeof(buf)), L_SET) == -1 ||
(bytes = read(wfd, buf, sizeof(buf))) == -1)
err(1, "%s", file);
for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
/*
* if the terminal line is '~', the machine stopped.
* see utmp(5) for more info.
*/
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;
currentout = -bp->ut_time;
crmsg = strncmp(bp->ut_name, "shutdown",
UT_NAMESIZE) ? "crash" : "shutdown";
if (want(bp, NO)) {
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);
if (maxrec != -1 && !--maxrec)
return;
}
continue;
}
/*
* if the line is '{' or '|', date got set; see
* utmp(5) for more info.
*/
if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
&& !bp->ut_line[1]) {
if (want(bp, NO)) {
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);
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);
}
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 (maxrec != -1 && !--maxrec)
return;
}
T->logout = bp->ut_time;
}
}
printf("ut_time = %lu\n", buf[0].ut_time);
printf("localtime(ut_time) = %p\n", localtime(&buf[0].ut_time));
ct = ctime(&buf[0].ut_time);
printf("ctime completed\n");
printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
}
/*
* want --
* see if want this entry
*/
int
want(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);
for (step = arglist; step; step = step->next)
switch(step->type) {
case HOST_TYPE:
if (!strncasecmp(step->name, bp->ut_host, UT_HOSTSIZE))
return (YES);
break;
case TTY_TYPE:
if (!strncmp(step->name, bp->ut_line, UT_LINESIZE))
return (YES);
break;
case USER_TYPE:
if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
return (YES);
break;
}
return (NO);
}
/*
* addarg --
* add an entry to a linked list of arguments
*/
void
addarg(int type, char *arg)
{
ARG *cur;
printf("addarg(%d, '%s')\n", type, arg);
if (!(cur = (ARG *)malloc((u_int)sizeof(ARG))))
err(1, "malloc failure");
cur->next = arglist;
cur->type = type;
cur->name = arg;
arglist = cur;
}
/*
* addtty --
* add an entry to a linked list of ttys
*/
TTY *
addtty(char *ttyname)
{
TTY *cur;
printf("addtty('%s')\n", ttyname);
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
* off the domain suffix since that's what login(1) does.
*/
void
hostconv(char *arg)
{
static int first = 1;
static char *hostdot, name[MAXHOSTNAMELEN];
char *argdot;
if (!(argdot = strchr(arg, '.')))
return;
if (first) {
first = 0;
if (gethostname(name, sizeof(name)))
err(1, "gethostname");
hostdot = strchr(name, '.');
}
if (hostdot && !strcasecmp(hostdot, argdot))
*argdot = '\0';
}
/*
* ttyconv --
* convert tty to correct name.
*/
char *
ttyconv(char *arg)
{
char *mval;
/*
* kludge -- we assume that all tty's end with
* a two character suffix.
*/
if (strlen(arg) == 2) {
/* either 6 for "ttyxx" or 8 for "console" */
if (!(mval = malloc((u_int)8)))
err(1, "malloc failure");
if (!strcmp(arg, "co"))
(void)strcpy(mval, "console");
else {
(void)strcpy(mval, "tty");
(void)strcpy(mval + 3, arg);
}
return (mval);
}
if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
return (arg + 5);
return (arg);
}
#pragma databank 1
/*
* onintr --
* on interrupt, we inform the user how far we've gotten
*/
void
onintr(int signo, int type)
{
char *ct;
ct = ctime(&buf[0].ut_time);
printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
if (signo == SIGINT)
exit(1);
(void)fflush(stdout); /* fix required for rsh */
}
#pragma databank 0

9
usr.bin/last/last.desc Normal file
View File

@ -0,0 +1,9 @@
Name: last
Version: 1.0 (February 1998)
Shell: GNO
Author: Derek Taubert (from FreeBSD 2.1.0 code)
Contact: taubert@geeks.org
Where: /usr/bin
FTP: ground.isca.uiowa.edu apple2.caltech.edu trenco.myrias.com
Indicate last logins of users.

31
usr.bin/last/last.rez Normal file
View File

@ -0,0 +1,31 @@
/*
* Resources for last version and comment
*
* $Id: last.rez,v 1.1 1998/02/09 08:58:52 taubert Exp $
*/
#define PROG "last"
#define DESC "Indicate last logins of users."
#include "Types.rez"
/*
* Version
*/
resource rVersion (1, purgeable3) {
{ 1, 0, 0, /* Version 1.0.0 */
release, /* development|alpha|beta|final|release */
0 }, /* non-final release number */
verUS, /* Country */
PROG, /* Program name */
DESC " Released with GNO/ME."
};
/*
* Comment
*/
resource rComment (1, purgeable3) {
PROG " v1.0 (February 1998)\n"
"GNO utility: " DESC "\n"
"Ported from FreeBSD 2.1.0 code by Derek Taubert."
};