lslogins(1): skeleton and argparsing for a new utility
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
This commit is contained in:
parent
37bc9a51c8
commit
ab1cfad5b7
|
@ -1047,6 +1047,11 @@ UL_REQUIRES_HAVE([lscpu], [cpu_set_t], [cpu_set_t type])
|
||||||
AM_CONDITIONAL([BUILD_LSCPU], [test "x$build_lscpu" = xyes])
|
AM_CONDITIONAL([BUILD_LSCPU], [test "x$build_lscpu" = xyes])
|
||||||
|
|
||||||
|
|
||||||
|
UL_BUILD_INIT([lslogins], [check])
|
||||||
|
UL_REQUIRES_BUILD([lslogins], [libsmartcols])
|
||||||
|
AM_CONDITIONAL([BUILD_LSLOGINS], [test "x$build_lslogins" = xyes])
|
||||||
|
|
||||||
|
|
||||||
UL_BUILD_INIT([chcpu], [check])
|
UL_BUILD_INIT([chcpu], [check])
|
||||||
UL_REQUIRES_LINUX([chcpu])
|
UL_REQUIRES_LINUX([chcpu])
|
||||||
UL_REQUIRES_HAVE([chcpu], [cpu_set_t], [cpu_set_t type])
|
UL_REQUIRES_HAVE([chcpu], [cpu_set_t], [cpu_set_t type])
|
||||||
|
|
|
@ -334,3 +334,13 @@ dist_man_MANS += sys-utils/setpriv.1
|
||||||
setpriv_SOURCES = sys-utils/setpriv.c
|
setpriv_SOURCES = sys-utils/setpriv.c
|
||||||
setpriv_LDADD = $(LDADD) -lcap-ng libcommon.la
|
setpriv_LDADD = $(LDADD) -lcap-ng libcommon.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_LSLOGINS
|
||||||
|
usrbin_exec_PROGRAMS += lslogins
|
||||||
|
dist_man_MANS += sys-utils/lslogins.1
|
||||||
|
lslogins_SOURCES = \
|
||||||
|
sys-utils/lslogins.c \
|
||||||
|
sys-utils/lslogins.h
|
||||||
|
lslogins_LDADD = $(LDADD) libcommon.la libsmartcols.la
|
||||||
|
lslogins_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir)
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
.\" Copyright 2014 Ondrej Oprala (ondrej.oprala@gmail.com)
|
||||||
|
.\" May be distributed under the GNU General Public License
|
||||||
|
.TH LSLOGINS "1" "April 2014" "util-linux" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
lslogins \- display information about known users in the system
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B lslogins
|
||||||
|
[\fI-adehmoptvx\fR] [-s|-u[\fI=UID\fR]] [-g \fIGROUPS\fR] [-l \fILOGINS\fR]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
Examine the wtmp and btmp logs, /etc/shadow (if necessary) and /etc/passwd
|
||||||
|
and output the desired data.
|
||||||
|
.PP
|
||||||
|
Mandatory arguments to long options are mandatory for short options too.
|
||||||
|
.PP
|
||||||
|
The default action is to list info about all the users in the system.
|
||||||
|
.SH OPTIONS
|
||||||
|
.PP
|
||||||
|
Display info about existing users.
|
||||||
|
.TP
|
||||||
|
\fB\-a\fR, \fB\-\-acc\-expiration\fR
|
||||||
|
Display data about the date of last password change and the account expiration date (see shadow(5) for more info).
|
||||||
|
.TP
|
||||||
|
\fB\-c\fR, \fB\-\-colon\fR
|
||||||
|
Separate info about each user with a colon instead of a newline.
|
||||||
|
.TP
|
||||||
|
\fB\-d\fR, \fB\-\-duplicates\fR
|
||||||
|
Show users with duplicate UIDs.
|
||||||
|
.TP
|
||||||
|
\fB\-e\fR, \fB\-\-export\fR
|
||||||
|
Output data in the format of NAME=VALUE.
|
||||||
|
.TP
|
||||||
|
\fB\-f\fR, \fB\-\-failed\fR
|
||||||
|
Display data about the users' last failed login attempts.
|
||||||
|
.TP
|
||||||
|
\fB\-g\fR, \fB\-\-groups\fR=\fIGROUPS\fR
|
||||||
|
Only show data of users belonging to \fIGROUPS\fR. More than one group may be specified; the list has to be comma-separated.
|
||||||
|
.TP
|
||||||
|
\fB\-\-last\fR
|
||||||
|
Display data containing information about the users' last login sessions.
|
||||||
|
.TP
|
||||||
|
\fB\-l\fR, \fB\-\-logins\fR=\fILOGINS\fR
|
||||||
|
Only show data of users with a login specified in \fILOGINS\fR. More than one login may be specified; the list has to be comma-separated.
|
||||||
|
.TP
|
||||||
|
\fB\-m\fR, \fB\-\-more\fR
|
||||||
|
Show secondary groups as well.
|
||||||
|
.TP
|
||||||
|
\fB\-n\fR, \fB\-\-newline\fR
|
||||||
|
Display each piece of information on a separate line.
|
||||||
|
.TP
|
||||||
|
\fB\-p\fR, \fB\-\-no\-password\fR
|
||||||
|
Show users without a password.
|
||||||
|
.TP
|
||||||
|
\fB\-r\fR, \fB\-\-raw\fR
|
||||||
|
Raw output (no columnation).
|
||||||
|
.TP
|
||||||
|
\fB\-s\fR, \fB\-\-sys\-accs\fR[=\fIUID\fR]
|
||||||
|
Show system accounts. These are by the default all accounts with UID below 1000 (non-inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID
|
||||||
|
treshold can also be specified explicitly (necessary for some distributions that allocate UIDs
|
||||||
|
starting from 100, 500 - or an entirely different value - rather than 1000).
|
||||||
|
.TP
|
||||||
|
\fB\-t\fR, \fB\-\-sort\fR
|
||||||
|
Sort by user name, rather than UID.
|
||||||
|
.TP
|
||||||
|
\fB\-u\fR, \fB\-\-user\-accs\fR[=\fIUID\fR]
|
||||||
|
Show user accounts. These are by the default all accounts with UID above 1000 (inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID
|
||||||
|
treshold can also be specified explicitly (necessary for some distributions that allocate UIDs
|
||||||
|
starting from 100, 500 - or an entirely different value - rather than 1000).
|
||||||
|
.TP
|
||||||
|
\fB\-x\fR, \fB\-\-extra\fR
|
||||||
|
Show extra information about users - home diretory, default login shell, password age and expiry information.
|
||||||
|
.TP
|
||||||
|
\fB\-z\fR, \fB\-\-print0\fR
|
||||||
|
Delimit user entries with a nul character, instead of a newline.
|
||||||
|
.TP
|
||||||
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
Display help information and exit.
|
||||||
|
\fB\-v\fR, \fB\-\-version\fR
|
||||||
|
Display version information and exit.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Note that switches -a and -x require root priviliges. Otherwise their fields will state <unknown> for each entry.
|
||||||
|
.sp
|
||||||
|
.SH COLORS
|
||||||
|
Implicit coloring can be disabled as follows:
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.br
|
||||||
|
.BI "touch /etc/terminal-colors.d/lslogins.disable"
|
||||||
|
.br
|
||||||
|
|
||||||
|
.RE
|
||||||
|
For more details see
|
||||||
|
.BR terminal-colors.d (5).
|
||||||
|
.SH EXIT STATUS
|
||||||
|
.TP
|
||||||
|
0
|
||||||
|
if OK,
|
||||||
|
.TP
|
||||||
|
1
|
||||||
|
if incorrect arguments specified,
|
||||||
|
.TP
|
||||||
|
2
|
||||||
|
if a serious error occurs (e.g. a corrupt log).
|
||||||
|
.SH SEE ALSO
|
||||||
|
\fBgroup\fP(5), \fBpasswd\fP(5), \fBshadow\fP(5), \fButmp\fP(5)
|
||||||
|
.SH HISTORY
|
||||||
|
The \fBlslogins\fP utility is inspired by the \fBlogins\fP utility, which first appeared in FreeBSD 4.10.
|
||||||
|
.SH AUTHORS
|
||||||
|
.MT ondrej.oprala@gmail.com
|
||||||
|
Ondrej Oprala
|
||||||
|
.ME
|
||||||
|
.SH AVAILABILITY
|
||||||
|
The lslogins command is part of the util-linux package and is available from
|
||||||
|
.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
|
||||||
|
Linux Kernel Archive
|
||||||
|
.UE .
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
* lslogins - List information about users on the system
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it would be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "c.h"
|
||||||
|
#include "nls.h"
|
||||||
|
#include "closestream.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
#include "strutils.h"
|
||||||
|
#include "optutils.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* column description
|
||||||
|
*/
|
||||||
|
struct lslogins_coldesc {
|
||||||
|
const char *name;
|
||||||
|
const char *help;
|
||||||
|
|
||||||
|
unsigned int is_abbr:1; /* name is abbreviation */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the most uber of flags */
|
||||||
|
static int uberflag;
|
||||||
|
|
||||||
|
/* we use the value of outmode to determine
|
||||||
|
* appropriate flags for the libsmartcols table
|
||||||
|
* (e.g., a value of out_newline would imply a raw
|
||||||
|
* table with the column separator set to '\n').
|
||||||
|
*/
|
||||||
|
static int outmode;
|
||||||
|
/*
|
||||||
|
* output modes
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
out_colon = 0,
|
||||||
|
out_export,
|
||||||
|
out_newline,
|
||||||
|
out_raw,
|
||||||
|
out_nul,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lslogins_user {
|
||||||
|
char *login;
|
||||||
|
uid_t uid;
|
||||||
|
char *group;
|
||||||
|
gid_t gid;
|
||||||
|
char *gecos;
|
||||||
|
|
||||||
|
int nopasswd:1;
|
||||||
|
|
||||||
|
char *sgroups;
|
||||||
|
|
||||||
|
struct tm *pwd_ctime;
|
||||||
|
struct tm *pwd_expir;
|
||||||
|
|
||||||
|
struct tm *last_login;
|
||||||
|
char * last_tty;
|
||||||
|
char * last_hostname;
|
||||||
|
|
||||||
|
struct tm *failed_login;
|
||||||
|
struct tm *failed_tty;
|
||||||
|
|
||||||
|
char *homedir;
|
||||||
|
char *shell;
|
||||||
|
char *pwd_status;
|
||||||
|
char *hush_status;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* flags
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
F_EXPIR = (1 << 0),
|
||||||
|
F_DUP = (1 << 1),
|
||||||
|
F_EXPRT = (1 << 2),
|
||||||
|
F_MORE = (1 << 3),
|
||||||
|
F_NOPWD = (1 << 4),
|
||||||
|
F_SYSAC = (1 << 5),
|
||||||
|
F_USRAC = (1 << 6),
|
||||||
|
F_SORT = (1 << 7),
|
||||||
|
F_EXTRA = (1 << 8),
|
||||||
|
F_FAIL = (1 << 9),
|
||||||
|
F_LAST = (1 << 10),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IDs
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
COL_LOGIN = 0,
|
||||||
|
COL_UID,
|
||||||
|
COL_NOPASSWD,
|
||||||
|
COL_PGRP,
|
||||||
|
COL_PGID,
|
||||||
|
COL_SGRPS,
|
||||||
|
COL_HOME,
|
||||||
|
COL_SHELL,
|
||||||
|
COL_FULLNAME,
|
||||||
|
COL_LAST_LOGIN,
|
||||||
|
COL_LAST_TTY,
|
||||||
|
COL_LAST_HOSTNAME,
|
||||||
|
COL_FAILED_LOGIN,
|
||||||
|
COL_FAILED_TTY,
|
||||||
|
COL_HUSH_STATUS,
|
||||||
|
COL_PWD_STATUS,
|
||||||
|
COL_PWD_EXPIR,
|
||||||
|
COL_PWD_CTIME,
|
||||||
|
/*COL_PWD_CTIME_MAX,
|
||||||
|
COL_PWD_CTIME_MIN,*/
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct lslogins_coldesc coldescs[] =
|
||||||
|
{
|
||||||
|
[COL_LOGIN] = { "LOGIN", N_("user/system login"), 1 },
|
||||||
|
[COL_UID] = { "UID", N_("user UID") },
|
||||||
|
[COL_NOPASSWD] = { "HAS PASSWORD", N_("account has a password?") },
|
||||||
|
[COL_PGRP] = { "GRP", N_("primary group name") },
|
||||||
|
[COL_PGID] = { "GRP_GID", N_("primary group GID") },
|
||||||
|
[COL_SGRPS] = { "SEC_GRPS", N_("secondary group names and GIDs") },
|
||||||
|
[COL_HOME] = { "HOMEDIR", N_("home directory") },
|
||||||
|
[COL_SHELL] = { "SHELL", N_("login shell") },
|
||||||
|
[COL_FULLNAME] = { "FULLNAME", N_("full user name") },
|
||||||
|
[COL_LAST_LOGIN] = { "LAST_LOGIN", N_("date of last login") },
|
||||||
|
[COL_LAST_TTY] = { "LAST_TTY", N_("last tty used") },
|
||||||
|
[COL_LAST_HOSTNAME] = { "LAST_HOSTNAME", N_("hostname during the last session") },
|
||||||
|
[COL_FAILED_LOGIN] = { "FAILED_LOGIN", N_("date of last failed login") },
|
||||||
|
[COL_FAILED_TTY] = { "FAILED_TTY", N_("where did the login fail?") },
|
||||||
|
[COL_HUSH_STATUS] = { "HUSH_STATUS", N_("User's hush settings") },
|
||||||
|
[COL_PWD_STATUS] = { "PWD_STATUS", N_("password status - see the -x option description") },
|
||||||
|
[COL_PWD_EXPIR] = { "PWD_EXPIR", N_("password expiration date") },
|
||||||
|
[COL_PWD_CTIME] = { "PWD_CHANGE", N_("date of last password change") },
|
||||||
|
/*[COL_PWD_CTIME_MAX] = { "PWD UNTIL", N_("max number of days a password may remain unchanged") },
|
||||||
|
[COL_PWD_CTIME_MIN] = { "PWD CAN CHANGE", N_("number of days required between changes") },*/
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
column_name_to_id(const char *name, size_t namesz)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(coldescs); i++) {
|
||||||
|
const char *cn = coldescs[i].name;
|
||||||
|
|
||||||
|
if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
warnx(_("unknown column: %s"), name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((__noreturn__)) usage(FILE *out)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
fputs(USAGE_HEADER, out);
|
||||||
|
fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
|
||||||
|
|
||||||
|
fputs(USAGE_OPTIONS, out);
|
||||||
|
fputs(_(" -a, --acc-expiration Display data\n"), out);
|
||||||
|
fputs(_(" -c, --colon-separate Display data in a format similar to /etc/passwd\n"), out);
|
||||||
|
fputs(_(" -d, --duplicates Display users with duplicate UIDs\n"), out);
|
||||||
|
fputs(_(" -e, --export Display in an export-able output format\n"), out);
|
||||||
|
fputs(_(" -f, --failed Display data about the last users' failed logins\n"), out);
|
||||||
|
fputs(_(" -g, --groups=<GROUPS> Display users belonging to a group in GROUPS\n"), out);
|
||||||
|
fputs(_(" -l, --logins=<LOGINS> Display only users from LOGINS\n"), out);
|
||||||
|
fputs(_(" --last Show info about the last login sessions\n"), out);
|
||||||
|
fputs(_(" -m, --more Display secondary groups as well\n"), out);
|
||||||
|
fputs(_(" -n, --newline Display each piece of information on a new line\n"), out);
|
||||||
|
fputs(_(" -o, --output[=<LIST>] Define the columns to output\n"), out);
|
||||||
|
fputs(_(" -p, --no-password Display users without a password\n"), out);
|
||||||
|
fputs(_(" -r, --raw Display the raw table\n"), out);
|
||||||
|
fputs(_(" -s, --sys-accs[=<UID>] Display system accounts\n"), out);
|
||||||
|
fputs(_(" -t, --sort Sort output by login instead of UID\n"), out);
|
||||||
|
fputs(_(" -u, --user-accs[=<UID>] Display user accounts\n"), out);
|
||||||
|
fputs(_(" -x, --extra Display extra information\n"), out);
|
||||||
|
fputs(_(" -z, --print0 Delimit user entries with a nul character"), out);
|
||||||
|
fputs(USAGE_SEPARATOR, out);
|
||||||
|
fputs(USAGE_HELP, out);
|
||||||
|
fputs(USAGE_VERSION, out);
|
||||||
|
|
||||||
|
fprintf(out, _("\nAvailable columns:\n"));
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(coldescs); i++)
|
||||||
|
fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
|
||||||
|
|
||||||
|
fprintf(out, _("\nFor more details see lslogins(1).\n"));
|
||||||
|
|
||||||
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
int columns[ARRAY_SIZE(coldescs)], ncolumns = 0;
|
||||||
|
char *logins = NULL, *groups = NULL;
|
||||||
|
|
||||||
|
/* long only options. */
|
||||||
|
enum {
|
||||||
|
OPT_LAST = CHAR_MAX + 1,
|
||||||
|
OPT_VER,
|
||||||
|
};
|
||||||
|
static const struct option longopts[] = {
|
||||||
|
{ "acc-expiration", no_argument, 0, 'a' },
|
||||||
|
{ "colon", no_argument, 0, 'c' },
|
||||||
|
{ "duplicates", no_argument, 0, 'd' },
|
||||||
|
{ "export", no_argument, 0, 'e' },
|
||||||
|
{ "failed", no_argument, 0, 'f' },
|
||||||
|
{ "groups", required_argument, 0, 'g' },
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ "logins", required_argument, 0, 'l' },
|
||||||
|
{ "more", no_argument, 0, 'm' },
|
||||||
|
{ "newline", no_argument, 0, 'n' },
|
||||||
|
{ "output", optional_argument, 0, 'o' },
|
||||||
|
{ "no-password", no_argument, 0, 'p' },
|
||||||
|
{ "last", no_argument, 0, OPT_LAST },
|
||||||
|
{ "raw", no_argument, 0, 'r' },
|
||||||
|
{ "sys-accs", optional_argument, 0, 's' },
|
||||||
|
{ "sort", no_argument, 0, 't' },
|
||||||
|
{ "user-accs", optional_argument, 0, 'u' },
|
||||||
|
{ "version", no_argument, 0, OPT_VER },
|
||||||
|
{ "extra", no_argument, 0, 'x' },
|
||||||
|
{ "print0", no_argument, 0, 'z' },
|
||||||
|
{ NULL, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
|
||||||
|
{ 'c','e','n','r','z' },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
textdomain(PACKAGE);
|
||||||
|
atexit(close_stdout);
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "acdefg:hl:mno::prs::tu::xz",
|
||||||
|
longopts, NULL)) != -1) {
|
||||||
|
|
||||||
|
err_exclusive_options(c, longopts, excl, excl_st);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
uberflag |= F_EXPIR;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
outmode = out_colon;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
uberflag |= F_DUP;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
outmode = out_export;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
uberflag |= F_FAIL;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
groups = strdup(optarg);
|
||||||
|
if (!groups)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(stdout);
|
||||||
|
case 'l':
|
||||||
|
logins = strdup(optarg);
|
||||||
|
if (!logins)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
uberflag |= F_MORE;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
outmode = out_newline;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (optarg) {
|
||||||
|
if (*optarg == '=')
|
||||||
|
optarg++;
|
||||||
|
ncolumns = string_to_idarray(optarg,
|
||||||
|
columns, ARRAY_SIZE(columns),
|
||||||
|
column_name_to_id);
|
||||||
|
if (ncolumns < 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
uberflag |= F_NOPWD;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
outmode = out_raw;
|
||||||
|
break;
|
||||||
|
case OPT_LAST:
|
||||||
|
uberflag |= F_LAST;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
uberflag |= F_SYSAC;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
uberflag |= F_SORT;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
uberflag |= F_USRAC;
|
||||||
|
break;
|
||||||
|
case OPT_VER:
|
||||||
|
printf(_("%s from %s\n"), program_invocation_short_name,
|
||||||
|
PACKAGE_STRING);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case 'x':
|
||||||
|
uberflag |= F_EXTRA;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
outmode = out_nul;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc != optind)
|
||||||
|
usage(stderr);
|
||||||
|
|
||||||
|
if (!ncolumns) {
|
||||||
|
columns[ncolumns++] = COL_LOGIN;
|
||||||
|
columns[ncolumns++] = COL_UID;
|
||||||
|
columns[ncolumns++] = COL_PGRP;
|
||||||
|
columns[ncolumns++] = COL_PGID;
|
||||||
|
columns[ncolumns++] = COL_FULLNAME;
|
||||||
|
|
||||||
|
if (uberflag & F_NOPWD) {
|
||||||
|
columns[ncolumns++] = COL_NOPASSWD;
|
||||||
|
}
|
||||||
|
if (uberflag & F_MORE) {
|
||||||
|
columns[ncolumns++] = COL_SGRPS;
|
||||||
|
}
|
||||||
|
if (uberflag & F_EXPIR) {
|
||||||
|
columns[ncolumns++] = COL_PWD_CTIME;
|
||||||
|
columns[ncolumns++] = COL_PWD_EXPIR;
|
||||||
|
}
|
||||||
|
if (uberflag & F_LAST) {
|
||||||
|
columns[ncolumns++] = COL_LAST_LOGIN;
|
||||||
|
columns[ncolumns++] = COL_LAST_TTY;
|
||||||
|
columns[ncolumns++] = COL_LAST_HOSTNAME;
|
||||||
|
}
|
||||||
|
if (uberflag & F_FAIL) {
|
||||||
|
columns[ncolumns++] = COL_FAILED_LOGIN;
|
||||||
|
columns[ncolumns++] = COL_FAILED_TTY;
|
||||||
|
}
|
||||||
|
if (uberflag & F_EXTRA) {
|
||||||
|
columns[ncolumns++] = COL_HOME;
|
||||||
|
columns[ncolumns++] = COL_SHELL;
|
||||||
|
columns[ncolumns++] = COL_PWD_STATUS;
|
||||||
|
columns[ncolumns++] = COL_HUSH_STATUS;
|
||||||
|
/* columns[ncolumns++] = COL_PWD_CTIME_MAX;
|
||||||
|
columns[ncolumns++] = COL_PWD_CTIME_MIN; */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue