# include <systemd/sd-journal.h>
#endif
+#ifdef HAVE_LIBLASTLOG2
+# include "lastlog2.h"
+#endif
+
#include "c.h"
#include "nls.h"
#include "closestream.h"
int lastlogin_fd;
+#ifdef HAVE_LIBLASTLOG2
+ const char *lastlog2_path;
+#endif
+
void *usertree;
uid_t uid;
return -EINVAL;
}
-static void get_lastlog(struct lslogins_control *ctl, uid_t uid, void *dst, int what)
+#ifdef HAVE_LIBLASTLOG2
+static int get_lastlog2(struct lslogins_control *ctl, const char *user, void *dst, int what)
+{
+ struct ll2_context *context = ll2_new_context(ctl->lastlog2_path); /* LL2_DEFAULT_DATABASE is default path */
+
+ switch (what) {
+ case LASTLOG_TIME: {
+ time_t *t = dst;
+ int64_t res_time = 0;
+
+ if (ll2_read_entry(context, user, &res_time, NULL, NULL, NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return -1;
+ }
+ *t = res_time;
+ break;
+ }
+ case LASTLOG_LINE: {
+ char *res_tty = NULL;
+
+ if (ll2_read_entry(context, user, NULL, &res_tty, NULL, NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return -1;
+ }
+ if (res_tty) {
+ mem2strcpy(dst, res_tty, strlen(res_tty), strlen(res_tty) + 1);
+ free (res_tty);
+ }
+ break;
+ }
+ case LASTLOG_HOST: {
+ char *res_host = NULL;
+
+ if (ll2_read_entry(context, user, NULL, NULL, &res_host, NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return -1;
+ }
+ if (res_host) {
+ mem2strcpy(dst, res_host, strlen(res_host), strlen(res_host) + 1);
+ free (res_host);
+ }
+ break;
+ }
+ default:
+ abort();
+ }
+ ll2_unref_context(context);
+ return 0;
+}
+#endif
+
+static void get_lastlog(struct lslogins_control *ctl, uid_t uid,
+#ifdef HAVE_LIBLASTLOG2
+ const char *user,
+#else
+ const char *user __attribute__((__unused__)),
+#endif
+ void *dst, int what)
{
struct lastlog ll;
+#ifdef HAVE_LIBLASTLOG2
+ if (get_lastlog2(ctl, user, dst, LASTLOG_TIME) >= 0)
+ return;
+#endif
if (ctl->lastlogin_fd < 0 ||
pread(ctl->lastlogin_fd, (void *)&ll, sizeof(ll), uid * sizeof(ll)) != sizeof(ll))
return;
user->last_login = make_time(ctl->time_mode, time);
} else {
time = 0;
- get_lastlog(ctl, pwd->pw_uid, &time, LASTLOG_TIME);
+ get_lastlog(ctl, pwd->pw_uid, pwd->pw_name, &time, LASTLOG_TIME);
if (time)
user->last_login = make_time(ctl->time_mode, time);
}
sizeof(user_wtmp->ut_line),
sizeof(user_wtmp->ut_line) + 1);;
} else
- get_lastlog(ctl, user->uid, user->last_tty, LASTLOG_LINE);
+ get_lastlog(ctl, user->uid, user->login, user->last_tty, LASTLOG_LINE);
break;
case COL_LAST_HOSTNAME:
user->last_hostname = xcalloc(1, sizeof(user_wtmp->ut_host) + 1);
sizeof(user_wtmp->ut_host),
sizeof(user_wtmp->ut_host) + 1);;
} else
- get_lastlog(ctl, user->uid, user->last_hostname, LASTLOG_HOST);
+ get_lastlog(ctl, user->uid, user->login, user->last_hostname, LASTLOG_HOST);
break;
case COL_FAILED_LOGIN:
if (user_btmp) {
fputs(_(" --wtmp-file <path> set an alternate path for wtmp\n"), out);
fputs(_(" --btmp-file <path> set an alternate path for btmp\n"), out);
fputs(_(" --lastlog <path> set an alternate path for lastlog\n"), out);
+#ifdef HAVE_LIBLASTLOG2
+ fputs(_(" --lastlog2 <path> set an alternate path for lastlog2\n"), out);
+#endif
fputs(USAGE_SEPARATOR, out);
fprintf(out, USAGE_HELP_OPTIONS(26));
OPT_WTMP = CHAR_MAX + 1,
OPT_BTMP,
OPT_LASTLOG,
+#ifdef HAVE_LIBLASTLOG2
+ OPT_LASTLOG2,
+#endif
OPT_NOTRUNC,
OPT_NOHEAD,
OPT_TIME_FMT,
{ "wtmp-file", required_argument, 0, OPT_WTMP },
{ "btmp-file", required_argument, 0, OPT_BTMP },
{ "lastlog-file", required_argument, 0, OPT_LASTLOG },
+#ifdef HAVE_LIBLASTLOG2
+ { "lastlog2-file", required_argument, 0, OPT_LASTLOG2 },
+#endif
#ifdef HAVE_LIBSELINUX
{ "context", no_argument, 0, 'Z' },
#endif
case OPT_LASTLOG:
path_lastlog = optarg;
break;
+#ifdef HAVE_LIBLASTLOG2
+ case OPT_LASTLOG2:
+ ctl->lastlog2_path = optarg;
+ break;
+#endif
case OPT_WTMP:
path_wtmp = optarg;
break;