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}