[net.sources] lastlog - last login times for all users

RSanders@USGS2-MULTICS.ARPA (12/19/85)

"lastlog" prints the last login times for all users, based on
the times in /usr/adm/lastlog.  Lastlog was written on & for
VAX 4.2 BSD Unix, so I could drop users who had not logged in
in a long time.  Do what you like with this.

-- Rex

----- Cut Here -----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#         lastlog.8
#         lastlog.c
# This archive created: Thu Dec 19 01:45:19 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'lastlog.8'" '(967 characters)'
if test -f 'lastlog.8'
then
 echo shar: will not over-write existing file "'lastlog.8'"
else
sed 's/^X//' << \SHAR_EOF > 'lastlog.8'
X.lg 0
X.TH LASTLOG 8 LOCAL "USGS Pacific Marine Geology"
X.SH NAME
Xlastlog \- print last login time for all users
X.SH SYNOPSIS
X/etc/lastlog
X.SH DESCRIPTION
X.I Lastlog
Xprints the user name, last login date/time, and gecos field
Xfrom the password file, for each user in 
X.BR /etc/passwd ,
Xsorted with the oldest login time first.
XIf a user has not logged in during the life of
X/usr/adm/lastlog,
Xthe date is replaced with \*(lqnever logged in\*(rq.
X.LP
X.I Lastlog
Xdiffers from 
X.IR last (1)
Xin using a file that is not periodically cleaned.
X.I Lastlog
Xuses /usr/adm/lastlog,
Xwhich grows only when new users are added.
X.SH FILES
X/etc/passwd \- password file
X.br
X/usr/adm/lastlog \- binary file with info for each uid
X.br
X/usr/include/lastlog.h \- description of /usr/adm/lastlog contents
X.SH SEE ALSO
Xlast(1), ac(8), passwd(5)
X.SH BUGS
XShould remove redundant entries for usernames sharing the same uid.
X.SH AUTHOR
XRex Sanders, US Geological Survey, Pacific Marine Geology
SHAR_EOF
chmod +x 'lastlog.8'
fi # end of overwriting check
echo shar: extracting "'lastlog.c'" '(2268 characters)'
if test -f 'lastlog.c'
then
 echo shar: will not over-write existing file "'lastlog.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lastlog.c'
X/*
X * lastlog - print last login time for all users, based on times
X *            stored in /usr/adm/lastlog.
X *
X * Lines are printed oldest first, with name, date/time, and gecos
X * field on each line.
X *
X * No command line options. Runs on VAX/4.2 BSD Unix.
X *
X * compile with:  cc -O -o lastlog lastlog.c
X *
X * Rex Sanders, US Geological Survey, Pacific Marine Geology, 12/19/85
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <sys/file.h>
X#include <sys/types.h>
X#include <lastlog.h>
X#include <pwd.h>
X
X/* maximum number of users/entries in /etc/passwd */
X#define MAXU       1000
X/* maximum length of the gecos field in /etc/passwd */
X#define MAXG        100
X
Xchar   *ctime ();
Xlong    lseek ();
X
Xstruct info_s {
X    int     time;
X    char    name[9];
X    char    gecos[MAXG];
X};
X
Xmain () {
X    int     infocmp ();
X    struct lastlog  ll;
X    struct passwd  *pw;
X    struct info_s   info[MAXU];
X    char    lastdate[25];
X    int     llfd;
X    register int    nusers = 0;
X    register int    i;
X
X    if ((llfd = open ("/usr/adm/lastlog", O_RDONLY)) < 0) {
X         perror ("lastlog: /usr/adm/lastlog:");
X         exit (1);
X    }
X
X/*
X * For each user in password file, grab password info
X */
X    while (pw = getpwent ()) {
X    /* 
X     * Grab info from lastlog file
X     */
X         if (lseek (llfd, (long) pw -> pw_uid * sizeof ll, 0) == -1)
X             continue;
X         if (read (llfd, (char *) & ll, sizeof ll) != sizeof ll)
X             continue;
X
X         info[nusers].time = ll.ll_time;
X         strncpy (info[nusers].name, pw -> pw_name, 9);
X         strncpy (info[nusers].gecos, pw -> pw_gecos, MAXG);
X         nusers++;
X    }
X
X/*
X * Sort users by last login time
X */
X    qsort ((char *) info, nusers, sizeof (struct info_s), infocmp);
X
X/*
X * Print info for each user
X */
X    for (i = 0; i < nusers; i++) {
X         if (info[i].time) {
X             strncpy (lastdate, ctime (&info[i].time), 24);
X             lastdate[24] = '\0';
X         }
X         else
X             strcpy (lastdate, "never logged in");
X
X         printf ("%-8s %-24s    %s\n", info[i].name, lastdate,
X                   info[i].gecos);
X    }
X
X    close (llfd);
X    endpwent ();
X}
X
X/*
X * infocmp - compare 2 info entries for qsort
X */
X
Xinfocmp (info1, info2)
Xstruct info_s  *info1,
X               *info2;
X{
X    register int    r;
X
X    if (info1 -> time == info2 -> time)
X         r = 0;
X    else
X         r = (info1 -> time > info2 -> time) ? 1 : -1;
X
X    return (r);
X}
SHAR_EOF
chmod +x 'lastlog.c'
fi # end of overwriting check
#         End of shell archive
exit 0