home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3400 < prev    next >
Internet Message Format  |  1991-05-21  |  3KB

  1. From: tchrist@convex.COM (Tom Christiansen)
  2. Newsgroups: comp.unix.questions,alt.sources
  3. Subject: Re: When does wtmp reset?
  4. Message-ID: <1991May21.231242.6970@convex.com>
  5. Date: 21 May 91 23:12:42 GMT
  6.  
  7. From the keyboard of tpm-sprl!tpm@uunet.uu.net (Terence P. Ma):
  8. :I know that the last login date is in /var/adm/lastlog.  Is there an easy
  9. :way to get the lastlogin date and time of all users or groups of users
  10. :without using "finger -s user1 user2 ..." to get at it?
  11.  
  12. Here's a C program to do that.  Perl version (runs 3x slower; sigh)
  13. available upon request.  
  14.  
  15. --tom
  16.  
  17. /*
  18.  * lastlog - print last login time for all users, based on times
  19.  *            stored in /usr/adm/lastlog.
  20.  *
  21.  * Lines are printed oldest first, with name, date/time, and gecos
  22.  * field on each line.
  23.  *
  24.  * No command line options. Runs on VAX/4.2 BSD Unix.
  25.  *
  26.  * compile with:  cc -O -o lastlog lastlog.c
  27.  *
  28.  * Rex Sanders, US Geological Survey, Pacific Marine Geology, 12/19/85
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <strings.h>
  33. #include <sys/file.h>
  34. #include <sys/types.h>
  35. #include <lastlog.h>
  36. #include <pwd.h>
  37. #include <sysexits.h>
  38.  
  39. /* maximum number of users/entries in /etc/passwd */
  40. #define MAXU       5000
  41. /* maximum length of the gecos field in /etc/passwd */
  42. #define MAXG        100
  43.  
  44. char   *ctime ();
  45. long    lseek ();
  46.  
  47. struct info_s {
  48.     int     time;
  49.     char    name[9];
  50.     char    gecos[MAXG];
  51. };
  52. struct info_s   info[MAXU];
  53.  
  54. main (argc, argv) char **argv; {
  55.     int     infocmp ();
  56.     struct lastlog  ll;
  57.     struct passwd  *pw;
  58.     char    lastdate[25];
  59.     int     llfd;
  60.     register int    nusers = 0;
  61.     register int    i;
  62.  
  63.     if ((llfd = open ("/usr/adm/lastlog", O_RDONLY)) < 0) {
  64.          perror ("lastlog: /usr/adm/lastlog");
  65.          exit (EX_OSFILE);
  66.     }
  67.  
  68. /*
  69.  * For each user in password file, grab password info
  70.  */
  71.     while (pw = getpwent ()) {
  72.     /* 
  73.      * Grab info from lastlog file
  74.      */
  75.      if (!strcmp(pw->pw_passwd,"*"))
  76.         continue;
  77.          if (lseek (llfd, (long) pw -> pw_uid * sizeof ll, 0) == -1) {
  78.         fprintf(stderr,"%s: lseek for uid %d failed\n", *argv, pw->pw_uid);
  79.         continue;
  80.      } 
  81.          if (read (llfd, (char *) & ll, sizeof ll) != sizeof ll) {
  82.         fprintf(stderr, "%s: read for uid %d failed\n", *argv, pw->pw_uid);
  83.         continue;
  84.      } 
  85.  
  86.  
  87.          info[nusers].time = ll.ll_time;
  88.          strncpy (info[nusers].name, pw -> pw_name, 9);
  89.          strncpy (info[nusers].gecos, pw -> pw_gecos, MAXG);
  90.          if (nusers++ == MAXU) {
  91.         fprintf(stderr, "%s: recompile with MAXU > %d\n",
  92.         *argv, MAXU);
  93.         exit(EX_SOFTWARE);
  94.      } 
  95.     }
  96.  
  97. /*
  98.  * Sort users by last login time
  99.  */
  100.     qsort ((char *) info, nusers, sizeof (struct info_s), infocmp);
  101.  
  102. /*
  103.  * Print info for each user
  104.  */
  105.     for (i = 0; i < nusers; i++) {
  106.          if (info[i].time) {
  107.              strncpy (lastdate, ctime (&info[i].time), 24);
  108.              lastdate[24] = '\0';
  109.          }
  110.          else
  111.              strcpy (lastdate, "never logged in");
  112.  
  113.          printf ("%-8s %-24s    %s\n", info[i].name, lastdate,
  114.                    info[i].gecos);
  115.     }
  116.  
  117.     close (llfd);
  118.     endpwent ();
  119. }
  120.  
  121. /*
  122.  * infocmp - compare 2 info entries for qsort
  123.  */
  124.  
  125. infocmp (info1, info2)
  126. struct info_s  *info1,
  127.                *info2;
  128. {
  129.     register int    r;
  130.  
  131.     if (info1 -> time == info2 -> time)
  132.          r = 0;
  133.     else
  134.          r = (info1 -> time > info2 -> time) ? 1 : -1;
  135.  
  136.     return (r);
  137. }
  138. --
  139. Tom Christiansen        tchrist@convex.com    convex!tchrist
  140.         "So much mail, so little time." 
  141.