master xplshn/aruu / cmd / pseudo / lastlog.c
 1/* See LICENSE file for copyright and license details. */
 2
 3#include <errno.h>
 4#include <pwd.h>
 5#include <stdio.h>
 6#include <stdlib.h>
 7#include <string.h>
 8#include <time.h>
 9#include <utmp.h>
10
11#include "paths.h"
12#include "text.h"
13#include "util.h"
14
15#define PASSWD "/etc/passwd"
16
17static FILE *last;
18
19static void
20lastlog(char *user)
21{
22  struct passwd *pwd;
23  struct lastlog ll;
24  time_t         lltime;
25
26  errno = 0;
27  if ((pwd = getpwnam(user)) == NULL) {
28    if (errno)
29      weprintf("getpwnam %s:", user);
30    else
31      weprintf("unknown user: %s\n", user);
32    return;
33  }
34
35  fseek(last, pwd->pw_uid * sizeof(struct lastlog), 0);
36  fread(&ll, sizeof(struct lastlog), 1, last);
37
38  if (ferror(last))
39    eprintf("%s: read error:", ARUU_PATH_LASTLOG);
40
41  /* on glibc `ll_time' can be an int32_t with compat32
42   * avoid compiler warning when calling ctime() */
43  lltime = ll.ll_time;
44  printf("%-8.8s %-8.8s %-16.16s %s", user, ll.ll_line, ll.ll_host, ctime(&lltime));
45}
46
47// ?man lastlog: report recent logins
48// ?man display the most recent login times of users
49int
50main(int argc, char **argv)
51{
52  FILE  *fp;
53  char  *line = NULL, *p;
54  size_t sz   = 0;
55
56  if ((last = fopen(ARUU_PATH_LASTLOG, "r")) == NULL)
57    eprintf("fopen %s:", ARUU_PATH_LASTLOG);
58
59  if (argc > 1) {
60    while (*++argv)
61      lastlog(*argv);
62  } else {
63    if ((fp = fopen(PASSWD, "r")) == NULL)
64      eprintf("fopen %s:", PASSWD);
65    while (agetline(&line, &sz, fp) != -1) {
66      if ((p = strchr(line, ':')) == NULL)
67        eprintf("invalid passwd entry\n");
68      *p = '\0';
69      lastlog(line);
70    }
71    if (fclose(fp))
72      eprintf("fclose %s:", PASSWD);
73    free(line);
74  }
75
76  if (fclose(last))
77    eprintf("fclose %s:", ARUU_PATH_LASTLOG);
78
79  return 0;
80}