tin@smsc.sony.com (Tin Le) (05/23/91)
I ported this from Tom C.'s posting in just a few minutes. There is also a lastlogin for System V (I have it running on ISC v2.0.2). With this, you could have the same functionalities as with BSD systems. Submitted-by: tin@rn31 Archive-name: lastlog/part01 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is lastlog, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 05/22/1991 21:05 UTC by tin@rn31 # Source directory /usr1/tin/News/last # # existing files will NOT be overwritten unless -c is specified # This format requires very little intelligence at unshar time. # "if test", "echo", "true", and "sed" may be needed. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 282 -rw-r--r-- Makefile # 3458 -rw-r--r-- lastlog.c # # ============= Makefile ============== if test -f 'Makefile' -a X"$1" != X"-c"; then echo 'x - skipping Makefile (File already exists)' else echo 'x - extracting Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && X# X# Makefile for last X# X# 5/22/91 Tin X# XTARGET = last XOBJECTS = lastlog.o XCFLAGS = -O -DSVR4 XLDFLAGS = -s XLIBS = XINCLDIR = /usr/include X X$(TARGET): $(OBJECTS) X $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(LIBS) X Xclean: X -rm -f $(OBJECTS) core X Xclobber: clean X -rm -f $(TARGET) X SHAR_EOF true || echo 'restore of Makefile failed' fi # ============= lastlog.c ============== if test -f 'lastlog.c' -a X"$1" != X"-c"; then echo 'x - skipping lastlog.c (File already exists)' else echo 'x - extracting lastlog.c (Text)' 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, Sony RISC SVR4. X * X * compile with: cc -O -o lastlog lastlog.c X * X * Tin Le, Sony Microsystems, San Jose 5/22/91 X * - Adapted for SVR4. X * X * Rex Sanders, US Geological Survey, Pacific Marine Geology, 12/19/85 X */ X X#include <stdio.h> X#include <sys/types.h> X#ifdef SVR4 X#include <fcntl.h> X#include <string.h> X#else X#include <sys/file.h> X#include <strings.h> X#endif X#include <lastlog.h> X#include <pwd.h> X#ifndef SVR4 X#include <sysexits.h> X#else X#define EX_OSFILE 1 X#define EX_SOFTWARE 2 X#endif X X/* In case your UNIX put lastlog somewhere other than */adm/lastlog */ X#define LASTLOG "/usr/adm/lastlog" X X/* maximum number of users/entries in /etc/passwd */ X#define MAXU 5000 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#ifdef SVR4 /* Actually there is no hard limit in SVR4 struct passwd X ** Change this to char *name, and malloc your string if you X ** really want to get complicated. X ** 5/22/91 Tin X */ X char name[15]; X#else X char name[9]; X#endif X char gecos[MAXG]; X}; Xstruct info_s info[MAXU]; X Xmain (argc, argv) char **argv; { X int infocmp (); X struct lastlog ll; X struct passwd *pw; X char lastdate[25]; X int llfd; X register int nusers = 0; X register int i; X X if ((llfd = open (LASTLOG, O_RDONLY)) < 0) { X perror("open()"); X fprintf(stderr, "lastlog: %s\n", LASTLOG); X exit (EX_OSFILE); 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 (!strcmp(pw->pw_passwd,"*")) X continue; X if (lseek (llfd, (long) pw -> pw_uid * sizeof ll, 0) == -1) { X fprintf(stderr,"%s: lseek for uid %d failed\n", *argv, pw->pw_uid); X continue; X } X if (read (llfd, (char *) & ll, sizeof ll) != sizeof ll) { X fprintf(stderr, "%s: read for uid %d (%s) failed\n", X *argv, pw->pw_uid, pw->pw_name); X continue; X } X X X info[nusers].time = ll.ll_time; X#ifdef SVR4 X strcpy (info[nusers].name, pw -> pw_name); X#else X strncpy (info[nusers].name, pw -> pw_name, 9); X#endif X strncpy (info[nusers].gecos, pw -> pw_gecos, MAXG); X if (nusers++ == MAXU) { X fprintf(stderr, "%s: recompile with MAXU > %d\n", X *argv, MAXU); X exit(EX_SOFTWARE); X } 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 ("%-12s %-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} X SHAR_EOF true || echo 'restore of lastlog.c failed' fi exit 0 -- .---------------------------------------------------------------------- . Tin Le Work Internet: tin@smsc.Sony.COM . Sony Microsystems UUCP: {uunet,mips}!sonyusa!tin . Work: (408) 944-4157 Home Internet: tin@szebra.uu.net