lslogins: cleanup -a output

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2014-05-29 14:17:41 +02:00
parent d4aa0ff138
commit ed374569ae
1 changed files with 76 additions and 49 deletions

View File

@ -192,6 +192,13 @@ enum {
COL_NPROCS, COL_NPROCS,
}; };
#define is_wtmp_col(x) ((x) == COL_LAST_LOGIN || \
(x) == COL_LAST_TTY || \
(x) == COL_LAST_HOSTNAME)
#define is_btmp_col(x) ((x) == COL_FAILED_LOGIN || \
(x) == COL_FAILED_TTY)
enum { enum {
STATUS_FALSE = 0, STATUS_FALSE = 0,
STATUS_TRUE, STATUS_TRUE,
@ -233,11 +240,11 @@ static struct lslogins_coldesc coldescs[] =
[COL_FAILED_LOGIN] = { "FAILED-LOGIN", N_("date of last failed login"), N_("Failed login"), 0.1 }, [COL_FAILED_LOGIN] = { "FAILED-LOGIN", N_("date of last failed login"), N_("Failed login"), 0.1 },
[COL_FAILED_TTY] = { "FAILED-TTY", N_("where did the login fail?"), N_("Failed login terminal"), 0.05 }, [COL_FAILED_TTY] = { "FAILED-TTY", N_("where did the login fail?"), N_("Failed login terminal"), 0.05 },
[COL_HUSH_STATUS] = { "HUSHED", N_("user's hush settings"), N_("Hushed"), 1, SCOLS_FL_RIGHT }, [COL_HUSH_STATUS] = { "HUSHED", N_("user's hush settings"), N_("Hushed"), 1, SCOLS_FL_RIGHT },
[COL_PWD_WARN] = { "PWD-WARN", N_("days user is warned of password expiration"), N_("Password expiration warn interval"), 0.1 }, [COL_PWD_WARN] = { "PWD-WARN", N_("days user is warned of password expiration"), N_("Password expiration warn interval"), 0.1, SCOLS_FL_RIGHT },
[COL_PWD_EXPIR] = { "PWD-EXPIR", N_("password expiration date"), N_("Password expiration"), 0.1 }, [COL_PWD_EXPIR] = { "PWD-EXPIR", N_("password expiration date"), N_("Password expiration"), 0.1, SCOLS_FL_RIGHT },
[COL_PWD_CTIME] = { "PWD-CHANGE", N_("date of last password change"), N_("Password changed"), 0.1 }, [COL_PWD_CTIME] = { "PWD-CHANGE", N_("date of last password change"), N_("Password changed"), 0.1, SCOLS_FL_RIGHT},
[COL_PWD_CTIME_MIN] = { "PWD-MIN", N_("number of days required between changes"), N_("Minimal change time"), 0.1 }, [COL_PWD_CTIME_MIN] = { "PWD-MIN", N_("number of days required between changes"), N_("Minimal change time"), 0.1, SCOLS_FL_RIGHT },
[COL_PWD_CTIME_MAX] = { "PWD-MAX", N_("max number of days a password may remain unchanged"), N_("Maximal change time"), 0.1 }, [COL_PWD_CTIME_MAX] = { "PWD-MAX", N_("max number of days a password may remain unchanged"), N_("Maximal change time"), 0.1, SCOLS_FL_RIGHT },
[COL_SELINUX] = { "CONTEXT", N_("the user's security context"), N_("Selinux context"), 0.1 }, [COL_SELINUX] = { "CONTEXT", N_("the user's security context"), N_("Selinux context"), 0.1 },
[COL_NPROCS] = { "PROC", N_("number of processes run by the user"), N_("Running process"), 1, SCOLS_FL_RIGHT }, [COL_NPROCS] = { "PROC", N_("number of processes run by the user"), N_("Running process"), 1, SCOLS_FL_RIGHT },
}; };
@ -273,11 +280,20 @@ static struct libscols_table *tb;
static int columns[ARRAY_SIZE(coldescs)]; static int columns[ARRAY_SIZE(coldescs)];
static int ncolumns; static int ncolumns;
static struct timeval now;
static int date_is_today(time_t t) static int date_is_today(time_t t)
{ {
struct timeval tv; if (now.tv_sec == 0)
gettimeofday(&tv, NULL); gettimeofday(&now, NULL);
return t / 86400 == tv.tv_sec / 86400; return t / (3600 * 24) == now.tv_sec / (3600 * 24);
}
static int date_is_thisyear(time_t t)
{
if (now.tv_sec == 0)
gettimeofday(&now, NULL);
return t / (3600 * 24 * 365) == now.tv_sec / (3600 * 24 * 365);
} }
static int column_name_to_id(const char *name, size_t namesz) static int column_name_to_id(const char *name, size_t namesz)
@ -293,6 +309,7 @@ static int column_name_to_id(const char *name, size_t namesz)
warnx(_("unknown column: %s"), name); warnx(_("unknown column: %s"), name);
return -1; return -1;
} }
static char *make_time(int mode, time_t time) static char *make_time(int mode, time_t time)
{ {
char *s; char *s;
@ -310,8 +327,10 @@ static char *make_time(int mode, time_t time)
case TIME_SHORT: case TIME_SHORT:
if (date_is_today(time)) if (date_is_today(time))
strftime(buf, sizeof(buf), "%H:%M:%S", &tm); strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
else else if (date_is_thisyear(time))
strftime(buf, sizeof(buf), "%b%d/%H:%M", &tm); strftime(buf, sizeof(buf), "%b%d/%H:%M", &tm);
else
strftime(buf, sizeof(buf), "%Y-%b%d", &tm);
break; break;
case TIME_ISO: case TIME_ISO:
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &tm); strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &tm);
@ -402,6 +421,24 @@ static struct utmp *get_last_wtmp(struct lslogins_control *ctl, const char *user
} }
static int require_wtmp(void)
{
size_t i;
for (i = 0; i < (size_t) ncolumns; i++)
if (is_wtmp_col(columns[i]))
return 1;
return 0;
}
static int require_btmp(void)
{
size_t i;
for (i = 0; i < (size_t) ncolumns; i++)
if (is_btmp_col(columns[i]))
return 1;
return 0;
}
static struct utmp *get_last_btmp(struct lslogins_control *ctl, const char *username) static struct utmp *get_last_btmp(struct lslogins_control *ctl, const char *username)
{ {
size_t n = 0; size_t n = 0;
@ -652,20 +689,12 @@ static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const c
shadow->sp_lstchg * 86400); shadow->sp_lstchg * 86400);
break; break;
case COL_PWD_CTIME_MIN: case COL_PWD_CTIME_MIN:
if (shadow) { if (shadow && shadow->sp_min > 0)
if (shadow->sp_min <= 0) xasprintf(&user->pwd_ctime_min, "%ld", shadow->sp_min);
user->pwd_ctime_min = xstrdup("unlimited");
else
xasprintf(&user->pwd_ctime_min, "%ld", shadow->sp_min);
}
break; break;
case COL_PWD_CTIME_MAX: case COL_PWD_CTIME_MAX:
if (shadow) { if (shadow && shadow->sp_max > 0)
if (shadow->sp_max <= 0) xasprintf(&user->pwd_ctime_max, "%ld", shadow->sp_max);
user->pwd_ctime_max = xstrdup("unlimited");
else
xasprintf(&user->pwd_ctime_max, "%ld", shadow->sp_max);
}
break; break;
case COL_SELINUX: case COL_SELINUX:
{ {
@ -1166,10 +1195,11 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int c, want_wtmp = 0, want_btmp = 0; int c, opt_o = 0;
char *logins = NULL, *groups = NULL; char *logins = NULL, *groups = NULL;
char *path_wtmp = _PATH_WTMP, *path_btmp = _PATH_BTMP; char *path_wtmp = _PATH_WTMP, *path_btmp = _PATH_BTMP;
struct lslogins_control *ctl = xcalloc(1, sizeof(struct lslogins_control)); struct lslogins_control *ctl = xcalloc(1, sizeof(struct lslogins_control));
size_t i;
/* long only options. */ /* long only options. */
enum { enum {
@ -1225,6 +1255,10 @@ int main(int argc, char *argv[])
ctl->time_mode = TIME_SHORT; ctl->time_mode = TIME_SHORT;
/* very basic default */
columns[ncolumns++] = COL_UID;
columns[ncolumns++] = COL_USER;
while ((c = getopt_long(argc, argv, "acefg:hl:mno:rsuxzZ", while ((c = getopt_long(argc, argv, "acefg:hl:mno:rsuxzZ",
longopts, NULL)) != -1) { longopts, NULL)) != -1) {
@ -1232,7 +1266,11 @@ int main(int argc, char *argv[])
switch (c) { switch (c) {
case 'a': case 'a':
lslogins_flag |= F_EXPIR; columns[ncolumns++] = COL_PWD_WARN;
columns[ncolumns++] = COL_PWD_CTIME_MIN;
columns[ncolumns++] = COL_PWD_CTIME_MAX;
columns[ncolumns++] = COL_PWD_CTIME;
columns[ncolumns++] = COL_PWD_EXPIR;
break; break;
case 'c': case 'c':
outmode = OUT_COLON; outmode = OUT_COLON;
@ -1268,6 +1306,7 @@ int main(int argc, char *argv[])
if (ncolumns < 0) if (ncolumns < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
opt_o = 1;
break; break;
case 'r': case 'r':
outmode = OUT_RAW; outmode = OUT_RAW;
@ -1344,21 +1383,18 @@ int main(int argc, char *argv[])
lslogins_flag &= ~(F_USRAC | F_SYSAC); lslogins_flag &= ~(F_USRAC | F_SYSAC);
if (!ncolumns && outmode == OUT_PRETTY) { if (!ncolumns && outmode == OUT_PRETTY) {
size_t i;
want_wtmp = 1;
want_btmp = 1;
for (i = 0; i < ARRAY_SIZE(coldescs); i++) for (i = 0; i < ARRAY_SIZE(coldescs); i++)
columns[ncolumns++] = i; columns[ncolumns++] = i;
} else if (!ncolumns) { } else if (ncolumns == 2 && !opt_o) {
columns[ncolumns++] = COL_UID; /* default colummns */
columns[ncolumns++] = COL_USER; columns[ncolumns++] = COL_NPROCS;
columns[ncolumns++] = COL_PGRP; columns[ncolumns++] = COL_PWDLOCK;
columns[ncolumns++] = COL_PGID; columns[ncolumns++] = COL_PWDDENY;
columns[ncolumns++] = COL_LAST_LOGIN; columns[ncolumns++] = COL_LAST_LOGIN;
columns[ncolumns++] = COL_GECOS;
want_wtmp = 1; }
/*
if (lslogins_flag & F_NOPWD) if (lslogins_flag & F_NOPWD)
columns[ncolumns++] = COL_PWDEMPTY; columns[ncolumns++] = COL_PWDEMPTY;
@ -1375,7 +1411,6 @@ int main(int argc, char *argv[])
if (lslogins_flag & F_FAIL) { if (lslogins_flag & F_FAIL) {
columns[ncolumns++] = COL_FAILED_LOGIN; columns[ncolumns++] = COL_FAILED_LOGIN;
columns[ncolumns++] = COL_FAILED_TTY; columns[ncolumns++] = COL_FAILED_TTY;
want_btmp = 1;
} }
if (lslogins_flag & F_EXTRA) { if (lslogins_flag & F_EXTRA) {
columns[ncolumns++] = COL_HOME; columns[ncolumns++] = COL_HOME;
@ -1386,26 +1421,18 @@ int main(int argc, char *argv[])
columns[ncolumns++] = COL_PWDLOCK; columns[ncolumns++] = COL_PWDLOCK;
columns[ncolumns++] = COL_HUSH_STATUS; columns[ncolumns++] = COL_HUSH_STATUS;
columns[ncolumns++] = COL_PWD_WARN; columns[ncolumns++] = COL_PWD_WARN;
columns[ncolumns++] = COL_PWD_CTIME_MIN; /*?*/ columns[ncolumns++] = COL_PWD_CTIME_MIN;
columns[ncolumns++] = COL_PWD_CTIME_MAX; /*?*/ columns[ncolumns++] = COL_PWD_CTIME_MAX;
columns[ncolumns++] = COL_NPROCS; columns[ncolumns++] = COL_NPROCS;
} }
if (lslogins_flag & F_SELINUX) if (lslogins_flag & F_SELINUX)
columns[ncolumns++] = COL_SELINUX; columns[ncolumns++] = COL_SELINUX;
} else {
int n = 0, i;
while (n < ncolumns) {
i = columns[n++];
if (i <= COL_LAST_HOSTNAME && i >= COL_LAST_LOGIN)
want_wtmp = 1;
if (i == COL_FAILED_TTY && i >= COL_FAILED_LOGIN)
want_btmp = 1;
}
}
if (want_wtmp) */
if (require_wtmp())
parse_wtmp(ctl, path_wtmp); parse_wtmp(ctl, path_wtmp);
if (want_btmp) if (require_btmp())
parse_btmp(ctl, path_btmp); parse_btmp(ctl, path_btmp);
get_ulist(ctl, logins, groups); get_ulist(ctl, logins, groups);