From: Sami Kerola Date: Sun, 29 Mar 2020 19:40:48 +0000 (+0100) Subject: lslogins: use lastlog as wtmp fallback X-Git-Tag: v2.36-rc1~160^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3434ac972054ffb0315786df76c885949259926f;p=thirdparty%2Futil-linux.git lslogins: use lastlog as wtmp fallback The wtmp file tends to rotate higher rate than lastlog, so use the later as fallback in when wtmp tells nothing in LAST-LOGIN column. Signed-off-by: Sami Kerola --- diff --git a/bash-completion/lslogins b/bash-completion/lslogins index 8651fe9df2..93c9773b29 100755 --- a/bash-completion/lslogins +++ b/bash-completion/lslogins @@ -23,7 +23,7 @@ _lslogins_module() COMPREPLY=( $(compgen -W "short full iso" -- $cur) ) return 0 ;; - '--wtmp-file'|'--btmp-file') + '--wtmp-file'|'--btmp-file'|'--lastlog') local IFS=$'\n' compopt -o filenames COMPREPLY=( $(compgen -f -- $cur) ) @@ -69,6 +69,7 @@ _lslogins_module() --print0 --wtmp-file --btmp-file + --lastlog --help --version " -- $cur) ) diff --git a/login-utils/lslogins.1 b/login-utils/lslogins.1 index 06bad42ab4..fbeaacedf6 100644 --- a/login-utils/lslogins.1 +++ b/login-utils/lslogins.1 @@ -113,6 +113,9 @@ Display version information and exit. \fB\-\-wtmp\-file \fIpath\fP Alternate path for wtmp. .TP +\fB\-\-lastlog \fIpath\fP +Alternate path for lastlog. +.TP \fB\-Z\fR, \fB\-\-context\fR Display the users' security context. .TP diff --git a/login-utils/lslogins.c b/login-utils/lslogins.c index 6e2d0ff25f..c687e58e89 100644 --- a/login-utils/lslogins.c +++ b/login-utils/lslogins.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef HAVE_LIBSELINUX @@ -95,6 +96,12 @@ enum { OUT_PRETTY }; +enum { + LASTLOG_TIME, + LASTLOG_LINE, + LASTLOG_HOST +}; + struct lslogins_user { char *login; uid_t uid; @@ -252,6 +259,8 @@ struct lslogins_control { struct utmpx *btmp; size_t btmp_size; + int lastlogin_fd; + void *usertree; uid_t uid; @@ -516,6 +525,31 @@ static int parse_btmp(struct lslogins_control *ctl, char *path) return rc; } +static void get_lastlog(struct lslogins_control *ctl, uid_t uid, void *dst, int what) +{ + struct lastlog ll; + + if (ctl->lastlogin_fd < 0 || + pread(ctl->lastlogin_fd, (void *)&ll, sizeof(ll), uid * sizeof(ll)) != sizeof(ll)) + return; + + switch (what) { + case LASTLOG_TIME: { + time_t *t = (time_t *)dst; + *t = ll.ll_time; + break; + } + case LASTLOG_LINE: + mem2strcpy(dst, ll.ll_line, sizeof(ll.ll_line), sizeof(ll.ll_line) + 1); + break; + case LASTLOG_HOST: + mem2strcpy(dst, ll.ll_host, sizeof(ll.ll_host), sizeof(ll.ll_host) + 1); + break; + default: + abort(); + } +} + static int get_sgroups(gid_t **list, size_t *len, struct passwd *pwd) { size_t n = 0; @@ -737,23 +771,31 @@ static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const c if (user_wtmp) { time = user_wtmp->ut_tv.tv_sec; user->last_login = make_time(ctl->time_mode, time); + } else { + time = 0; + get_lastlog(ctl, pwd->pw_uid, &time, LASTLOG_TIME); + if (time) + user->last_login = make_time(ctl->time_mode, time); } break; case COL_LAST_TTY: + user->last_tty = xcalloc(1, sizeof(user_wtmp->ut_line) + 1); if (user_wtmp) { - user->last_tty = xmalloc(sizeof(user_wtmp->ut_line) + 1); mem2strcpy(user->last_tty, user_wtmp->ut_line, sizeof(user_wtmp->ut_line), sizeof(user_wtmp->ut_line) + 1);; + } else { + get_lastlog(ctl, user->uid, user->last_tty, LASTLOG_LINE); } break; case COL_LAST_HOSTNAME: + user->last_hostname = xcalloc(1, sizeof(user_wtmp->ut_host) + 1); if (user_wtmp) { - user->last_hostname = xmalloc(sizeof(user_wtmp->ut_host) + 1); mem2strcpy(user->last_hostname, user_wtmp->ut_host, sizeof(user_wtmp->ut_host), sizeof(user_wtmp->ut_host) + 1);; - } + } else + get_lastlog(ctl, user->uid, user->last_hostname, LASTLOG_HOST); break; case COL_FAILED_LOGIN: if (user_btmp) { @@ -1363,6 +1405,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -z, --print0 delimit user entries with a nul character\n"), out); fputs(_(" --wtmp-file set an alternate path for wtmp\n"), out); fputs(_(" --btmp-file set an alternate path for btmp\n"), out); + fputs(_(" --lastlog set an alternate path for lastlog\n"), out); fputs(USAGE_SEPARATOR, out); printf(USAGE_HELP_OPTIONS(26)); @@ -1379,7 +1422,7 @@ int main(int argc, char *argv[]) { int c; char *logins = NULL, *groups = NULL, *outarg = NULL; - char *path_wtmp = _PATH_WTMP, *path_btmp = _PATH_BTMP; + char *path_lastlog = _PATH_LASTLOG, *path_wtmp = _PATH_WTMP, *path_btmp = _PATH_BTMP; struct lslogins_control *ctl = xcalloc(1, sizeof(struct lslogins_control)); size_t i; @@ -1387,6 +1430,7 @@ int main(int argc, char *argv[]) enum { OPT_WTMP = CHAR_MAX + 1, OPT_BTMP, + OPT_LASTLOG, OPT_NOTRUNC, OPT_NOHEAD, OPT_TIME_FMT, @@ -1417,6 +1461,7 @@ int main(int argc, char *argv[]) { "print0", no_argument, 0, 'z' }, { "wtmp-file", required_argument, 0, OPT_WTMP }, { "btmp-file", required_argument, 0, OPT_BTMP }, + { "lastlog-file", required_argument, 0, OPT_LASTLOG }, #ifdef HAVE_LIBSELINUX { "context", no_argument, 0, 'Z' }, #endif @@ -1524,6 +1569,9 @@ int main(int argc, char *argv[]) case 'z': outmode = OUT_NUL; break; + case OPT_LASTLOG: + path_lastlog = optarg; + break; case OPT_WTMP: path_wtmp = optarg; break; @@ -1591,8 +1639,10 @@ int main(int argc, char *argv[]) &ncolumns, column_name_to_id) < 0) return EXIT_FAILURE; - if (require_wtmp()) + if (require_wtmp()) { parse_wtmp(ctl, path_wtmp); + ctl->lastlogin_fd = open(path_lastlog, O_RDONLY, 0); + } if (require_btmp()) parse_btmp(ctl, path_btmp); @@ -1606,6 +1656,7 @@ int main(int argc, char *argv[]) scols_unref_table(tb); tdestroy(ctl->usertree, free_user); + close(ctl->lastlogin_fd); free_ctl(ctl); return EXIT_SUCCESS;