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