2014-08-18 13:24:29 -04:00
|
|
|
/* See LICENSE file for copyright and license details. */
|
2014-08-18 16:55:38 -04:00
|
|
|
#include <errno.h>
|
2014-08-18 13:24:29 -04:00
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <utmp.h>
|
|
|
|
|
2014-08-18 17:02:22 -04:00
|
|
|
#include "text.h"
|
2014-08-18 16:55:38 -04:00
|
|
|
#include "util.h"
|
|
|
|
|
2014-08-18 13:24:29 -04:00
|
|
|
#define PASSWD "/etc/passwd"
|
|
|
|
|
|
|
|
static FILE *last;
|
|
|
|
|
|
|
|
static void
|
|
|
|
lastlog(char *user)
|
|
|
|
{
|
|
|
|
struct passwd *pwd;
|
|
|
|
struct lastlog ll;
|
|
|
|
time_t lltime;
|
|
|
|
|
2014-08-18 16:55:38 -04:00
|
|
|
errno = 0;
|
2014-08-18 13:24:29 -04:00
|
|
|
if ((pwd = getpwnam(user)) == NULL) {
|
2014-08-18 16:55:38 -04:00
|
|
|
if (errno)
|
|
|
|
weprintf("getpwnam %s:", user);
|
|
|
|
else
|
|
|
|
weprintf("unknown user: %s\n", user);
|
2014-08-18 13:24:29 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fseek(last, pwd->pw_uid * sizeof(struct lastlog), 0);
|
|
|
|
fread(&ll, sizeof(struct lastlog), 1, last);
|
|
|
|
|
2014-08-18 16:55:38 -04:00
|
|
|
if (ferror(last))
|
2014-08-18 17:02:22 -04:00
|
|
|
eprintf("%s: read error:", _PATH_LASTLOG);
|
2014-08-18 13:24:29 -04:00
|
|
|
|
|
|
|
/* on glibc `ll_time' can be an int32_t with compat32
|
|
|
|
* avoid compiler warning when calling ctime() */
|
|
|
|
lltime = ll.ll_time;
|
|
|
|
printf("%-8.8s %-8.8s %-16.16s %s",
|
|
|
|
user, ll.ll_line, ll.ll_host, ctime(&lltime));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
2014-08-18 17:02:22 -04:00
|
|
|
char *line = NULL, *p;
|
|
|
|
size_t sz = 0;
|
2014-08-18 13:24:29 -04:00
|
|
|
|
2014-08-18 16:55:38 -04:00
|
|
|
if ((last = fopen(_PATH_LASTLOG, "r")) == NULL)
|
|
|
|
eprintf("fopen %s:", _PATH_LASTLOG);
|
2014-08-18 13:24:29 -04:00
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
while (*++argv)
|
|
|
|
lastlog(*argv);
|
|
|
|
} else {
|
2014-08-18 16:55:38 -04:00
|
|
|
if ((fp = fopen(PASSWD, "r")) == NULL)
|
|
|
|
eprintf("fopen %s:", PASSWD);
|
2014-08-18 17:02:22 -04:00
|
|
|
while (agetline(&line, &sz, fp) != -1) {
|
2014-08-18 16:55:38 -04:00
|
|
|
if ((p = strchr(line, ':')) == NULL)
|
|
|
|
eprintf("invalid passwd entry\n");
|
2014-08-18 13:24:29 -04:00
|
|
|
*p = '\0';
|
|
|
|
lastlog(line);
|
|
|
|
}
|
|
|
|
if (fclose(fp))
|
2014-08-18 17:02:22 -04:00
|
|
|
eprintf("fclose %s:", PASSWD);
|
|
|
|
free(line);
|
2014-08-18 13:24:29 -04:00
|
|
|
}
|
|
|
|
|
2014-08-18 17:02:22 -04:00
|
|
|
if (fclose(last))
|
|
|
|
eprintf("fclose %s:", _PATH_LASTLOG);
|
2014-08-18 13:24:29 -04:00
|
|
|
|
2014-10-02 18:45:25 -04:00
|
|
|
return 0;
|
2014-08-18 13:24:29 -04:00
|
|
|
}
|