You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
460 lines
15 KiB
460 lines
15 KiB
diff -up util-linux-2.23.2/include/pathnames.h.kzak util-linux-2.23.2/include/pathnames.h |
|
--- util-linux-2.23.2/include/pathnames.h.kzak 2016-03-16 15:17:42.648298525 +0100 |
|
+++ util-linux-2.23.2/include/pathnames.h 2016-03-16 15:18:13.769055345 +0100 |
|
@@ -36,6 +36,7 @@ |
|
#endif |
|
#define _PATH_MOTDFILE "/etc/motd" |
|
#define _PATH_NOLOGIN "/etc/nologin" |
|
+#define _PATH_VAR_NOLOGIN "/var/run/nologin" |
|
|
|
#define _PATH_LOGIN "/bin/login" |
|
#define _PATH_INITTAB "/etc/inittab" |
|
diff -up util-linux-2.23.2/login-utils/lslogins.1.kzak util-linux-2.23.2/login-utils/lslogins.1 |
|
--- util-linux-2.23.2/login-utils/lslogins.1.kzak 2016-03-16 15:17:42.639298595 +0100 |
|
+++ util-linux-2.23.2/login-utils/lslogins.1 2016-03-16 15:18:13.769055345 +0100 |
|
@@ -5,7 +5,10 @@ |
|
lslogins \- display information about known users in the system |
|
.SH SYNOPSIS |
|
.B lslogins |
|
-[\fIoptions\fR] [\fB-s\fR|\fB-u\fR[=\fIUID\fR]] [\fB-g \fIgroups\fR] [\fB-l \fIlogins\fR] |
|
+[options] |
|
+.RB [ \-s | \-u [ =\fIUID ]] |
|
+.RB [ \-g " \fIgroups\fR]" |
|
+.RB [ \-l " \fIlogins\fR]" |
|
.SH DESCRIPTION |
|
.PP |
|
Examine the wtmp and btmp logs, /etc/shadow (if necessary) and /etc/passwd |
|
@@ -17,7 +20,7 @@ Mandatory arguments to long options are |
|
.TP |
|
\fB\-a\fR, \fB\-\-acc\-expiration\fR |
|
Display data about the date of last password change and the account expiration |
|
-date (see \fBshadow\fR(5) for more info). (Requires root priviliges.) |
|
+date (see \fBshadow\fR(5) for more info). (Requires root privileges.) |
|
.TP |
|
\fB\-\-btmp\-file \fIpath\fP |
|
Alternate path for btmp. |
|
@@ -31,7 +34,7 @@ Output data in the format of NAME=VALUE. |
|
\fB\-f\fR, \fB\-\-failed\fR |
|
Display data about the users' last failed login attempts. |
|
.TP |
|
-\fB\-G\fR, \fB\-\-groups\-info\fR |
|
+\fB\-G\fR, \fB\-\-supp\-groups\fR |
|
Show information about groups. |
|
.TP |
|
\fB\-g\fR, \fB\-\-groups\fR=\fIgroups\fR |
|
@@ -48,9 +51,6 @@ Display data containing information abou |
|
Only show data of users with a login specified in \fIlogins\fR (user names or user |
|
IDS). More than one login may be specified; the list has to be comma-separated. |
|
.TP |
|
-\fB\-m\fR, \fB\-\-supp\-groups\fR |
|
-Show supplementary groups. |
|
-.TP |
|
\fB\-n\fR, \fB\-\-newline\fR |
|
Display each piece of information on a separate line. |
|
.TP |
|
@@ -71,21 +71,21 @@ Display information related to login by |
|
\fB\-r\fR, \fB\-\-raw\fR |
|
Raw output (no columnation). |
|
.TP |
|
-\fB\-s\fR, \fB\-\-system\-accs\fR[=\fIthreshold\fR] |
|
+\fB\-s\fR, \fB\-\-system\-accs\fR |
|
Show system accounts. These are by default all accounts with a UID below 1000 |
|
-(non-inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID |
|
-threshold can also be specified explicitly (necessary for some distributions that |
|
-allocate UIDs starting from 100, 500 - or an entirely different value - rather than 1000). |
|
+(non-inclusive), with the exception of either nobody or nfsnobody (UID 65534). |
|
+This hardcoded default maybe overwritten by parameters SYS_UID_MIN and SYS_UID_MAX in |
|
+the file /etc/login.defs. |
|
.TP |
|
-\fB\-\-time-format\fR \fItype\fP |
|
+\fB\-\-time\-format\fR \fItype\fP |
|
Display dates in short, full or iso format. The default is short, this time |
|
format is designed to be space efficient and human readable. |
|
.TP |
|
-\fB\-u\fR, \fB\-\-user\-accs\fR[=\fIthreshold\fR] |
|
+\fB\-u\fR, \fB\-\-user\-accs\fR |
|
Show user accounts. These are by default all accounts with UID above 1000 |
|
-(inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID |
|
-threshold can also be specified explicitly (necessary for some distributions that |
|
-allocate UIDs starting from 100, 500 - or an entirely different value - rather than 1000). |
|
+(inclusive), with the exception of either nobody or nfsnobody (UID 65534). |
|
+This hardcoded default maybe overwritten by parameters UID_MIN and UID_MAX in |
|
+the file /etc/login.defs. |
|
.TP |
|
\fB\-V\fR, \fB\-\-version\fR |
|
Display version information and exit. |
|
diff -up util-linux-2.23.2/login-utils/lslogins.c.kzak util-linux-2.23.2/login-utils/lslogins.c |
|
--- util-linux-2.23.2/login-utils/lslogins.c.kzak 2016-03-16 15:17:42.639298595 +0100 |
|
+++ util-linux-2.23.2/login-utils/lslogins.c 2016-03-16 15:22:49.845899268 +0100 |
|
@@ -144,6 +144,7 @@ enum { |
|
TIME_SHORT, |
|
TIME_FULL, |
|
TIME_ISO, |
|
+ TIME_ISO_SHORT, |
|
}; |
|
|
|
/* |
|
@@ -350,6 +351,9 @@ static char *make_time(int mode, time_t |
|
case TIME_ISO: |
|
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &tm); |
|
break; |
|
+ case TIME_ISO_SHORT: |
|
+ strftime(buf, sizeof(buf), "%Y-%m-%d", &tm); |
|
+ break; |
|
default: |
|
errx(EXIT_FAILURE, _("unsupported time type")); |
|
} |
|
@@ -396,7 +400,7 @@ again: |
|
x = snprintf(p, len, "%s,", grp->gr_name); |
|
} |
|
|
|
- if (x < 0 || (size_t) x + 1 > len) { |
|
+ if (x < 0 || (size_t) x >= len) { |
|
size_t cur = p - res; |
|
|
|
maxlen *= 2; |
|
@@ -496,21 +500,24 @@ static int parse_btmp(struct lslogins_co |
|
static int get_sgroups(gid_t **list, size_t *len, struct passwd *pwd) |
|
{ |
|
size_t n = 0; |
|
+ int ngroups = 0; |
|
|
|
*len = 0; |
|
*list = NULL; |
|
|
|
/* first let's get a supp. group count */ |
|
- getgrouplist(pwd->pw_name, pwd->pw_gid, *list, (int *) len); |
|
- if (!*len) |
|
+ getgrouplist(pwd->pw_name, pwd->pw_gid, *list, &ngroups); |
|
+ if (!ngroups) |
|
return -1; |
|
|
|
- *list = xcalloc(1, *len * sizeof(gid_t)); |
|
+ *list = xcalloc(1, ngroups * sizeof(gid_t)); |
|
|
|
/* now for the actual list of GIDs */ |
|
- if (-1 == getgrouplist(pwd->pw_name, pwd->pw_gid, *list, (int *) len)) |
|
+ if (-1 == getgrouplist(pwd->pw_name, pwd->pw_gid, *list, &ngroups)) |
|
return -1; |
|
|
|
+ *len = (size_t) ngroups; |
|
+ |
|
/* getgroups also returns the user's primary GID - dispose of it */ |
|
while (n < *len) { |
|
if ((*list)[n] == pwd->pw_gid) |
|
@@ -520,6 +527,7 @@ static int get_sgroups(gid_t **list, siz |
|
|
|
if (*len) |
|
(*list)[n] = (*list)[--(*len)]; |
|
+ |
|
return 0; |
|
} |
|
|
|
@@ -685,8 +693,8 @@ static struct lslogins_user *get_user_in |
|
if (strstr(pwd->pw_shell, "nologin")) |
|
user->nologin = 1; |
|
else if (pwd->pw_uid) |
|
- user->nologin = access("/etc/nologin", F_OK) == 0 || |
|
- access("/var/run/nologin", F_OK) == 0; |
|
+ user->nologin = access(_PATH_NOLOGIN, F_OK) == 0 || |
|
+ access(_PATH_VAR_NOLOGIN, F_OK) == 0; |
|
break; |
|
case COL_PWD_WARN: |
|
if (shadow && shadow->sp_warn >= 0) |
|
@@ -694,7 +702,8 @@ static struct lslogins_user *get_user_in |
|
break; |
|
case COL_PWD_EXPIR: |
|
if (shadow && shadow->sp_expire >= 0) |
|
- user->pwd_expire = make_time(TIME_SHORT, |
|
+ user->pwd_expire = make_time(ctl->time_mode == TIME_ISO ? |
|
+ TIME_ISO_SHORT : ctl->time_mode, |
|
shadow->sp_expire * 86400); |
|
break; |
|
case COL_PWD_CTIME: |
|
@@ -702,7 +711,8 @@ static struct lslogins_user *get_user_in |
|
* (especially in non-GMT timezones) would only serve |
|
* to confuse */ |
|
if (shadow) |
|
- user->pwd_ctime = make_time(TIME_SHORT, |
|
+ user->pwd_ctime = make_time(ctl->time_mode == TIME_ISO ? |
|
+ TIME_ISO_SHORT : ctl->time_mode, |
|
shadow->sp_lstchg * 86400); |
|
break; |
|
case COL_PWD_CTIME_MIN: |
|
@@ -852,7 +862,7 @@ static int get_user(struct lslogins_cont |
|
const char *username) |
|
{ |
|
*user = get_user_info(ctl, username); |
|
- if (!*user && errno) |
|
+ if (!*user) |
|
if (IS_REAL_ERRNO(errno)) |
|
return -1; |
|
return 0; |
|
@@ -887,33 +897,33 @@ static int create_usertree(struct lslogi |
|
|
|
static struct libscols_table *setup_table(struct lslogins_control *ctl) |
|
{ |
|
- struct libscols_table *tb = scols_new_table(); |
|
+ struct libscols_table *table = scols_new_table(); |
|
int n = 0; |
|
|
|
- if (!tb) |
|
+ if (!table) |
|
errx(EXIT_FAILURE, _("failed to initialize output table")); |
|
if (ctl->noheadings) |
|
- scols_table_enable_noheadings(tb, 1); |
|
+ scols_table_enable_noheadings(table, 1); |
|
|
|
switch(outmode) { |
|
case OUT_COLON: |
|
- scols_table_enable_raw(tb, 1); |
|
- scols_table_set_column_separator(tb, ":"); |
|
+ scols_table_enable_raw(table, 1); |
|
+ scols_table_set_column_separator(table, ":"); |
|
break; |
|
case OUT_NEWLINE: |
|
- scols_table_set_column_separator(tb, "\n"); |
|
+ scols_table_set_column_separator(table, "\n"); |
|
/* fallthrough */ |
|
case OUT_EXPORT: |
|
- scols_table_enable_export(tb, 1); |
|
+ scols_table_enable_export(table, 1); |
|
break; |
|
case OUT_NUL: |
|
- scols_table_set_line_separator(tb, "\0"); |
|
+ scols_table_set_line_separator(table, "\0"); |
|
/* fallthrough */ |
|
case OUT_RAW: |
|
- scols_table_enable_raw(tb, 1); |
|
+ scols_table_enable_raw(table, 1); |
|
break; |
|
case OUT_PRETTY: |
|
- scols_table_enable_noheadings(tb, 1); |
|
+ scols_table_enable_noheadings(table, 1); |
|
default: |
|
break; |
|
} |
|
@@ -924,7 +934,7 @@ static struct libscols_table *setup_tabl |
|
if (ctl->notrunc) |
|
flags &= ~SCOLS_FL_TRUNC; |
|
|
|
- if (!scols_table_new_column(tb, |
|
+ if (!scols_table_new_column(table, |
|
coldescs[columns[n]].name, |
|
coldescs[columns[n]].whint, |
|
flags)) |
|
@@ -932,9 +942,9 @@ static struct libscols_table *setup_tabl |
|
++n; |
|
} |
|
|
|
- return tb; |
|
+ return table; |
|
fail: |
|
- scols_unref_table(tb); |
|
+ scols_unref_table(table); |
|
return NULL; |
|
} |
|
|
|
@@ -1050,10 +1060,10 @@ static void fill_table(const void *u, co |
|
return; |
|
} |
|
#ifdef HAVE_LIBSYSTEMD |
|
-static void print_journal_tail(const char *journal_path, uid_t uid, size_t len) |
|
+static void print_journal_tail(const char *journal_path, uid_t uid, size_t len, int time_mode) |
|
{ |
|
sd_journal *j; |
|
- char *match, *buf; |
|
+ char *match, *timestamp; |
|
uint64_t x; |
|
time_t t; |
|
const char *identifier, *pid, *message; |
|
@@ -1064,7 +1074,6 @@ static void print_journal_tail(const cha |
|
else |
|
sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); |
|
|
|
- buf = xmalloc(sizeof(char) * 16); |
|
xasprintf(&match, "_UID=%d", uid); |
|
|
|
sd_journal_add_match(j, match, 0); |
|
@@ -1074,37 +1083,35 @@ static void print_journal_tail(const cha |
|
do { |
|
if (0 > sd_journal_get_data(j, "SYSLOG_IDENTIFIER", |
|
(const void **) &identifier, &identifier_len)) |
|
- return; |
|
+ goto done; |
|
if (0 > sd_journal_get_data(j, "_PID", |
|
(const void **) &pid, &pid_len)) |
|
- return; |
|
+ goto done; |
|
if (0 > sd_journal_get_data(j, "MESSAGE", |
|
(const void **) &message, &message_len)) |
|
- return; |
|
+ goto done; |
|
|
|
sd_journal_get_realtime_usec(j, &x); |
|
t = x / 1000000; |
|
- strftime(buf, 16, "%b %d %H:%M:%S", localtime(&t)); |
|
- |
|
- fprintf(stdout, "%s", buf); |
|
- |
|
+ timestamp = make_time(time_mode, t); |
|
+ /* Get rid of journal entry field identifiers */ |
|
identifier = strchr(identifier, '=') + 1; |
|
- pid = strchr(pid, '=') + 1 ; |
|
+ pid = strchr(pid, '=') + 1; |
|
message = strchr(message, '=') + 1; |
|
|
|
- fprintf(stdout, " %s", identifier); |
|
- fprintf(stdout, "[%s]:", pid); |
|
- fprintf(stdout, "%s\n", message); |
|
+ fprintf(stdout, "%s %s[%s]: %s\n", timestamp, identifier, pid, |
|
+ message); |
|
+ free(timestamp); |
|
} while (sd_journal_next(j)); |
|
|
|
- free(buf); |
|
+done: |
|
free(match); |
|
sd_journal_flush_matches(j); |
|
sd_journal_close(j); |
|
} |
|
#endif |
|
|
|
-static int print_pretty(struct libscols_table *tb) |
|
+static int print_pretty(struct libscols_table *table) |
|
{ |
|
struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD); |
|
struct libscols_column *col; |
|
@@ -1113,8 +1120,8 @@ static int print_pretty(struct libscols_ |
|
const char *hstr, *dstr; |
|
int n = 0; |
|
|
|
- ln = scols_table_get_line(tb, 0); |
|
- while (!scols_table_next_column(tb, itr, &col)) { |
|
+ ln = scols_table_get_line(table, 0); |
|
+ while (!scols_table_next_column(table, itr, &col)) { |
|
|
|
data = scols_line_get_cell(ln, n); |
|
|
|
@@ -1142,7 +1149,7 @@ static int print_user_table(struct lslog |
|
print_pretty(tb); |
|
#ifdef HAVE_LIBSYSTEMD |
|
fprintf(stdout, _("\nLast logs:\n")); |
|
- print_journal_tail(ctl->journal_path, ctl->uid, 3); |
|
+ print_journal_tail(ctl->journal_path, ctl->uid, 3, ctl->time_mode); |
|
fputc('\n', stdout); |
|
#endif |
|
} else |
|
@@ -1175,16 +1182,25 @@ static void free_user(void *f) |
|
free(u); |
|
} |
|
|
|
-struct lslogins_timefmt { |
|
- const char *name; |
|
- int val; |
|
-}; |
|
+static int parse_time_mode(const char *optarg) |
|
+{ |
|
+ struct lslogins_timefmt { |
|
+ const char *name; |
|
+ const int val; |
|
+ }; |
|
+ static const struct lslogins_timefmt timefmts[] = { |
|
+ {"iso", TIME_ISO}, |
|
+ {"full", TIME_FULL}, |
|
+ {"short", TIME_SHORT}, |
|
+ }; |
|
+ size_t i; |
|
|
|
-static struct lslogins_timefmt timefmts[] = { |
|
- { "short", TIME_SHORT }, |
|
- { "full", TIME_FULL }, |
|
- { "iso", TIME_ISO }, |
|
-}; |
|
+ for (i = 0; i < ARRAY_SIZE(timefmts); i++) { |
|
+ if (strcmp(timefmts[i].name, optarg) == 0) |
|
+ return timefmts[i].val; |
|
+ } |
|
+ errx(EXIT_FAILURE, _("unknown time format: %s"), optarg); |
|
+} |
|
|
|
static void __attribute__((__noreturn__)) usage(FILE *out) |
|
{ |
|
@@ -1193,16 +1209,18 @@ static void __attribute__((__noreturn__) |
|
fputs(USAGE_HEADER, out); |
|
fprintf(out, _(" %s [options]\n"), program_invocation_short_name); |
|
|
|
+ fputs(USAGE_SEPARATOR, out); |
|
+ fputs(_("Display information about known users in the system.\n"), out); |
|
+ |
|
fputs(USAGE_OPTIONS, out); |
|
fputs(_(" -a, --acc-expiration display info about passwords expiration\n"), out); |
|
fputs(_(" -c, --colon-separate display data in a format similar to /etc/passwd\n"), out); |
|
fputs(_(" -e, --export display in an export-able output format\n"), out); |
|
fputs(_(" -f, --failed display data about the users' last failed logins\n"), out); |
|
- fputs(_(" -G, --groups-info display information about groups\n"), out); |
|
+ fputs(_(" -G, --supp-groups display information about groups\n"), out); |
|
fputs(_(" -g, --groups=<groups> display users belonging to a group in <groups>\n"), out); |
|
fputs(_(" -L, --last show info about the users' last login sessions\n"), out); |
|
fputs(_(" -l, --logins=<logins> display only users from <logins>\n"), out); |
|
- fputs(_(" -m, --supp-groups display supplementary groups as well\n"), out); |
|
fputs(_(" -n, --newline display each piece of information on a new line\n"), out); |
|
fputs(_(" --noheadings don't print headings\n"), out); |
|
fputs(_(" --notruncate don't truncate output\n"), out); |
|
@@ -1226,7 +1244,7 @@ static void __attribute__((__noreturn__) |
|
fprintf(out, " %14s %s\n", coldescs[i].name, |
|
_(coldescs[i].help)); |
|
|
|
- fprintf(out, _("\nFor more details see lslogins(1).\n")); |
|
+ fprintf(out, USAGE_MAN_TAIL("lslogins(1)")); |
|
|
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); |
|
} |
|
@@ -1241,8 +1259,7 @@ int main(int argc, char *argv[]) |
|
|
|
/* long only options. */ |
|
enum { |
|
- OPT_VER = CHAR_MAX + 1, |
|
- OPT_WTMP, |
|
+ OPT_WTMP = CHAR_MAX + 1, |
|
OPT_BTMP, |
|
OPT_NOTRUNC, |
|
OPT_NOHEAD, |
|
@@ -1300,7 +1317,7 @@ int main(int argc, char *argv[]) |
|
add_column(columns, ncolumns++, COL_UID); |
|
add_column(columns, ncolumns++, COL_USER); |
|
|
|
- while ((c = getopt_long(argc, argv, "acfGg:hLl:no:prsuVxzZ", |
|
+ while ((c = getopt_long(argc, argv, "acefGg:hLl:no:prsuVzZ", |
|
longopts, NULL)) != -1) { |
|
|
|
err_exclusive_options(c, longopts, excl, excl_st); |
|
@@ -1394,18 +1411,7 @@ int main(int argc, char *argv[]) |
|
ctl->noheadings = 1; |
|
break; |
|
case OPT_TIME_FMT: |
|
- { |
|
- size_t i; |
|
- |
|
- for (i = 0; i < ARRAY_SIZE(timefmts); i++) { |
|
- if (strcmp(timefmts[i].name, optarg) == 0) { |
|
- ctl->time_mode = timefmts[i].val; |
|
- break; |
|
- } |
|
- } |
|
- if (ctl->time_mode == TIME_INVALID) |
|
- usage(stderr); |
|
- } |
|
+ ctl->time_mode = parse_time_mode(optarg); |
|
break; |
|
case 'V': |
|
printf(UTIL_LINUX_VERSION); |
|
@@ -1433,7 +1439,7 @@ int main(int argc, char *argv[]) |
|
logins = argv[optind]; |
|
outmode = OUT_PRETTY; |
|
} else if (argc != optind) |
|
- usage(stderr); |
|
+ errx(EXIT_FAILURE, _("Only one user may be specified. Use -l for multiple users.")); |
|
|
|
scols_init_debug(0); |
|
|
|
|