lastlog.c - ubase - suckless linux base utils
(HTM) git clone git://git.suckless.org/ubase
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
lastlog.c (1555B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <paths.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 "text.h"
12 #include "util.h"
13
14 #define PASSWD "/etc/passwd"
15
16 static FILE *last;
17
18 static void
19 lastlog(char *user)
20 {
21 struct passwd *pwd;
22 struct lastlog ll;
23 time_t lltime;
24
25 errno = 0;
26 if ((pwd = getpwnam(user)) == NULL) {
27 if (errno)
28 weprintf("getpwnam %s:", user);
29 else
30 weprintf("unknown user: %s\n", user);
31 return;
32 }
33
34 fseek(last, pwd->pw_uid * sizeof(struct lastlog), 0);
35 fread(&ll, sizeof(struct lastlog), 1, last);
36
37 if (ferror(last))
38 eprintf("%s: read error:", _PATH_LASTLOG);
39
40 /* on glibc `ll_time' can be an int32_t with compat32
41 * avoid compiler warning when calling ctime() */
42 lltime = ll.ll_time;
43 printf("%-8.8s %-8.8s %-16.16s %s",
44 user, ll.ll_line, ll.ll_host, ctime(&lltime));
45 }
46
47 int
48 main(int argc, char **argv)
49 {
50 FILE *fp;
51 char *line = NULL, *p;
52 size_t sz = 0;
53
54 if ((last = fopen(_PATH_LASTLOG, "r")) == NULL)
55 eprintf("fopen %s:", _PATH_LASTLOG);
56
57 if (argc > 1) {
58 while (*++argv)
59 lastlog(*argv);
60 } else {
61 if ((fp = fopen(PASSWD, "r")) == NULL)
62 eprintf("fopen %s:", PASSWD);
63 while (agetline(&line, &sz, fp) != -1) {
64 if ((p = strchr(line, ':')) == NULL)
65 eprintf("invalid passwd entry\n");
66 *p = '\0';
67 lastlog(line);
68 }
69 if (fclose(fp))
70 eprintf("fclose %s:", PASSWD);
71 free(line);
72 }
73
74 if (fclose(last))
75 eprintf("fclose %s:", _PATH_LASTLOG);
76
77 return 0;
78 }