ubase

suckless linux base utils
git clone git://git.suckless.org/ubase
Log | Files | Refs | README | LICENSE

commit e4677f290b9fbc6feceda0fbe406d19a8881faae
parent 129168715207a4e28cbc276cccdf4c5ff59b2163
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 18 Aug 2014 18:24:29 +0100

Add lastlog(8)

At the moment this does not work with ubase login(1).  We should
add support to login(1) to write the lastlog entries.

Minor modifications by sin.

Diffstat:
MLICENSE | 1+
MMakefile | 2++
Alastlog.8 | 11+++++++++++
Alastlog.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -8,6 +8,7 @@ MIT/X Consortium License © 2014 Carlos J. Torres <vlaadbrain@gmail.com> © 2014 Hiltjo Posthuma <hiltjo@codemadness.org> © 2014 Laslo Hunhold <dev@frign.de> +© 2014 Roberto E. Vargas Caballero <k0ga@shike2.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/Makefile b/Makefile @@ -33,6 +33,7 @@ LIB = \ util/tty.o SRC = \ + lastlog.c \ chvt.c \ clear.c \ ctrlaltdel.c \ @@ -115,6 +116,7 @@ MAN8 = \ hwclock.8 \ insmod.8 \ killall5.8 \ + lastlog.8 \ lsmod.8 \ lsusb.8 \ mkswap.8 \ diff --git a/lastlog.8 b/lastlog.8 @@ -0,0 +1,11 @@ +.TH LASTLOG 8 ubase-VERSION +.SH NAME +\fBlastlog\fR - Show last login of users +.SH SYPNOSIS +\fBlastlog\fI [user ...] +.SH DESCRIPTION +\fBlastlog\fR Show time, tty, and host (if it was a remote +connection) of last login of users. If some user names are passed +as parameter then information about last login of these users is +shown, otherwise is shown for all the users in /etc/passwd in the +order they appear in it. diff --git a/lastlog.c b/lastlog.c @@ -0,0 +1,75 @@ +/* See LICENSE file for copyright and license details. */ +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <utmp.h> + +#define PASSWD "/etc/passwd" + +static FILE *last; + +static void +lastlog(char *user) +{ + struct passwd *pwd; + struct lastlog ll; + time_t lltime; + + if ((pwd = getpwnam(user)) == NULL) { + fprintf(stderr, "unknown user: %s\n", user); + return; + } + + fseek(last, pwd->pw_uid * sizeof(struct lastlog), 0); + fread(&ll, sizeof(struct lastlog), 1, last); + + if (ferror(last)) { + perror("error reading lastlog"); + exit(EXIT_FAILURE); + } + + /* 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; + char line[512], *p; + + if ((last = fopen(_PATH_LASTLOG, "r")) == NULL) { + perror(_PATH_LASTLOG); + exit(EXIT_FAILURE); + } + + if (argc > 1) { + while (*++argv) + lastlog(*argv); + } else { + if ((fp = fopen(PASSWD, "r")) == NULL) { + perror(PASSWD); + exit(EXIT_FAILURE); + } + while ((fgets(line, sizeof(line), fp)) != NULL) { + if ((p = strchr(line, ':')) == NULL) { + fputs("incorrect password file", stderr); + exit(-1); + } + *p = '\0'; + lastlog(line); + } + if (fclose(fp)) + perror(PASSWD); + } + + fclose(last); + + return EXIT_SUCCESS; +}