summaryrefslogtreecommitdiff
path: root/source/a/shadow/patches
diff options
context:
space:
mode:
Diffstat (limited to 'source/a/shadow/patches')
-rw-r--r--source/a/shadow/patches/README_PATCHES9
-rw-r--r--source/a/shadow/patches/r3054.diff27
-rw-r--r--source/a/shadow/patches/r3055.diff1515
-rw-r--r--source/a/shadow/patches/r3060.diff116
-rw-r--r--source/a/shadow/patches/r3062.diff139
-rw-r--r--source/a/shadow/patches/r3096.diff27
-rw-r--r--source/a/shadow/patches/r3160.diff239
-rw-r--r--source/a/shadow/patches/r3194.diff15
-rw-r--r--source/a/shadow/patches/r3299.diff12
9 files changed, 2099 insertions, 0 deletions
diff --git a/source/a/shadow/patches/README_PATCHES b/source/a/shadow/patches/README_PATCHES
new file mode 100644
index 00000000..0c639d1a
--- /dev/null
+++ b/source/a/shadow/patches/README_PATCHES
@@ -0,0 +1,9 @@
+
+r3054.diff: Fixed wrong format string
+r3055.diff: Help output to stderr not stdout.
+r3060.diff: Fix memory leaks
+r3062.diff: Avoid memzero() on a possibly NULL pointer.
+r3096.diff: Fix parsing of gshadow entries.
+r3160.diff: Fixed limits support (non PAM enabled versions only)
+r3194.diff: shell's name must be -su when a su fakes a login.
+r3299.diff: man/ru/Makefile.am: Remove double inclusion of $(man_nopam)
diff --git a/source/a/shadow/patches/r3054.diff b/source/a/shadow/patches/r3054.diff
new file mode 100644
index 00000000..dc1eab13
--- /dev/null
+++ b/source/a/shadow/patches/r3054.diff
@@ -0,0 +1,27 @@
+* src/useradd.c: Fixed wrong format string.
+* lib/gshadow.c: Removed declaration of unused variable.
+
+===================================================================
+--- src/useradd.c (revision 3052)
++++ src/useradd.c (revision 3054)
+@@ -684,7 +684,7 @@
+ static void usage (void)
+ {
+ (void) fprintf (stderr,
+- _("Usage: useradd [options] LOGIN\n"
++ _("Usage: %s [options] LOGIN\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+
+===================================================================
+--- lib/gshadow.c (revision 3052)
++++ lib/gshadow.c (revision 3054)
+@@ -216,7 +216,6 @@
+ static char *buf = NULL;
+
+ char *cp;
+- struct sgrp *ret;
+
+ if (0 == buflen) {
+ buf = (char *) malloc (BUFSIZ);
diff --git a/source/a/shadow/patches/r3055.diff b/source/a/shadow/patches/r3055.diff
new file mode 100644
index 00000000..a2af6f39
--- /dev/null
+++ b/source/a/shadow/patches/r3055.diff
@@ -0,0 +1,1515 @@
+===================================================================
+--- src/userdel.c (revision 3054)
++++ src/userdel.c (revision 3055)
+@@ -94,7 +94,7 @@
+ static bool spw_locked = false;
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static void update_groups (void);
+ static void close_files (void);
+ static void fail_exit (int);
+@@ -111,7 +111,7 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+ fputs (_("Usage: userdel [options] LOGIN\n"
+ "\n"
+@@ -120,8 +120,8 @@
+ " even if not owned by user\n"
+ " -h, --help display this help message and exit\n"
+ " -r, --remove remove home directory and mail spool\n"
+- "\n"), stderr);
+- exit (E_USAGE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ /*
+@@ -774,17 +774,19 @@
+ case 'f': /* force remove even if not owned by user */
+ fflg = true;
+ break;
++ case 'h':
++ usage (E_SUCCESS);
+ case 'r': /* remove home dir and mailbox */
+ rflg = true;
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+ }
+
+ if ((optind + 1) != argc) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ OPENLOG ("userdel");
+Index: src/lastlog.c
+===================================================================
+--- src/lastlog.c (revision 3054)
++++ src/lastlog.c (revision 3055)
+@@ -71,7 +71,7 @@
+
+ #define NOW (time ((time_t *) 0))
+
+-static void usage (void)
++static void usage (int status)
+ {
+ fputs (_("Usage: lastlog [options]\n"
+ "\n"
+@@ -80,8 +80,8 @@
+ " -h, --help display this help message and exit\n"
+ " -t, --time DAYS print only lastlog records more recent than DAYS\n"
+ " -u, --user LOGIN print lastlog record of the specified LOGIN\n"
+- "\n"), stderr);
+- exit (EXIT_FAILURE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ static void print_one (/*@null@*/const struct passwd *pw)
+@@ -208,7 +208,7 @@
+ NULL)) != -1) {
+ switch (c) {
+ case 'h':
+- usage ();
++ usage (EXIT_SUCCESS);
+ break;
+ case 't':
+ {
+@@ -267,7 +267,7 @@
+ break;
+ }
+ default:
+- usage ();
++ usage (EXIT_FAILURE);
+ break;
+ }
+ }
+@@ -275,7 +275,7 @@
+ fprintf (stderr,
+ _("lastlog: unexpected argument: %s\n"),
+ argv[optind]);
+- usage();
++ usage (EXIT_FAILURE);
+ }
+ }
+
+Index: src/gpasswd.c
+===================================================================
+--- src/gpasswd.c (revision 3054)
++++ src/gpasswd.c (revision 3055)
+@@ -94,7 +94,7 @@
+ #endif
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static RETSIGTYPE catch_signals (int killed);
+ static bool is_valid_user_list (const char *users);
+ static void process_flags (int argc, char **argv);
+@@ -128,14 +128,15 @@
+ /*
+ * usage - display usage message
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- fprintf (stderr,
++ fprintf (status ? stderr : stdout,
+ _("Usage: %s [option] GROUP\n"
+ "\n"
+ "Options:\n"
+ " -a, --add USER add USER to GROUP\n"
+ " -d, --delete USER remove USER from GROUP\n"
++ " -h, --help display this help message and exit\n"
+ " -r, --remove-password remove the GROUP's password\n"
+ " -R, --restrict restrict access to GROUP to its members\n"
+ " -M, --members USER,... set the list of members of GROUP\n"
+@@ -150,7 +151,7 @@
+ _("The options cannot be combined.\n")
+ #endif
+ );
+- exit (E_USAGE);
++ exit (status);
+ }
+
+ /*
+@@ -235,6 +236,7 @@
+ static struct option long_options[] = {
+ {"add", required_argument, NULL, 'a'},
+ {"delete", required_argument, NULL, 'd'},
++ {"help", no_argument, NULL, 'h'},
+ {"remove-password", no_argument, NULL, 'r'},
+ {"restrict", no_argument, NULL, 'R'},
+ {"administrators", required_argument, NULL, 'A'},
+@@ -242,7 +244,7 @@
+ {NULL, 0, NULL, '\0'}
+ };
+
+- while ((flag = getopt_long (argc, argv, "a:A:d:gM:rR", long_options, &option_index)) != -1) {
++ while ((flag = getopt_long (argc, argv, "a:A:d:ghM:rR", long_options, &option_index)) != -1) {
+ switch (flag) {
+ case 'a': /* add a user */
+ aflg = true;
+@@ -276,6 +278,8 @@
+ break;
+ case 'g': /* no-op from normal password */
+ break;
++ case 'h':
++ usage (E_SUCCESS);
+ case 'M': /* set the list of members */
+ members = optarg;
+ if (!is_valid_user_list (members)) {
+@@ -290,7 +294,7 @@
+ Rflg = true;
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+@@ -325,14 +329,14 @@
+ exclusive++;
+ }
+ if (exclusive > 1) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ /*
+ * Make sure one (and only one) group was provided
+ */
+ if ((argc != (opt_index+1)) || (NULL == group)) {
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+Index: src/newusers.c
+===================================================================
+--- src/newusers.c (revision 3054)
++++ src/newusers.c (revision 3055)
+@@ -92,7 +92,7 @@
+ static bool spw_locked = false;
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static void fail_exit (int);
+ static int add_group (const char *, const char *, gid_t *, gid_t);
+ static int get_user_id (const char *, uid_t *);
+@@ -110,15 +110,16 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options]\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+ #ifndef USE_PAM
+- (void) fprintf (stderr,
++ (void) fprintf (usageout,
+ _(" -c, --crypt-method the crypt method (one of %s)\n"),
+ #ifndef USE_SHA_CRYPT
+ "NONE DES MD5"
+@@ -127,18 +128,18 @@
+ #endif /* USE_SHA_CRYPT */
+ );
+ #endif /* !USE_PAM */
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
+- (void) fputs (_(" -r, --system create system accounts\n"), stderr);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
++ (void) fputs (_(" -r, --system create system accounts\n"), usageout);
+ #ifndef USE_PAM
+ #ifdef USE_SHA_CRYPT
+ (void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
+ " crypt algorithms\n"),
+- stderr);
++ usageout);
+ #endif /* USE_SHA_CRYPT */
+ #endif /* !USE_PAM */
+- (void) fputs ("\n", stderr);
++ (void) fputs ("\n", usageout);
+
+- exit (EXIT_FAILURE);
++ exit (status);
+ }
+
+ /*
+@@ -548,7 +549,7 @@
+ long_options, &option_index)) != -1) {
+ switch (c) {
+ case 'h':
+- usage ();
++ usage (EXIT_SUCCESS);
+ break;
+ case 'r':
+ rflg = true;
+@@ -565,13 +566,13 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (EXIT_FAILURE);
+ }
+ break;
+ #endif /* USE_SHA_CRYPT */
+ #endif /* !USE_PAM */
+ default:
+- usage ();
++ usage (EXIT_FAILURE);
+ break;
+ }
+ }
+@@ -602,7 +603,7 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-s", "-c");
+- usage ();
++ usage (EXIT_FAILURE);
+ }
+ #endif /* USE_SHA_CRYPT */
+
+@@ -618,7 +619,7 @@
+ fprintf (stderr,
+ _("%s: unsupported crypt method: %s\n"),
+ Prog, crypt_method);
+- usage ();
++ usage (EXIT_FAILURE);
+ }
+ }
+ #endif /* !USE_PAM */
+Index: src/chpasswd.c
+===================================================================
+--- src/chpasswd.c (revision 3054)
++++ src/chpasswd.c (revision 3055)
+@@ -74,7 +74,7 @@
+
+ /* local function prototypes */
+ static void fail_exit (int code);
+-static void usage (void);
++static void usage (int status);
+ static void process_flags (int argc, char **argv);
+ static void check_flags (void);
+ static void check_perms (void);
+@@ -112,15 +112,16 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options]\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+ #ifndef USE_PAM
+- (void) fprintf (stderr,
++ (void) fprintf (usageout,
+ _(" -c, --crypt-method the crypt method (one of %s)\n"),
+ #ifndef USE_SHA_CRYPT
+ "NONE DES MD5"
+@@ -128,22 +129,22 @@
+ "NONE DES MD5 SHA256 SHA512"
+ #endif /* USE_SHA_CRYPT */
+ );
+- (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), stderr);
++ (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
+ #endif /* !USE_PAM */
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
+ #ifndef USE_PAM
+ (void) fputs (_(" -m, --md5 encrypt the clear text password using\n"
+ " the MD5 algorithm\n"),
+- stderr);
++ usageout);
+ #ifdef USE_SHA_CRYPT
+ (void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
+ " crypt algorithms\n"),
+- stderr);
++ usageout);
+ #endif /* USE_SHA_CRYPT */
+ #endif /* !USE_PAM */
+- (void) fputs ("\n", stderr);
++ (void) fputs ("\n", usageout);
+
+- exit (E_USAGE);
++ exit (status);
+ }
+
+ /*
+@@ -181,7 +182,7 @@
+ long_options, &option_index)) != -1) {
+ switch (c) {
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ #ifndef USE_PAM
+ case 'c':
+@@ -201,13 +202,13 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ #endif /* USE_SHA_CRYPT */
+ #endif /* !USE_PAM */
+ default:
+- usage ();
++ usage (E_USAGE);
+ break;
+ }
+ }
+@@ -229,7 +230,7 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-s", "-c");
+- usage ();
++ usage (E_USAGE);
+ }
+ #endif
+
+@@ -238,7 +239,7 @@
+ fprintf (stderr,
+ _("%s: the -c, -e, and -m flags are exclusive\n"),
+ Prog);
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (cflg) {
+@@ -253,7 +254,7 @@
+ fprintf (stderr,
+ _("%s: unsupported crypt method: %s\n"),
+ Prog, crypt_method);
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+ #endif /* USE_PAM */
+Index: src/groupmems.c
+===================================================================
+--- src/groupmems.c (revision 3054)
++++ src/groupmems.c (revision 3055)
+@@ -88,7 +88,7 @@
+ const struct group *grp);
+ static void purge_members (const struct group *grp);
+ static void display_members (const char *const *members);
+-static void usage (void);
++static void usage (int status);
+ static void process_flags (int argc, char **argv);
+ static void check_perms (void);
+ static void fail_exit (int code);
+@@ -361,7 +361,7 @@
+ }
+ }
+
+-static void usage (void)
++static void usage (int status)
+ {
+ (void) fputs (_("Usage: groupmems [options] [action]\n"
+ "\n"
+@@ -372,10 +372,11 @@
+ "Actions:\n"
+ " -a, --add username add username to the members of the group\n"
+ " -d, --delete username remove username from the members of the group\n"
++ " -h, --help display this help message and exit\n"
+ " -p, --purge purge all members from the group\n"
+ " -l, --list list the members of the group\n"
+- "\n"), stderr);
+- fail_exit (EXIT_USAGE);
++ "\n"), status ? stderr : stdout);
++ fail_exit (status);
+ }
+
+ /*
+@@ -389,12 +390,13 @@
+ {"add", required_argument, NULL, 'a'},
+ {"delete", required_argument, NULL, 'd'},
+ {"group", required_argument, NULL, 'g'},
++ {"help", no_argument, NULL, 'h'},
+ {"list", no_argument, NULL, 'l'},
+ {"purge", no_argument, NULL, 'p'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+- while ((arg = getopt_long (argc, argv, "a:d:g:lp", long_options,
++ while ((arg = getopt_long (argc, argv, "a:d:g:hlp", long_options,
+ &option_index)) != EOF) {
+ switch (arg) {
+ case 'a':
+@@ -408,6 +410,8 @@
+ case 'g':
+ thisgroup = xstrdup (optarg);
+ break;
++ case 'h':
++ usage (EXIT_SUCCESS);
+ case 'l':
+ list = true;
+ ++exclusive;
+@@ -417,12 +421,12 @@
+ ++exclusive;
+ break;
+ default:
+- usage ();
++ usage (EXIT_USAGE);
+ }
+ }
+
+ if ((exclusive > 1) || (optind < argc)) {
+- usage ();
++ usage (EXIT_USAGE);
+ }
+
+ /* local, no need for xgetpwnam */
+Index: src/usermod.c
+===================================================================
+--- src/usermod.c (revision 3054)
++++ src/usermod.c (revision 3055)
+@@ -149,7 +149,7 @@
+ static void date_to_str (char *buf, size_t maxsize,
+ long int date, const char *negativ);
+ static int get_groups (char *);
+-static void usage (void);
++static void usage (int status);
+ static void new_pwent (struct passwd *);
+ #ifdef WITH_SELINUX
+ static void selinux_update_mapping (void);
+@@ -300,9 +300,9 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- fprintf (stderr,
++ fprintf (status ? stderr : stdout,
+ _("Usage: usermod [options] LOGIN\n"
+ "\n"
+ "Options:\n"
+@@ -334,7 +334,7 @@
+ ""
+ #endif
+ );
+- exit (E_USAGE);
++ exit (status);
+ }
+
+ /*
+@@ -815,7 +815,7 @@
+ bool anyflag = false;
+
+ if ((1 == argc) || ('-' == argv[argc - 1][0])) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ {
+@@ -955,7 +955,7 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ fflg = true;
+ break;
+@@ -976,6 +976,8 @@
+ }
+ Gflg = true;
+ break;
++ case 'h':
++ usage (E_SUCCESS);
+ case 'l':
+ if (!is_valid_user_name (optarg)) {
+ fprintf (stderr,
+@@ -1036,7 +1038,7 @@
+ break;
+ #endif
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ anyflag = true;
+ }
+@@ -1092,14 +1094,14 @@
+ }
+
+ if (optind != argc - 1) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (aflg && (!Gflg)) {
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-a", "-G");
+- usage ();
++ usage (E_USAGE);
+ exit (E_USAGE);
+ }
+
+@@ -1107,7 +1109,7 @@
+ fprintf (stderr,
+ _("%s: the -L, -p, and -U flags are exclusive\n"),
+ Prog);
+- usage ();
++ usage (E_USAGE);
+ exit (E_USAGE);
+ }
+
+@@ -1115,7 +1117,7 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-o", "-u");
+- usage ();
++ usage (E_USAGE);
+ exit (E_USAGE);
+ }
+
+@@ -1123,7 +1125,7 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-m", "-d");
+- usage ();
++ usage (E_USAGE);
+ exit (E_USAGE);
+ }
+
+Index: src/chgpasswd.c
+===================================================================
+--- src/chgpasswd.c (revision 3054)
++++ src/chgpasswd.c (revision 3055)
+@@ -78,7 +78,7 @@
+
+ /* local function prototypes */
+ static void fail_exit (int code);
+-static void usage (void);
++static void usage (int status);
+ static void process_flags (int argc, char **argv);
+ static void check_flags (void);
+ static void check_perms (void);
+@@ -114,9 +114,10 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- fprintf (stderr, _("Usage: %s [options]\n"
++ fprintf (status ? stderr : stdout,
++ _("Usage: %s [options]\n"
+ "\n"
+ "Options:\n"
+ " -c, --crypt-method the crypt method (one of %s)\n"
+@@ -135,7 +136,7 @@
+ " crypt algorithms\n")
+ #endif
+ );
+- exit (E_USAGE);
++ exit (status);
+ }
+
+ /*
+@@ -174,7 +175,7 @@
+ eflg = true;
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'm':
+ md5flg = true;
+@@ -186,12 +187,12 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ #endif
+ default:
+- usage ();
++ usage (E_USAGE);
+ break;
+ }
+ }
+@@ -212,7 +213,7 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-s", "-c");
+- usage ();
++ usage (E_USAGE);
+ }
+ #endif
+
+@@ -221,7 +222,7 @@
+ fprintf (stderr,
+ _("%s: the -c, -e, and -m flags are exclusive\n"),
+ Prog);
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (cflg) {
+@@ -236,7 +237,7 @@
+ fprintf (stderr,
+ _("%s: unsupported crypt method: %s\n"),
+ Prog, crypt_method);
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+ }
+Index: src/vipw.c
+===================================================================
+--- src/vipw.c (revision 3054)
++++ src/vipw.c (revision 3055)
+@@ -1,7 +1,7 @@
+ /*
+ vipw, vigr edit the password or group file
+ with -s will edit shadow or gshadow file
+-
++
+ Copyright (c) 1997 , Guy Maor <maor@ece.utexas.edu>
+ Copyright (c) 1999 - 2000, Marek Michałkiewicz
+ Copyright (c) 2002 - 2006, Tomasz Kłoczko
+@@ -29,8 +29,8 @@
+
+ #include <errno.h>
+ #include <getopt.h>
+-#ifdef WITH_SELINUX
+-#include <selinux/selinux.h>
++#ifdef WITH_SELINUX
++#include <selinux/selinux.h>
+ #endif
+ #include <signal.h>
+ #include <stdio.h>
+@@ -64,7 +64,7 @@
+ static bool quiet = false;
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static int create_backup_file (FILE *, const char *, struct stat *);
+ static void vipwexit (const char *msg, int syserr, int ret);
+ static void vipwedit (const char *, int (*)(void), int (*)(void));
+@@ -72,9 +72,9 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- (void)
++ (void)
+ fputs (_("Usage: vipw [options]\n"
+ "\n"
+ "Options:\n"
+@@ -83,8 +83,8 @@
+ " -p, --passwd edit passwd database\n"
+ " -q, --quiet quiet mode\n"
+ " -s, --shadow edit shadow or gshadow database\n"
+- "\n"), stderr);
+- exit (E_USAGE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ /*
+@@ -285,8 +285,8 @@
+ if (st1.st_mtime == st2.st_mtime) {
+ vipwexit (0, 0, 0);
+ }
+-#ifdef WITH_SELINUX
+- /* unset the fscreatecon */
++#ifdef WITH_SELINUX
++ /* unset the fscreatecon */
+ if (is_selinux_enabled ()) {
+ if (setfscreatecon (NULL)) {
+ vipwexit (_("setfscreatecon () failed"), errno, 1);
+@@ -353,7 +353,7 @@
+ do_vipw = false;
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'p':
+ do_vipw = true;
+@@ -365,7 +365,7 @@
+ editshadow = true;
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+ }
+Index: src/useradd.c
+===================================================================
+--- src/useradd.c (revision 3054)
++++ src/useradd.c (revision 3055)
+@@ -179,7 +179,7 @@
+ static void show_defaults (void);
+ static int set_defaults (void);
+ static int get_groups (char *);
+-static void usage (void);
++static void usage (int status);
+ static void new_pwent (struct passwd *);
+ #ifdef WITH_SELINUX
+ static void selinux_update_mapping (void);
+@@ -681,45 +681,46 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options] LOGIN\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+ (void) fputs (_(" -b, --base-dir BASE_DIR base directory for the home directory of the\n"
+- " new account\n"), stderr);
+- (void) fputs (_(" -c, --comment COMMENT GECOS field of the new account\n"), stderr);
+- (void) fputs (_(" -d, --home-dir HOME_DIR home directory of the new account\n"), stderr);
+- (void) fputs (_(" -D, --defaults print or change default useradd configuration\n"), stderr);
+- (void) fputs (_(" -e, --expiredate EXPIRE_DATE expiration date of the new account\n"), stderr);
+- (void) fputs (_(" -f, --inactive INACTIVE password inactivity period of the new account\n"), stderr);
++ " new account\n"), usageout);
++ (void) fputs (_(" -c, --comment COMMENT GECOS field of the new account\n"), usageout);
++ (void) fputs (_(" -d, --home-dir HOME_DIR home directory of the new account\n"), usageout);
++ (void) fputs (_(" -D, --defaults print or change default useradd configuration\n"), usageout);
++ (void) fputs (_(" -e, --expiredate EXPIRE_DATE expiration date of the new account\n"), usageout);
++ (void) fputs (_(" -f, --inactive INACTIVE password inactivity period of the new account\n"), usageout);
+ (void) fputs (_(" -g, --gid GROUP name or ID of the primary group of the new\n"
+- " account\n"), stderr);
++ " account\n"), usageout);
+ (void) fputs (_(" -G, --groups GROUPS list of supplementary groups of the new\n"
+- " account\n"), stderr);
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
+- (void) fputs (_(" -k, --skel SKEL_DIR use this alternative skeleton directory\n"), stderr);
+- (void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), stderr);
++ " account\n"), usageout);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
++ (void) fputs (_(" -k, --skel SKEL_DIR use this alternative skeleton directory\n"), usageout);
++ (void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), usageout);
+ (void) fputs (_(" -l, --no-log-init do not add the user to the lastlog and\n"
+- " faillog databases\n"), stderr);
+- (void) fputs (_(" -m, --create-home create the user's home directory\n"), stderr);
+- (void) fputs (_(" -M, --no-create-home do not create the user's home directory\n"), stderr);
++ " faillog databases\n"), usageout);
++ (void) fputs (_(" -m, --create-home create the user's home directory\n"), usageout);
++ (void) fputs (_(" -M, --no-create-home do not create the user's home directory\n"), usageout);
+ (void) fputs (_(" -N, --no-user-group do not create a group with the same name as\n"
+- " the user\n"), stderr);
++ " the user\n"), usageout);
+ (void) fputs (_(" -o, --non-unique allow to create users with duplicate\n"
+- " (non-unique) UID\n"), stderr);
+- (void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), stderr);
+- (void) fputs (_(" -r, --system create a system account\n"), stderr);
+- (void) fputs (_(" -s, --shell SHELL login shell of the new account\n"), stderr);
+- (void) fputs (_(" -u, --uid UID user ID of the new account\n"), stderr);
+- (void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), stderr);
++ " (non-unique) UID\n"), usageout);
++ (void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), usageout);
++ (void) fputs (_(" -r, --system create a system account\n"), usageout);
++ (void) fputs (_(" -s, --shell SHELL login shell of the new account\n"), usageout);
++ (void) fputs (_(" -u, --uid UID user ID of the new account\n"), usageout);
++ (void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), usageout);
+ #ifdef WITH_SELINUX
+- (void) fputs (_(" -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping\n"), stderr);
++ (void) fputs (_(" -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping\n"), usageout);
+ #endif
+- (void) fputs ("\n", stderr);
+- exit (E_USAGE);
++ (void) fputs ("\n", usageout);
++ exit (status);
+ }
+
+ /*
+@@ -989,9 +990,9 @@
+ };
+ while ((c = getopt_long (argc, argv,
+ #ifdef WITH_SELINUX
+- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
++ "b:c:d:De:f:g:G:hk:K:lmMNop:rs:u:UZ:",
+ #else
+- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
++ "b:c:d:De:f:g:G:hk:K:lmMNop:rs:u:U",
+ #endif
+ long_options, NULL)) != -1) {
+ switch (c) {
+@@ -1029,7 +1030,7 @@
+ break;
+ case 'D':
+ if (anyflag) {
+- usage ();
++ usage (E_USAGE);
+ }
+ Dflg = true;
+ break;
+@@ -1066,7 +1067,7 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ /*
+ * -f -1 is allowed
+@@ -1106,7 +1107,7 @@
+ Gflg = true;
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'k':
+ def_template = optarg;
+@@ -1201,7 +1202,7 @@
+ break;
+ #endif
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ anyflag = true;
+ }
+@@ -1220,31 +1221,31 @@
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-o", "-u");
+- usage ();
++ usage (E_USAGE);
+ }
+ if (kflg && !mflg) {
+ fprintf (stderr,
+ _("%s: %s flag is only allowed with the %s flag\n"),
+ Prog, "-k", "-m");
+- usage ();
++ usage (E_USAGE);
+ }
+ if (Uflg && gflg) {
+ fprintf (stderr,
+ _("%s: options %s and %s conflict\n"),
+ Prog, "-U", "-g");
+- usage ();
++ usage (E_USAGE);
+ }
+ if (Uflg && Nflg) {
+ fprintf (stderr,
+ _("%s: options %s and %s conflict\n"),
+ Prog, "-U", "-N");
+- usage ();
++ usage (E_USAGE);
+ }
+ if (mflg && Mflg) {
+ fprintf (stderr,
+ _("%s: options %s and %s conflict\n"),
+ Prog, "-m", "-M");
+- usage ();
++ usage (E_USAGE);
+ }
+
+ /*
+@@ -1253,15 +1254,15 @@
+ */
+ if (Dflg) {
+ if (optind != argc) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (uflg || oflg || Gflg || dflg || cflg || mflg) {
+- usage ();
++ usage (E_USAGE);
+ }
+ } else {
+ if (optind != argc - 1) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ user_name = argv[optind];
+Index: src/su.c
+===================================================================
+--- src/su.c (revision 3054)
++++ src/su.c (revision 3055)
+@@ -323,7 +323,7 @@
+ /*
+ * usage - print command line syntax and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+ fputs (_("Usage: su [options] [LOGIN]\n"
+ "\n"
+@@ -335,8 +335,8 @@
+ " --preserve-environment do not reset environment variables, and\n"
+ " keep the same shell\n"
+ " -s, --shell SHELL use SHELL instead of the default in passwd\n"
+- "\n"), stderr);
+- exit (E_USAGE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ /*
+@@ -421,7 +421,7 @@
+ command = optarg;
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'l':
+ fakelogin = true;
+@@ -438,7 +438,7 @@
+ shellstr = optarg;
+ break;
+ default:
+- usage (); /* NOT REACHED */
++ usage (E_USAGE); /* NOT REACHED */
+ }
+ }
+
+Index: src/groupmod.c
+===================================================================
+--- src/groupmod.c (revision 3054)
++++ src/groupmod.c (revision 3055)
+@@ -93,7 +93,7 @@
+ pflg = false; /* new encrypted password */
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static void new_grent (struct group *);
+
+ #ifdef SHADOWGRP
+@@ -113,21 +113,22 @@
+ * usage - display usage message and exit
+ */
+
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options] GROUP\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+- (void) fputs (_(" -g, --gid GID change the group ID to GID\n"), stderr);
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
+- (void) fputs (_(" -n, --new-name NEW_GROUP change the name to NEW_GROUP\n"), stderr);
+- (void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), stderr);
++ (void) fputs (_(" -g, --gid GID change the group ID to GID\n"), usageout);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
++ (void) fputs (_(" -n, --new-name NEW_GROUP change the name to NEW_GROUP\n"), usageout);
++ (void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), usageout);
+ (void) fputs (_(" -p, --password PASSWORD change the password to this (encrypted)\n"
+- " PASSWORD\n"), stderr);
+- (void) fputs ("\n", stderr);
+- exit (E_USAGE);
++ " PASSWORD\n"), usageout);
++ (void) fputs ("\n", usageout);
++ exit (status);
+ }
+
+ /*
+@@ -362,6 +363,8 @@
+ exit (E_BAD_ARG);
+ }
+ break;
++ case 'h':
++ usage (E_SUCCESS);
+ case 'n':
+ nflg = true;
+ group_newname = optarg;
+@@ -374,16 +377,16 @@
+ pflg = true;
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+ if (oflg && !gflg) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (optind != (argc - 1)) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ group_name = argv[argc - 1];
+Index: src/passwd.c
+===================================================================
+--- src/passwd.c (revision 3054)
++++ src/passwd.c (revision 3055)
+@@ -180,7 +180,7 @@
+ " -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"
+ " -x, --maxdays MAX_DAYS set maximum number of days before password\n"
+ " change to MAX_DAYS\n"
+- "\n"), stderr);
++ "\n"), status ? stderr : stdout);
+ exit (status);
+ }
+
+@@ -811,7 +811,7 @@
+ {NULL, 0, NULL, '\0'}
+ };
+
+- while ((c = getopt_long (argc, argv, "adei:kln:qr:Suw:x:",
++ while ((c = getopt_long (argc, argv, "adehi:kln:qr:Suw:x:",
+ long_options, &option_index)) != -1) {
+ switch (c) {
+ case 'a':
+@@ -897,6 +897,8 @@
+ xflg = true;
+ anyflag = true;
+ break;
++ case 'h':
++ usage (E_SUCCESS);
+ default:
+ usage (E_BAD_ARG);
+ }
+Index: src/groupadd.c
+===================================================================
+--- src/groupadd.c (revision 3054)
++++ src/groupadd.c (revision 3055)
+@@ -88,7 +88,7 @@
+ #endif
+
+ /* local function prototypes */
+-static void usage (void);
++static void usage (int status);
+ static void new_grent (struct group *grent);
+
+ #ifdef SHADOWGRP
+@@ -105,24 +105,25 @@
+ /*
+ * usage - display usage message and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options] GROUP\n"
+ "\n"
+ "Options:\n"),
+ Prog);
+ (void) fputs (_(" -f, --force exit successfully if the group already exists,\n"
+- " and cancel -g if the GID is already used\n"), stderr);
+- (void) fputs (_(" -g, --gid GID use GID for the new group\n"), stderr);
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
+- (void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), stderr);
++ " and cancel -g if the GID is already used\n"), usageout);
++ (void) fputs (_(" -g, --gid GID use GID for the new group\n"), usageout);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
++ (void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), usageout);
+ (void) fputs (_(" -o, --non-unique allow to create groups with duplicate\n"
+- " (non-unique) GID\n"), stderr);
+- (void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), stderr);
+- (void) fputs (_(" -r, --system create a system account\n"), stderr);
+- (void) fputs ("\n", stderr);
+- exit (E_USAGE);
++ " (non-unique) GID\n"), usageout);
++ (void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), usageout);
++ (void) fputs (_(" -r, --system create a system account\n"), usageout);
++ (void) fputs ("\n", usageout);
++ exit (status);
+ }
+
+ /*
+@@ -412,7 +413,7 @@
+ }
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'K':
+ /*
+@@ -444,7 +445,7 @@
+ rflg = true;
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+@@ -452,7 +453,7 @@
+ * Check the flags consistency
+ */
+ if (optind != argc - 1) {
+- usage ();
++ usage (E_USAGE);
+ }
+ group_name = argv[optind];
+
+@@ -468,7 +469,7 @@
+ {
+ /* -o does not make sense without -g */
+ if (oflg && !gflg) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ check_new_name ();
+Index: src/chage.c
+===================================================================
+--- src/chage.c (revision 3054)
++++ src/chage.c (revision 3055)
+@@ -91,7 +91,7 @@
+
+ /* local function prototypes */
+ static bool isnum (const char *s);
+-static void usage (void);
++static void usage (int status);
+ static void date_to_str (char *buf, size_t maxsize, time_t date);
+ static int new_fields (void);
+ static void print_date (time_t date);
+@@ -152,7 +152,7 @@
+ /*
+ * usage - print command line syntax and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+ fputs (_("Usage: chage [options] [LOGIN]\n"
+ "\n"
+@@ -168,8 +168,8 @@
+ " -M, --maxdays MAX_DAYS set maximim number of days before password\n"
+ " change to MAX_DAYS\n"
+ " -W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"
+- "\n"), stderr);
+- exit (E_USAGE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ static void date_to_str (char *buf, size_t maxsize, time_t date)
+@@ -413,7 +413,7 @@
+ fprintf (stderr,
+ _("%s: invalid date '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ case 'E':
+@@ -425,11 +425,11 @@
+ fprintf (stderr,
+ _("%s: invalid date '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'I':
+ Iflg = true;
+@@ -438,7 +438,7 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ case 'l':
+@@ -451,7 +451,7 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ case 'M':
+@@ -461,7 +461,7 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ case 'W':
+@@ -471,11 +471,11 @@
+ fprintf (stderr,
+ _("%s: invalid numeric argument '%s'\n"),
+ Prog, optarg);
+- usage ();
++ usage (E_USAGE);
+ }
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+@@ -495,14 +495,14 @@
+ */
+
+ if (argc != opt_index + 1) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ if (lflg && (mflg || Mflg || dflg || Wflg || Iflg || Eflg)) {
+ fprintf (stderr,
+ _("%s: do not include \"l\" with other flags\n"),
+ Prog);
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+Index: src/faillog.c
+===================================================================
+--- src/faillog.c (revision 3054)
++++ src/faillog.c (revision 3055)
+@@ -47,6 +47,17 @@
+ /*@-exitarg@*/
+ #include "exitcodes.h"
+
++/* local function prototypes */
++static void usage (int status);
++static void print_one (/*@null@*/const struct passwd *pw, bool force);
++static void set_locktime (long locktime);
++static bool set_locktime_one (uid_t uid, long locktime);
++static void setmax (int max);
++static bool setmax_one (uid_t uid, int max);
++static void print (void);
++static bool reset_one (uid_t uid);
++static void reset (void);
++
+ /*
+ * Global variables
+ */
+@@ -69,24 +80,25 @@
+
+ #define NOW (time((time_t *) 0))
+
+-static void usage (void)
++static void usage (int status)
+ {
+- (void) fprintf (stderr,
++ FILE *usageout = status ? stderr : stdout;
++ (void) fprintf (usageout,
+ _("Usage: %s [options]\n"
+ "\n"
+ "Options:\n"),
+ "faillog");
+- (void) fputs (_(" -a, --all display faillog records for all users\n"), stderr);
+- (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
+- (void) fputs (_(" -l, --lock-time SEC after failed login lock account for SEC seconds\n"), stderr);
+- (void) fputs (_(" -m, --maximum MAX set maximum failed login counters to MAX\n"), stderr);
+- (void) fputs (_(" -r, --reset reset the counters of login failures\n"), stderr);
+- (void) fputs (_(" -t, --time DAYS display faillog records more recent than DAYS\n"), stderr);
++ (void) fputs (_(" -a, --all display faillog records for all users\n"), usageout);
++ (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
++ (void) fputs (_(" -l, --lock-time SEC after failed login lock account for SEC seconds\n"), usageout);
++ (void) fputs (_(" -m, --maximum MAX set maximum failed login counters to MAX\n"), usageout);
++ (void) fputs (_(" -r, --reset reset the counters of login failures\n"), usageout);
++ (void) fputs (_(" -t, --time DAYS display faillog records more recent than DAYS\n"), usageout);
+ (void) fputs (_(" -u, --user LOGIN/RANGE display faillog record or maintains failure\n"
+ " counters and limits (if used with -r, -m,\n"
+- " or -l) only for the specified LOGIN(s)\n"), stderr);
+- (void) fputs ("\n", stderr);
+- exit (E_USAGE);
++ " or -l) only for the specified LOGIN(s)\n"), usageout);
++ (void) fputs ("\n", usageout);
++ exit (status);
+ }
+
+ static void print_one (/*@null@*/const struct passwd *pw, bool force)
+@@ -495,7 +507,7 @@
+ aflg = true;
+ break;
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 'l':
+ if (getlong (optarg, &fail_locktime) == 0) {
+@@ -561,16 +573,16 @@
+ break;
+ }
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+ }
+
+ if (aflg && uflg) {
+- usage ();
++ usage (E_USAGE);
+ }
+ if (tflg && (lflg || mflg || rflg)) {
+- usage ();
++ usage (E_USAGE);
+ }
+
+ /* Open the faillog database */
+Index: src/chsh.c
+===================================================================
+--- src/chsh.c (revision 3054)
++++ src/chsh.c (revision 3055)
+@@ -72,7 +72,7 @@
+
+ /* local function prototypes */
+ static void fail_exit (int code);
+-static void usage (void);
++static void usage (int status);
+ static void new_fields (void);
+ static bool shell_is_listed (const char *);
+ static bool is_restricted_shell (const char *);
+@@ -101,15 +101,15 @@
+ /*
+ * usage - print command line syntax and exit
+ */
+-static void usage (void)
++static void usage (int status)
+ {
+ fputs (_("Usage: chsh [options] [LOGIN]\n"
+ "\n"
+ "Options:\n"
+ " -h, --help display this help message and exit\n"
+ " -s, --shell SHELL new login shell for the user account\n"
+- "\n"), stderr);
+- exit (E_USAGE);
++ "\n"), status ? stderr : stdout);
++ exit (status);
+ }
+
+ /*
+@@ -217,14 +217,14 @@
+ &option_index)) != -1) {
+ switch (c) {
+ case 'h':
+- usage ();
++ usage (E_SUCCESS);
+ break;
+ case 's':
+ sflg = true;
+ STRFCPY (loginsh, optarg);
+ break;
+ default:
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+@@ -233,7 +233,7 @@
+ * be the user's name.
+ */
+ if (argc > (optind + 1)) {
+- usage ();
++ usage (E_USAGE);
+ }
+ }
+
+Index: man/groupmems.8.xml
+===================================================================
+--- man/groupmems.8.xml (revision 3054)
++++ man/groupmems.8.xml (revision 3055)
+@@ -114,6 +114,12 @@
+ </listitem>
+ </varlistentry>
+ <varlistentry>
++ <term><option>-h</option>, <option>--help</option></term>
++ <listitem>
++ <para>Display help message and exit.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
+ <term><option>-l</option>, <option>--list</option></term>
+ <listitem>
+ <para>List the group membership list.</para>
+Index: man/gpasswd.1.xml
+===================================================================
+--- man/gpasswd.1.xml (revision 3054)
++++ man/gpasswd.1.xml (revision 3055)
+@@ -1,7 +1,7 @@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ Copyright (c) 1996 , Rafal Maszkowski
+- Copyright (c) 2007 - 2008, Nicolas François
++ Copyright (c) 2007 - 2009, Nicolas François
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+@@ -148,6 +148,14 @@
+ </variablelist>
+ <variablelist remap='IP'>
+ <varlistentry>
++ <term><option>-h</option>, <option>--help</option></term>
++ <listitem>
++ <para>Display help message and exit.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ <variablelist remap='IP'>
++ <varlistentry>
+ <term>
+ <option>-r</option>, <option>--remove-password</option>
+ </term>
+Index: NEWS
+===================================================================
+--- NEWS (revision 3054)
++++ NEWS (revision 3055)
+@@ -1,5 +1,11 @@
+ $Id$
+
++shadow-4.1.4.1 -> shadow-4.1.4.2 UNRELEASED
++
++- general
++ * report usage error to stderr, but report usage help to stdout (and return
++ zero) when explicitly requested (e.g. with --help).
++
+ shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
+
+ - general
diff --git a/source/a/shadow/patches/r3060.diff b/source/a/shadow/patches/r3060.diff
new file mode 100644
index 00000000..8ece6430
--- /dev/null
+++ b/source/a/shadow/patches/r3060.diff
@@ -0,0 +1,116 @@
+* libmisc/copydir.c, lib/shadowmem.c, lib/groupmem.c, lib/pwmem.c:
+Fix some memory leaks.
+
+Index: libmisc/copydir.c
+===================================================================
+--- libmisc/copydir.c (revision 3059)
++++ libmisc/copydir.c (revision 3060)
+@@ -443,6 +443,7 @@
+ nchars = readlink (filename, buffer, size);
+
+ if (nchars < 0) {
++ free(buffer);
+ return NULL;
+ }
+
+
+Index: lib/shadowmem.c
+===================================================================
+--- lib/shadowmem.c (revision 3059)
++++ lib/shadowmem.c (revision 3060)
+@@ -52,10 +52,13 @@
+ *sp = *spent;
+ sp->sp_namp = strdup (spent->sp_namp);
+ if (NULL == sp->sp_namp) {
++ free(sp);
+ return NULL;
+ }
+ sp->sp_pwdp = strdup (spent->sp_pwdp);
+ if (NULL == sp->sp_pwdp) {
++ free(sp->sp_namp);
++ free(sp);
+ return NULL;
+ }
+
+Index: lib/groupmem.c
+===================================================================
+--- lib/groupmem.c (revision 3059)
++++ lib/groupmem.c (revision 3060)
+@@ -51,10 +51,13 @@
+ *gr = *grent;
+ gr->gr_name = strdup (grent->gr_name);
+ if (NULL == gr->gr_name) {
++ free(gr);
+ return NULL;
+ }
+ gr->gr_passwd = strdup (grent->gr_passwd);
+ if (NULL == gr->gr_passwd) {
++ free(gr->gr_name);
++ free(gr);
+ return NULL;
+ }
+
+@@ -62,11 +65,21 @@
+
+ gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
+ if (NULL == gr->gr_mem) {
++ free(gr->gr_passwd);
++ free(gr->gr_name);
++ free(gr);
+ return NULL;
+ }
+ for (i = 0; grent->gr_mem[i]; i++) {
+ gr->gr_mem[i] = strdup (grent->gr_mem[i]);
+ if (NULL == gr->gr_mem[i]) {
++ int j;
++ for (j=0; j<i; j++)
++ free(gr->gr_mem[j]);
++ free(gr->gr_mem);
++ free(gr->gr_passwd);
++ free(gr->gr_name);
++ free(gr);
+ return NULL;
+ }
+ }
+Index: lib/pwmem.c
+===================================================================
+--- lib/pwmem.c (revision 3059)
++++ lib/pwmem.c (revision 3060)
+@@ -51,22 +51,37 @@
+ *pw = *pwent;
+ pw->pw_name = strdup (pwent->pw_name);
+ if (NULL == pw->pw_name) {
++ free(pw);
+ return NULL;
+ }
+ pw->pw_passwd = strdup (pwent->pw_passwd);
+ if (NULL == pw->pw_passwd) {
++ free(pw->pw_name);
++ free(pw);
+ return NULL;
+ }
+ pw->pw_gecos = strdup (pwent->pw_gecos);
+ if (NULL == pw->pw_gecos) {
++ free(pw->pw_passwd);
++ free(pw->pw_name);
++ free(pw);
+ return NULL;
+ }
+ pw->pw_dir = strdup (pwent->pw_dir);
+ if (NULL == pw->pw_dir) {
++ free(pw->pw_gecos);
++ free(pw->pw_passwd);
++ free(pw->pw_name);
++ free(pw);
+ return NULL;
+ }
+ pw->pw_shell = strdup (pwent->pw_shell);
+ if (NULL == pw->pw_shell) {
++ free(pw->pw_dir);
++ free(pw->pw_gecos);
++ free(pw->pw_passwd);
++ free(pw->pw_name);
++ free(pw);
+ return NULL;
+ }
+
diff --git a/source/a/shadow/patches/r3062.diff b/source/a/shadow/patches/r3062.diff
new file mode 100644
index 00000000..00d9ba3a
--- /dev/null
+++ b/source/a/shadow/patches/r3062.diff
@@ -0,0 +1,139 @@
+Index: lib/shadowmem.c
+===================================================================
+--- lib/shadowmem.c (revision 3061)
++++ lib/shadowmem.c (revision 3062)
+@@ -49,8 +49,14 @@
+ if (NULL == sp) {
+ return NULL;
+ }
+- *sp = *spent;
+- sp->sp_namp = strdup (spent->sp_namp);
++ sp->sp_lstchg = spent->sp_lstchg;
++ sp->sp_min = spent->sp_min;
++ sp->sp_max = spent->sp_max;
++ sp->sp_warn = spent->sp_warn;
++ sp->sp_inact = spent->sp_inact;
++ sp->sp_expire = spent->sp_expire;
++ sp->sp_flag = spent->sp_flag;
++ sp->sp_namp = strdup (spent->sp_namp);
+ if (NULL == sp->sp_namp) {
+ free(sp);
+ return NULL;
+@@ -68,8 +74,10 @@
+ void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
+ {
+ free (spent->sp_namp);
+- memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
+- free (spent->sp_pwdp);
++ if (NULL != spent->sp_pwdp) {
++ memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
++ free (spent->sp_pwdp);
++ }
+ free (spent);
+ }
+
+Index: lib/groupmem.c
+===================================================================
+--- lib/groupmem.c (revision 3061)
++++ lib/groupmem.c (revision 3062)
+@@ -48,7 +48,7 @@
+ if (NULL == gr) {
+ return NULL;
+ }
+- *gr = *grent;
++ gr->gr_gid = grent->gr_gid;
+ gr->gr_name = strdup (grent->gr_name);
+ if (NULL == gr->gr_name) {
+ free(gr);
+@@ -90,13 +90,18 @@
+
+ void gr_free (/*@out@*/ /*@only@*/struct group *grent)
+ {
++ size_t i;
+ free (grent->gr_name);
+- memzero (grent->gr_passwd, strlen (grent->gr_passwd));
+- free (grent->gr_passwd);
+- while (*(grent->gr_mem)) {
+- free (*(grent->gr_mem));
+- grent->gr_mem++;
++ if (NULL != grent->gr_passwd) {
++ memzero (grent->gr_passwd, strlen (grent->gr_passwd));
++ free (grent->gr_passwd);
+ }
++ if (NULL != grent->gr_mem) {
++ for (i = 0; NULL != grent->gr_mem[i]; i++) {
++ free (grent->gr_mem[i]);
++ }
++ free (grent->gr_mem);
++ }
+ free (grent);
+ }
+
+Index: lib/sgroupio.c
+===================================================================
+--- lib/sgroupio.c (revision 3061)
++++ lib/sgroupio.c (revision 3062)
+@@ -51,7 +51,6 @@
+ if (NULL == sg) {
+ return NULL;
+ }
+- *sg = *sgent;
+ sg->sg_name = strdup (sgent->sg_name);
+ if (NULL == sg->sg_name) {
+ free (sg);
+@@ -137,17 +136,20 @@
+
+ void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent)
+ {
++ size_t i;
+ free (sgent->sg_name);
+- memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
+- free (sgent->sg_passwd);
+- while (NULL != *(sgent->sg_adm)) {
+- free (*(sgent->sg_adm));
+- sgent->sg_adm++;
++ if (NULL != sgent->sg_passwd) {
++ memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
++ free (sgent->sg_passwd);
+ }
+- while (NULL != *(sgent->sg_mem)) {
+- free (*(sgent->sg_mem));
+- sgent->sg_mem++;
++ for (i = 0; NULL != sgent->sg_adm[i]; i++) {
++ free (sgent->sg_adm[i]);
+ }
++ free (sgent->sg_adm);
++ for (i = 0; NULL != sgent->sg_mem[i]; i++) {
++ free (sgent->sg_mem[i]);
++ }
++ free (sgent->sg_mem);
+ free (sgent);
+ }
+
+Index: lib/pwmem.c
+===================================================================
+--- lib/pwmem.c (revision 3061)
++++ lib/pwmem.c (revision 3062)
+@@ -48,7 +48,8 @@
+ if (NULL == pw) {
+ return NULL;
+ }
+- *pw = *pwent;
++ pw->pw_uid = pwent->pw_uid;
++ pw->pw_gid = pwent->pw_gid;
+ pw->pw_name = strdup (pwent->pw_name);
+ if (NULL == pw->pw_name) {
+ free(pw);
+@@ -91,8 +92,10 @@
+ void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
+ {
+ free (pwent->pw_name);
+- memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
+- free (pwent->pw_passwd);
++ if (pwent->pw_passwd) {
++ memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
++ free (pwent->pw_passwd);
++ }
+ free (pwent->pw_gecos);
+ free (pwent->pw_dir);
+ free (pwent->pw_shell);
diff --git a/source/a/shadow/patches/r3096.diff b/source/a/shadow/patches/r3096.diff
new file mode 100644
index 00000000..0e77ce6f
--- /dev/null
+++ b/source/a/shadow/patches/r3096.diff
@@ -0,0 +1,27 @@
+
+* lib/gshadow.c: Fix parsing of gshadow entries.
+
+Index: lib/gshadow.c
+===================================================================
+--- lib/gshadow.c (revision 3095)
++++ lib/gshadow.c (revision 3096)
+@@ -222,6 +222,7 @@
+ if (NULL == buf) {
+ return NULL;
+ }
++ buflen = BUFSIZ;
+ }
+
+ if (NULL == fp) {
+@@ -229,9 +230,9 @@
+ }
+
+ #ifdef USE_NIS
+- while (fgetsx (buf, (int) sizeof buf, fp) == buf)
++ while (fgetsx (buf, (int) buflen, fp) == buf)
+ #else
+- if (fgetsx (buf, (int) sizeof buf, fp) == buf)
++ if (fgetsx (buf, (int) buflen, fp) == buf)
+ #endif
+ {
+ while ( ((cp = strrchr (buf, '\n')) == NULL)
diff --git a/source/a/shadow/patches/r3160.diff b/source/a/shadow/patches/r3160.diff
new file mode 100644
index 00000000..5aabbaa9
--- /dev/null
+++ b/source/a/shadow/patches/r3160.diff
@@ -0,0 +1,239 @@
+Index: libmisc/limits.c
+===================================================================
+--- libmisc/limits.c (revision 3159)
++++ libmisc/limits.c (revision 3160)
+@@ -33,6 +33,7 @@
+ /*
+ * Separated from setup.c. --marekm
+ * Resource limits thanks to Cristian Gafton.
++ * Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org> ("thor").
+ */
+
+ #include <config.h>
+@@ -44,6 +45,7 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdio.h>
++#include <ctype.h>
+ #include "prototypes.h"
+ #include "defines.h"
+ #include <pwd.h>
+@@ -69,17 +71,37 @@
+ unsigned int multiplier)
+ {
+ struct rlimit rlim;
+- long limit;
++ rlim_t limit;
+
+- if (getlong (value, &limit) == 0) {
+- return 0;
++ /* The "-" is special, not belonging to a strange negative limit.
++ It is infinity, in a controlled way. --thor */
++ if(value[0] == '-') {
++ limit = RLIM_INFINITY;
+ }
+- limit *= multiplier;
+- if (limit != (rlim_t) limit) {
+- return 0;
++ else {
++ /* We cannot use getlong here because it fails when there
++ is more to the value than just this number!
++ Also, we are limited to base 10 here (hex numbers will not
++ work with the limit string parser as is anyway) --thor */
++ char *endptr;
++ long longlimit = strtol(value, &endptr, 10);
++ if ((0 == longlimit) && (value == endptr)) {
++ /* No argument at all. No-op.
++ We could instead throw an error, though. --thor */
++ return 0;
++ }
++ longlimit *= multiplier;
++ limit = (rlim_t)longlimit;
++ if(longlimit != limit)
++ {
++ /* Again, silent error handling... I left it that way.
++ Wouldn't screaming make more sense? --thor */
++ return 0;
++ }
+ }
+- rlim.rlim_cur = (rlim_t) limit;
+- rlim.rlim_max = (rlim_t) limit;
++
++ rlim.rlim_cur = limit;
++ rlim.rlim_max = limit;
+ if (setrlimit (resource, &rlim) != 0) {
+ return LOGIN_ERROR_RLIMIT;
+ }
+@@ -199,6 +221,9 @@
+ * [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
+ * [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
+ *
++ * Remember to extend the "no-limits" string below when adding a new limit...
++ * --thor
++ *
+ * Return value:
+ * 0 = okay, of course
+ * LOGIN_ERROR_RLIMIT = error setting some RLIMIT
+@@ -214,7 +239,20 @@
+ bool reported = false;
+
+ pp = buf;
++ /* Skip leading whitespace. --thor */
++ while(*pp == ' ' || *pp == '\t') ++pp;
+
++ /* The special limit string "-" results in no limit for all known limits.
++ We achieve that by parsing a full limit string, parts of it being ignored
++ if a limit type is not known to the system.
++ Though, there will be complaining for unknown limit types. --thor */
++ if(strcmp(pp, "-") == 0) {
++ /* Remember to extend this, too, when adding new limits!
++ Oh... but "unlimited" does not make sense for umask, or does it?
++ --thor */
++ pp = "A- C- D- F- M- N- R- S- T- P- I- O-";
++ }
++
+ while ('\0' != *pp) {
+ switch (*pp++) {
+ #ifdef RLIMIT_AS
+@@ -316,6 +354,10 @@
+ break;
+ default:
+ /* Only report invalid strings once */
++ /* Note: A string can be invalid just because a specific (theoretically
++ valid) setting is not supported by this build.
++ It is just a warning in syslog anyway. The line is still processed
++ --thor */
+ if (!reported) {
+ SYSLOG ((LOG_WARN,
+ "Invalid limit string: '%s'",
+@@ -324,13 +366,51 @@
+ retval |= LOGIN_ERROR_RLIMIT;
+ }
+ }
++ /* After parsing one limit setting (or just complaining about it),
++ one still needs to skip its argument to prevent a bogus warning on
++ trying to parse that as limit specification.
++ So, let's skip all digits, "-" and our limited set of whitespace.
++ --thor */
++ while(isdigit(*pp) || *pp == '-' || *pp == ' ' || *pp == '\t') {
++ ++pp;
++ }
+ }
+ return retval;
+ }
+
++/* Check if user uname is in the group gname.
++ * Can I be sure that gr_mem contains no UID as string?
++ * Returns true when user is in the group, false when not.
++ * Any error is treated as false. --thor
++ */
++static bool user_in_group (const char *uname, const char *gname)
++{
++ struct group *groupdata;
++ char **member;
++ if(uname == NULL || gname == NULL){
++ return false;
++ }
++ /* We are not claiming to be re-entrant!
++ * In case of paranoia or a multithreaded login program,
++ * one needs to add some mess for getgrnam_r. */
++ groupdata = getgrnam(gname);
++ if(groupdata == NULL) {
++ SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.", gname));
++ return false;
++ }
++ /* Now look for our user in the list of members. */
++ member = groupdata->gr_mem;
++ while(*member != NULL) {
++ if(strcmp(*member, uname) == 0) {
++ return true;
++ }
++ ++member;
++ }
++ return false;
++}
++
+ static int setup_user_limits (const char *uname)
+ {
+- /* TODO: allow and use @group syntax --cristiang */
+ FILE *fil;
+ char buf[1024];
+ char name[1024];
+@@ -352,7 +432,7 @@
+ }
+ /* The limits file have the following format:
+ * - '#' (comment) chars only as first chars on a line;
+- * - username must start on first column
++ * - username must start on first column (or *, or @group --thor)
+ * A better (smarter) checking should be done --cristiang */
+ while (fgets (buf, 1024, fil) != NULL) {
+ if (('#' == buf[0]) || ('\n' == buf[0])) {
+@@ -367,6 +447,13 @@
+ * Imposing a limit should be done with care, so a wrong
+ * entry means no care anyway :-). A '-' as a limits
+ * strings means no limits --cristiang */
++ /* In addition to the handling of * as name which was alrady present,
++ I added handling of the @group syntax.
++ To clarify: The first entry with matching user name rules,
++ everything after it is ignored. If there is no user entry,
++ the last encountered entry for a matching group rules.
++ If there is no matching group entry, the default limits rule.
++ --thor. */
+ if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
+ name, tempbuf) == 2) {
+ if (strcmp (name, uname) == 0) {
+@@ -374,6 +461,12 @@
+ break;
+ } else if (strcmp (name, "*") == 0) {
+ strcpy (deflimits, tempbuf);
++ } else if (name[0] == '@') {
++ /* If the user is in the group, the group limits apply unless
++ later a line for the specific user is found. --thor */
++ if(user_in_group(uname, name+1)) {
++ strcpy (limits, tempbuf);
++ }
+ }
+ }
+ }
+Index: man/limits.5.xml
+===================================================================
+--- man/limits.5.xml (revision 3159)
++++ man/limits.5.xml (revision 3160)
+@@ -64,7 +64,13 @@
+ <emphasis remap='I'>user LIMITS_STRING</emphasis>
+ </para>
+
++ <para>or in the form:</para>
++
+ <para>
++ <emphasis remap='I'>@group LIMITS_STRING</emphasis>
++ </para>
++
++ <para>
+ The <emphasis>LIMITS_STRING</emphasis> is a string of a concatenated
+ list of resource limits. Each limit consists of a letter identifier
+ followed by a numerical limit.
+@@ -125,11 +131,23 @@
+ </para>
+
+ <para>
++ The limits specified in the form "<replaceable>@group</replaceable>"
++ apply to the members of the specified
++ <replaceable>group</replaceable>.
++ </para>
++
++ <para>
+ To completely disable limits for a user, a single dash
+ "<emphasis>-</emphasis>" will do.
+ </para>
+
+ <para>
++ To disable a limit for a user, a single dash
++ "<replaceable>-</replaceable>" can be used instead of the numerical
++ value for this limit.
++ </para>
++
++ <para>
+ Also, please note that all limit settings are set PER LOGIN. They are
+ not global, nor are they permanent. Perhaps global limits will come,
+ but for now this will have to do ;)
diff --git a/source/a/shadow/patches/r3194.diff b/source/a/shadow/patches/r3194.diff
new file mode 100644
index 00000000..0eff631b
--- /dev/null
+++ b/source/a/shadow/patches/r3194.diff
@@ -0,0 +1,15 @@
+* src/su.c: shell's name must be -su when a su fakes a login.
+
+===================================================================
+--- src/su.c (revision 3193)
++++ src/su.c (revision 3194)
+@@ -1021,7 +1021,7 @@
+ * Use the shell and create an argv
+ * with the rest of the command line included.
+ */
+- argv[-1] = shellstr;
++ argv[-1] = cp;
+ #ifndef USE_PAM
+ execve_shell (shellstr, &argv[-1], environ);
+ err = errno;
+
diff --git a/source/a/shadow/patches/r3299.diff b/source/a/shadow/patches/r3299.diff
new file mode 100644
index 00000000..a46b18f0
--- /dev/null
+++ b/source/a/shadow/patches/r3299.diff
@@ -0,0 +1,12 @@
+Index: man/ru/Makefile.am
+===================================================================
+--- man/ru/Makefile.am (revision 3298)
++++ man/ru/Makefile.am (revision 3299)
+@@ -1,7 +1,6 @@
+ mandir = @mandir@/ru
+
+ man_MANS = \
+- $(man_nopam) \
+ chage.1 \
+ chfn.1 \
+ chgpasswd.8 \