summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/shadow/files/add_root_cmd_options.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-extended/shadow/files/add_root_cmd_options.patch')
-rw-r--r--meta/recipes-extended/shadow/files/add_root_cmd_options.patch1384
1 files changed, 0 insertions, 1384 deletions
diff --git a/meta/recipes-extended/shadow/files/add_root_cmd_options.patch b/meta/recipes-extended/shadow/files/add_root_cmd_options.patch
deleted file mode 100644
index ab87e35535..0000000000
--- a/meta/recipes-extended/shadow/files/add_root_cmd_options.patch
+++ /dev/null
@@ -1,1384 +0,0 @@
1Add a --root command option to the following utilties:
2
3* useradd
4* groupadd
5* usermod
6* groupmod
7* userdel
8* groupdel
9* passwd
10* gpasswd
11* pwconv
12* pwunconv
13* grpconv
14* grpunconv
15
16This option allows the utilities to be chrooted when run under pseudo.
17They can then be used to manipulate user and group account information
18in target sysroots.
19
20The useradd utility was also modified to create home directories
21recursively when necessary.
22
23Upstream-Status: Inappropriate [Other]
24Workaround is specific to our build system.
25
26Signed-off-by: Scott Garman <scott.a.garman@intel.com>
27
282011-09-29 Fix the parsing of the --root option in gpasswd, useradd, usermod:
29
30In programs which need to scan the command line in two passes to handle
31--root option separately from the rest of the arguments, replace the first
32calls to getopt_long with a simple iteration over the argument list since
33getopt_long has the bad habit of reordering arguments on the command line.
34
35Signed-off-by: Julian Pidancet <julian.pidancet@gmail.com>
36
37diff -urN shadow-4.1.4.3.orig//src/gpasswd.c shadow-4.1.4.3//src/gpasswd.c
38--- shadow-4.1.4.3.orig//src/gpasswd.c 2011-09-29 12:00:45.211000091 +0100
39+++ shadow-4.1.4.3//src/gpasswd.c 2011-09-29 12:09:54.590000090 +0100
40@@ -63,6 +63,7 @@
41 * (/etc/gshadow present) */
42 static bool is_shadowgrp;
43 #endif
44+static const char *newroot = "";
45
46 /* Flags set by options */
47 static bool aflg = false;
48@@ -97,6 +98,7 @@
49 static void usage (void);
50 static RETSIGTYPE catch_signals (int killed);
51 static bool is_valid_user_list (const char *users);
52+static void process_root_flag (int argc, char **argv);
53 static void process_flags (int argc, char **argv);
54 static void check_flags (int argc, int opt_index);
55 static void open_files (void);
56@@ -136,6 +138,7 @@
57 "Options:\n"
58 " -a, --add USER add USER to GROUP\n"
59 " -d, --delete USER remove USER from GROUP\n"
60+ " -Q --root CHROOT_DIR directory to chroot into\n"
61 " -r, --remove-password remove the GROUP's password\n"
62 " -R, --restrict restrict access to GROUP to its members\n"
63 " -M, --members USER,... set the list of members of GROUP\n"
64@@ -226,6 +229,57 @@
65 }
66
67 /*
68+ * process_root_flag - chroot if given the --root option
69+ *
70+ * We do this outside of process_flags() because
71+ * the is_shadow_pwd boolean needs to be set before
72+ * process_flags(), and if we do need to chroot() we
73+ * must do so before is_shadow_pwd gets set.
74+ */
75+static void process_root_flag (int argc, char **argv)
76+{
77+ /*
78+ * Parse the command line options.
79+ */
80+ int i;
81+ char *root;
82+
83+ for (i = 0; i < argc; i++) {
84+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-Q")) {
85+ if (i + 1 == argc) {
86+ fprintf (stderr,
87+ _("%s: option '%s' requires an argument\n"),
88+ Prog, argv[i]);
89+ exit (E_BAD_ARG);
90+ }
91+ root = argv[i + 1];
92+
93+ if ('/' != root[0]) {
94+ fprintf (stderr,
95+ _("%s: invalid chroot path '%s'\n"),
96+ Prog, root);
97+ exit (E_BAD_ARG);
98+ }
99+ newroot = root;
100+
101+ if (access (newroot, F_OK) != 0) {
102+ fprintf(stderr,
103+ _("%s: chroot directory %s does not exist\n"),
104+ Prog, newroot);
105+ exit (E_BAD_ARG);
106+ }
107+ if ( chroot(newroot) != 0 ) {
108+ fprintf(stderr,
109+ _("%s: unable to chroot to directory %s\n"),
110+ Prog, newroot);
111+ exit (E_BAD_ARG);
112+ }
113+ break;
114+ }
115+ }
116+}
117+
118+/*
119 * process_flags - process the command line options and arguments
120 */
121 static void process_flags (int argc, char **argv)
122@@ -235,6 +289,7 @@
123 static struct option long_options[] = {
124 {"add", required_argument, NULL, 'a'},
125 {"delete", required_argument, NULL, 'd'},
126+ {"root", required_argument, NULL, 'Q'},
127 {"remove-password", no_argument, NULL, 'r'},
128 {"restrict", no_argument, NULL, 'R'},
129 {"administrators", required_argument, NULL, 'A'},
130@@ -242,7 +297,7 @@
131 {NULL, 0, NULL, '\0'}
132 };
133
134- while ((flag = getopt_long (argc, argv, "a:A:d:gM:rR", long_options, &option_index)) != -1) {
135+ while ((flag = getopt_long (argc, argv, "a:A:d:gM:Q:rR", long_options, &option_index)) != -1) {
136 switch (flag) {
137 case 'a': /* add a user */
138 aflg = true;
139@@ -283,6 +338,9 @@
140 }
141 Mflg = true;
142 break;
143+ case 'Q':
144+ /* no-op since we handled this in process_root_flag() earlier */
145+ break;
146 case 'r': /* remove group password */
147 rflg = true;
148 break;
149@@ -995,6 +1053,8 @@
150 setbuf (stdout, NULL);
151 setbuf (stderr, NULL);
152
153+ process_root_flag (argc, argv);
154+
155 #ifdef SHADOWGRP
156 is_shadowgrp = sgr_file_present ();
157 #endif
158diff -urN shadow-4.1.4.3.orig//src/groupadd.c shadow-4.1.4.3//src/groupadd.c
159--- shadow-4.1.4.3.orig//src/groupadd.c 2011-09-29 12:00:45.212000091 +0100
160+++ shadow-4.1.4.3//src/groupadd.c 2011-09-29 11:59:28.386000092 +0100
161@@ -76,6 +76,7 @@
162 static gid_t group_id;
163 static /*@null@*/char *group_passwd;
164 static /*@null@*/char *empty_list = NULL;
165+static const char *newroot = "";
166
167 static bool oflg = false; /* permit non-unique group ID to be specified with -g */
168 static bool gflg = false; /* ID value for the new group */
169@@ -120,6 +121,7 @@
170 (void) fputs (_(" -o, --non-unique allow to create groups with duplicate\n"
171 " (non-unique) GID\n"), stderr);
172 (void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), stderr);
173+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
174 (void) fputs (_(" -r, --system create a system account\n"), stderr);
175 (void) fputs ("\n", stderr);
176 exit (E_USAGE);
177@@ -383,12 +385,13 @@
178 {"key", required_argument, NULL, 'K'},
179 {"non-unique", no_argument, NULL, 'o'},
180 {"password", required_argument, NULL, 'p'},
181+ {"root", required_argument, NULL, 'R'},
182 {"system", no_argument, NULL, 'r'},
183 {NULL, 0, NULL, '\0'}
184 };
185
186 while ((c =
187- getopt_long (argc, argv, "fg:hK:op:r", long_options,
188+ getopt_long (argc, argv, "fg:hK:op:R:r", long_options,
189 &option_index)) != -1) {
190 switch (c) {
191 case 'f':
192@@ -440,6 +443,28 @@
193 pflg = true;
194 group_passwd = optarg;
195 break;
196+ case 'R':
197+ if ('/' != optarg[0]) {
198+ fprintf (stderr,
199+ _("%s: invalid chroot path '%s'\n"),
200+ Prog, optarg);
201+ exit (E_BAD_ARG);
202+ }
203+ newroot = optarg;
204+
205+ if (access (newroot, F_OK) != 0) {
206+ fprintf(stderr,
207+ _("%s: chroot directory %s does not exist\n"),
208+ Prog, newroot);
209+ exit (E_BAD_ARG);
210+ }
211+ if ( chroot(newroot) != 0 ) {
212+ fprintf(stderr,
213+ _("%s: unable to chroot to directory %s\n"),
214+ Prog, newroot);
215+ exit (E_BAD_ARG);
216+ }
217+ break;
218 case 'r':
219 rflg = true;
220 break;
221diff -urN shadow-4.1.4.3.orig//src/groupdel.c shadow-4.1.4.3//src/groupdel.c
222--- shadow-4.1.4.3.orig//src/groupdel.c 2011-09-29 12:00:45.212000091 +0100
223+++ shadow-4.1.4.3//src/groupdel.c 2011-09-29 11:59:28.386000092 +0100
224@@ -36,6 +36,7 @@
225
226 #include <ctype.h>
227 #include <fcntl.h>
228+#include <getopt.h>
229 #include <grp.h>
230 #include <pwd.h>
231 #ifdef ACCT_TOOLS_SETUID
232@@ -59,6 +60,7 @@
233
234 static char *group_name;
235 static gid_t group_id = -1;
236+static const char *newroot = "";
237
238 #ifdef SHADOWGRP
239 static bool is_shadow_grp;
240@@ -70,12 +72,14 @@
241 /*@-exitarg@*/
242 #define E_SUCCESS 0 /* success */
243 #define E_USAGE 2 /* invalid command syntax */
244+#define E_BAD_ARG 3 /* invalid argument to option */
245 #define E_NOTFOUND 6 /* specified group doesn't exist */
246 #define E_GROUP_BUSY 8 /* can't remove user's primary group */
247 #define E_GRP_UPDATE 10 /* can't update group file */
248
249 /* local function prototypes */
250 static void usage (void);
251+static void process_flags (int argc, char **argv);
252 static void grp_update (void);
253 static void close_files (void);
254 static void open_files (void);
255@@ -86,11 +90,78 @@
256 */
257 static void usage (void)
258 {
259- fputs (_("Usage: groupdel group\n"), stderr);
260+ (void) fprintf (stderr,
261+ _("Usage: groupdel [options]\n"
262+ "\n"
263+ "Options:\n"),
264+ Prog);
265+ (void) fputs (_(" -g, --group GROUP group name to delete\n"), stderr);
266+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
267+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
268+ (void) fputs ("\n", stderr);
269 exit (E_USAGE);
270 }
271
272 /*
273+ * process_flags - perform command line argument setting
274+ *
275+ * process_flags() interprets the command line arguments and sets
276+ * the values that the user will be created with accordingly. The
277+ * values are checked for sanity.
278+ */
279+static void process_flags (int argc, char **argv)
280+{
281+ {
282+ /*
283+ * Parse the command line options.
284+ */
285+ int c;
286+ static struct option long_options[] = {
287+ {"group", required_argument, NULL, 'g'},
288+ {"help", no_argument, NULL, 'h'},
289+ {"root", required_argument, NULL, 'R'},
290+ {NULL, 0, NULL, '\0'}
291+ };
292+ while ((c = getopt_long (argc, argv,
293+ "g:R:",
294+ long_options, NULL)) != -1) {
295+ switch (c) {
296+ case 'g':
297+ group_name = optarg;
298+ break;
299+ case 'h':
300+ usage ();
301+ break;
302+ case 'R':
303+ if ('/' != optarg[0]) {
304+ fprintf (stderr,
305+ _("%s: invalid chroot path '%s'\n"),
306+ Prog, optarg);
307+ exit (E_BAD_ARG);
308+ }
309+ newroot = optarg;
310+
311+ if (access (newroot, F_OK) != 0) {
312+ fprintf(stderr,
313+ _("%s: chroot directory %s does not exist\n"),
314+ Prog, newroot);
315+ exit (E_BAD_ARG);
316+ }
317+ if ( chroot(newroot) != 0 ) {
318+ fprintf(stderr,
319+ _("%s: unable to chroot to directory %s\n"),
320+ Prog, newroot);
321+ exit (E_BAD_ARG);
322+ }
323+ break;
324+ default:
325+ usage ();
326+ }
327+ }
328+ }
329+}
330+
331+/*
332 * grp_update - update group file entries
333 *
334 * grp_update() writes the new records to the group files.
335@@ -328,14 +399,14 @@
336 (void) bindtextdomain (PACKAGE, LOCALEDIR);
337 (void) textdomain (PACKAGE);
338
339- if (argc != 2) {
340+ if (argc == 1) {
341 usage ();
342 }
343
344- group_name = argv[1];
345-
346 OPENLOG ("groupdel");
347
348+ process_flags (argc, argv);
349+
350 #ifdef ACCT_TOOLS_SETUID
351 #ifdef USE_PAM
352 {
353diff -urN shadow-4.1.4.3.orig//src/groupmod.c shadow-4.1.4.3//src/groupmod.c
354--- shadow-4.1.4.3.orig//src/groupmod.c 2011-09-29 12:00:45.212000091 +0100
355+++ shadow-4.1.4.3//src/groupmod.c 2011-09-29 11:59:28.387000092 +0100
356@@ -79,6 +79,7 @@
357 static char *group_passwd;
358 static gid_t group_id;
359 static gid_t group_newid;
360+static char *newroot = "";
361
362 struct cleanup_info_mod info_passwd;
363 struct cleanup_info_mod info_group;
364@@ -126,6 +127,7 @@
365 (void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), stderr);
366 (void) fputs (_(" -p, --password PASSWORD change the password to this (encrypted)\n"
367 " PASSWORD\n"), stderr);
368+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
369 (void) fputs ("\n", stderr);
370 exit (E_USAGE);
371 }
372@@ -346,10 +348,11 @@
373 {"new-name", required_argument, NULL, 'n'},
374 {"non-unique", no_argument, NULL, 'o'},
375 {"password", required_argument, NULL, 'p'},
376+ {"root", required_argument, NULL, 'R'},
377 {NULL, 0, NULL, '\0'}
378 };
379 while ((c =
380- getopt_long (argc, argv, "g:hn:op:",
381+ getopt_long (argc, argv, "g:hn:op:R:",
382 long_options, &option_index)) != -1) {
383 switch (c) {
384 case 'g':
385@@ -373,6 +376,28 @@
386 group_passwd = optarg;
387 pflg = true;
388 break;
389+ case 'R':
390+ if ('/' != optarg[0]) {
391+ fprintf (stderr,
392+ _("%s: invalid chroot path '%s'\n"),
393+ Prog, optarg);
394+ exit (E_BAD_ARG);
395+ }
396+ newroot = optarg;
397+
398+ if (access (newroot, F_OK) != 0) {
399+ fprintf(stderr,
400+ _("%s: chroot directory %s does not exist\n"),
401+ Prog, newroot);
402+ exit (E_BAD_ARG);
403+ }
404+ if ( chroot(newroot) != 0 ) {
405+ fprintf(stderr,
406+ _("%s: unable to chroot to directory %s\n"),
407+ Prog, newroot);
408+ exit (E_BAD_ARG);
409+ }
410+ break;
411 default:
412 usage ();
413 }
414diff -urN shadow-4.1.4.3.orig//src/grpconv.c shadow-4.1.4.3//src/grpconv.c
415--- shadow-4.1.4.3.orig//src/grpconv.c 2011-09-29 12:00:45.213000091 +0100
416+++ shadow-4.1.4.3//src/grpconv.c 2011-09-29 11:59:28.387000092 +0100
417@@ -39,6 +39,7 @@
418
419 #include <errno.h>
420 #include <fcntl.h>
421+#include <getopt.h>
422 #include <grp.h>
423 #include <stdio.h>
424 #include <stdlib.h>
425@@ -50,6 +51,14 @@
426 #ifdef SHADOWGRP
427 #include "groupio.h"
428 #include "sgroupio.h"
429+
430+/*
431+ * exit status values
432+ */
433+/*@-exitarg@*/
434+#define E_USAGE 2 /* invalid command syntax */
435+#define E_BAD_ARG 3 /* invalid argument to option */
436+
437 /*
438 * Global variables
439 */
440@@ -57,9 +66,12 @@
441
442 static bool gr_locked = false;
443 static bool sgr_locked = false;
444+static const char *newroot = "";
445
446 /* local function prototypes */
447 static void fail_exit (int status);
448+static void usage (void);
449+static void process_flags (int argc, char **argv);
450
451 static void fail_exit (int status)
452 {
453@@ -82,6 +94,77 @@
454 exit (status);
455 }
456
457+/*
458+ * usage - display usage message and exit
459+ */
460+static void usage (void)
461+{
462+ (void) fprintf (stderr,
463+ _("Usage: grpconv [options]\n"
464+ "\n"
465+ "Options:\n"),
466+ Prog);
467+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
468+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
469+ (void) fputs ("\n", stderr);
470+ exit (E_USAGE);
471+}
472+
473+/*
474+ * process_flags - perform command line argument setting
475+ *
476+ * process_flags() interprets the command line arguments and sets
477+ * the values that the user will be created with accordingly. The
478+ * values are checked for sanity.
479+ */
480+static void process_flags (int argc, char **argv)
481+{
482+ {
483+ /*
484+ * Parse the command line options.
485+ */
486+ int c;
487+ static struct option long_options[] = {
488+ {"help", no_argument, NULL, 'h'},
489+ {"root", required_argument, NULL, 'R'},
490+ {NULL, 0, NULL, '\0'}
491+ };
492+ while ((c = getopt_long (argc, argv,
493+ "R:",
494+ long_options, NULL)) != -1) {
495+ switch (c) {
496+ case 'h':
497+ usage ();
498+ break;
499+ case 'R':
500+ if ('/' != optarg[0]) {
501+ fprintf (stderr,
502+ _("%s: invalid chroot path '%s'\n"),
503+ Prog, optarg);
504+ exit (E_BAD_ARG);
505+ }
506+ newroot = optarg;
507+
508+ if (access (newroot, F_OK) != 0) {
509+ fprintf(stderr,
510+ _("%s: chroot directory %s does not exist\n"),
511+ Prog, newroot);
512+ exit (E_BAD_ARG);
513+ }
514+ if ( chroot(newroot) != 0 ) {
515+ fprintf(stderr,
516+ _("%s: unable to chroot to directory %s\n"),
517+ Prog, newroot);
518+ exit (E_BAD_ARG);
519+ }
520+ break;
521+ default:
522+ usage ();
523+ }
524+ }
525+ }
526+}
527+
528 int main (int argc, char **argv)
529 {
530 const struct group *gr;
531@@ -89,9 +172,6 @@
532 const struct sgrp *sg;
533 struct sgrp sgent;
534
535- if (1 != argc) {
536- (void) fputs (_("Usage: grpconv\n"), stderr);
537- }
538 Prog = Basename (argv[0]);
539
540 (void) setlocale (LC_ALL, "");
541@@ -100,6 +180,8 @@
542
543 OPENLOG ("grpconv");
544
545+ process_flags (argc, argv);
546+
547 if (gr_lock () == 0) {
548 fprintf (stderr,
549 _("%s: cannot lock %s; try again later.\n"),
550diff -urN shadow-4.1.4.3.orig//src/grpunconv.c shadow-4.1.4.3//src/grpunconv.c
551--- shadow-4.1.4.3.orig//src/grpunconv.c 2011-09-29 12:00:45.213000091 +0100
552+++ shadow-4.1.4.3//src/grpunconv.c 2011-09-29 11:59:28.387000092 +0100
553@@ -43,6 +43,7 @@
554 #include <stdlib.h>
555 #include <string.h>
556 #include <fcntl.h>
557+#include <getopt.h>
558 #include <time.h>
559 #include <unistd.h>
560 #include <grp.h>
561@@ -51,6 +52,14 @@
562 #ifdef SHADOWGRP
563 #include "groupio.h"
564 #include "sgroupio.h"
565+
566+/*
567+ * exit status values
568+ */
569+/*@-exitarg@*/
570+#define E_USAGE 2 /* invalid command syntax */
571+#define E_BAD_ARG 3 /* invalid argument to option */
572+
573 /*
574 * Global variables
575 */
576@@ -58,9 +67,12 @@
577
578 static bool gr_locked = false;
579 static bool sgr_locked = false;
580+static const char *newroot = "";
581
582 /* local function prototypes */
583 static void fail_exit (int status);
584+static void usage (void);
585+static void process_flags (int argc, char **argv);
586
587 static void fail_exit (int status)
588 {
589@@ -83,6 +95,77 @@
590 exit (status);
591 }
592
593+/*
594+ * usage - display usage message and exit
595+ */
596+static void usage (void)
597+{
598+ (void) fprintf (stderr,
599+ _("Usage: grpunconv [options]\n"
600+ "\n"
601+ "Options:\n"),
602+ Prog);
603+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
604+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
605+ (void) fputs ("\n", stderr);
606+ exit (E_USAGE);
607+}
608+
609+/*
610+ * process_flags - perform command line argument setting
611+ *
612+ * process_flags() interprets the command line arguments and sets
613+ * the values that the user will be created with accordingly. The
614+ * values are checked for sanity.
615+ */
616+static void process_flags (int argc, char **argv)
617+{
618+ {
619+ /*
620+ * Parse the command line options.
621+ */
622+ int c;
623+ static struct option long_options[] = {
624+ {"help", no_argument, NULL, 'h'},
625+ {"root", required_argument, NULL, 'R'},
626+ {NULL, 0, NULL, '\0'}
627+ };
628+ while ((c = getopt_long (argc, argv,
629+ "R:",
630+ long_options, NULL)) != -1) {
631+ switch (c) {
632+ case 'h':
633+ usage ();
634+ break;
635+ case 'R':
636+ if ('/' != optarg[0]) {
637+ fprintf (stderr,
638+ _("%s: invalid chroot path '%s'\n"),
639+ Prog, optarg);
640+ exit (E_BAD_ARG);
641+ }
642+ newroot = optarg;
643+
644+ if (access (newroot, F_OK) != 0) {
645+ fprintf(stderr,
646+ _("%s: chroot directory %s does not exist\n"),
647+ Prog, newroot);
648+ exit (E_BAD_ARG);
649+ }
650+ if ( chroot(newroot) != 0 ) {
651+ fprintf(stderr,
652+ _("%s: unable to chroot to directory %s\n"),
653+ Prog, newroot);
654+ exit (E_BAD_ARG);
655+ }
656+ break;
657+ default:
658+ usage ();
659+ }
660+ }
661+ }
662+}
663+
664 int main (int argc, char **argv)
665 {
666 const struct group *gr;
667@@ -100,6 +183,8 @@
668
669 OPENLOG ("grpunconv");
670
671+ process_flags (argc, argv);
672+
673 if (sgr_file_present () == 0) {
674 exit (0); /* no /etc/gshadow, nothing to do */
675 }
676diff -urN shadow-4.1.4.3.orig//src/passwd.c shadow-4.1.4.3//src/passwd.c
677--- shadow-4.1.4.3.orig//src/passwd.c 2011-09-29 12:00:45.214000091 +0100
678+++ shadow-4.1.4.3//src/passwd.c 2011-09-29 11:59:28.388000092 +0100
679@@ -75,6 +75,7 @@
680 static char *name; /* The name of user whose password is being changed */
681 static char *myname; /* The current user's name */
682 static bool amroot; /* The caller's real UID was 0 */
683+static const char *newroot = "";
684
685 static bool
686 aflg = false, /* -a - show status for all users */
687@@ -174,6 +175,7 @@
688 " -n, --mindays MIN_DAYS set minimum number of days before password\n"
689 " change to MIN_DAYS\n"
690 " -q, --quiet quiet mode\n"
691+ " -R, --root CHROOT_DIR directory to chroot into\n"
692 " -r, --repository REPOSITORY change password in REPOSITORY repository\n"
693 " -S, --status report password status on the named account\n"
694 " -u, --unlock unlock the password of the named account\n"
695@@ -803,6 +805,7 @@
696 {"lock", no_argument, NULL, 'l'},
697 {"mindays", required_argument, NULL, 'n'},
698 {"quiet", no_argument, NULL, 'q'},
699+ {"root", required_argument, NULL, 'R'},
700 {"repository", required_argument, NULL, 'r'},
701 {"status", no_argument, NULL, 'S'},
702 {"unlock", no_argument, NULL, 'u'},
703@@ -811,7 +814,7 @@
704 {NULL, 0, NULL, '\0'}
705 };
706
707- while ((c = getopt_long (argc, argv, "adei:kln:qr:Suw:x:",
708+ while ((c = getopt_long (argc, argv, "adei:kln:qR:r:Suw:x:",
709 long_options, &option_index)) != -1) {
710 switch (c) {
711 case 'a':
712@@ -858,6 +861,28 @@
713 case 'q':
714 qflg = true; /* ok for users */
715 break;
716+ case 'R':
717+ if ('/' != optarg[0]) {
718+ fprintf (stderr,
719+ _("%s: invalid chroot path '%s'\n"),
720+ Prog, optarg);
721+ exit (E_BAD_ARG);
722+ }
723+ newroot = optarg;
724+
725+ if (access (newroot, F_OK) != 0) {
726+ fprintf(stderr,
727+ _("%s: chroot directory %s does not exist\n"),
728+ Prog, newroot);
729+ exit (E_BAD_ARG);
730+ }
731+ if ( chroot(newroot) != 0 ) {
732+ fprintf(stderr,
733+ _("%s: unable to chroot to directory %s\n"),
734+ Prog, newroot);
735+ exit (E_BAD_ARG);
736+ }
737+ break;
738 case 'r':
739 /* -r repository (files|nis|nisplus) */
740 /* only "files" supported for now */
741diff -urN shadow-4.1.4.3.orig//src/pwconv.c shadow-4.1.4.3//src/pwconv.c
742--- shadow-4.1.4.3.orig//src/pwconv.c 2011-09-29 12:00:45.214000091 +0100
743+++ shadow-4.1.4.3//src/pwconv.c 2011-09-29 11:59:28.388000092 +0100
744@@ -59,6 +59,7 @@
745
746 #include <errno.h>
747 #include <fcntl.h>
748+#include <getopt.h>
749 #include <pwd.h>
750 #include <stdio.h>
751 #include <stdlib.h>
752@@ -79,6 +80,7 @@
753 #define E_SUCCESS 0 /* success */
754 #define E_NOPERM 1 /* permission denied */
755 #define E_USAGE 2 /* invalid command syntax */
756+#define E_BAD_ARG 3 /* invalid argument to option */
757 #define E_FAILURE 3 /* unexpected failure, nothing done */
758 #define E_MISSING 4 /* unexpected failure, passwd file missing */
759 #define E_PWDBUSY 5 /* passwd file(s) busy */
760@@ -90,9 +92,12 @@
761
762 static bool spw_locked = false;
763 static bool pw_locked = false;
764+static const char *newroot = "";
765
766 /* local function prototypes */
767 static void fail_exit (int status);
768+static void usage (void);
769+static void process_flags (int argc, char **argv);
770
771 static void fail_exit (int status)
772 {
773@@ -115,6 +120,77 @@
774 exit (status);
775 }
776
777+/*
778+ * usage - display usage message and exit
779+ */
780+static void usage (void)
781+{
782+ (void) fprintf (stderr,
783+ _("Usage: pwconv [options]\n"
784+ "\n"
785+ "Options:\n"),
786+ Prog);
787+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
788+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
789+ (void) fputs ("\n", stderr);
790+ exit (E_USAGE);
791+}
792+
793+/*
794+ * process_flags - perform command line argument setting
795+ *
796+ * process_flags() interprets the command line arguments and sets
797+ * the values that the user will be created with accordingly. The
798+ * values are checked for sanity.
799+ */
800+static void process_flags (int argc, char **argv)
801+{
802+ {
803+ /*
804+ * Parse the command line options.
805+ */
806+ int c;
807+ static struct option long_options[] = {
808+ {"help", no_argument, NULL, 'h'},
809+ {"root", required_argument, NULL, 'R'},
810+ {NULL, 0, NULL, '\0'}
811+ };
812+ while ((c = getopt_long (argc, argv,
813+ "R:",
814+ long_options, NULL)) != -1) {
815+ switch (c) {
816+ case 'h':
817+ usage ();
818+ break;
819+ case 'R':
820+ if ('/' != optarg[0]) {
821+ fprintf (stderr,
822+ _("%s: invalid chroot path '%s'\n"),
823+ Prog, optarg);
824+ exit (E_BAD_ARG);
825+ }
826+ newroot = optarg;
827+
828+ if (access (newroot, F_OK) != 0) {
829+ fprintf(stderr,
830+ _("%s: chroot directory %s does not exist\n"),
831+ Prog, newroot);
832+ exit (E_BAD_ARG);
833+ }
834+ if ( chroot(newroot) != 0 ) {
835+ fprintf(stderr,
836+ _("%s: unable to chroot to directory %s\n"),
837+ Prog, newroot);
838+ exit (E_BAD_ARG);
839+ }
840+ break;
841+ default:
842+ usage ();
843+ }
844+ }
845+ }
846+}
847+
848 int main (int argc, char **argv)
849 {
850 const struct passwd *pw;
851@@ -122,9 +198,6 @@
852 const struct spwd *sp;
853 struct spwd spent;
854
855- if (1 != argc) {
856- (void) fputs (_("Usage: pwconv\n"), stderr);
857- }
858 Prog = Basename (argv[0]);
859
860 (void) setlocale (LC_ALL, "");
861@@ -133,6 +206,8 @@
862
863 OPENLOG ("pwconv");
864
865+ process_flags (argc, argv);
866+
867 if (pw_lock () == 0) {
868 fprintf (stderr,
869 _("%s: cannot lock %s; try again later.\n"),
870diff -urN shadow-4.1.4.3.orig//src/pwunconv.c shadow-4.1.4.3//src/pwunconv.c
871--- shadow-4.1.4.3.orig//src/pwunconv.c 2011-09-29 12:00:45.214000091 +0100
872+++ shadow-4.1.4.3//src/pwunconv.c 2011-09-29 11:59:28.388000092 +0100
873@@ -35,6 +35,7 @@
874 #ident "$Id: pwunconv.c 2852 2009-04-30 21:44:35Z nekral-guest $"
875
876 #include <fcntl.h>
877+#include <getopt.h>
878 #include <pwd.h>
879 #include <stdio.h>
880 #include <sys/types.h>
881@@ -46,15 +47,24 @@
882 #include "shadowio.h"
883
884 /*
885+ * exit status values
886+ */
887+/*@-exitarg@*/
888+#define E_USAGE 2 /* invalid command syntax */
889+#define E_BAD_ARG 3 /* invalid argument to option */
890+/*
891 * Global variables
892 */
893 char *Prog;
894
895 static bool spw_locked = false;
896 static bool pw_locked = false;
897+static const char *newroot = "";
898
899 /* local function prototypes */
900 static void fail_exit (int status);
901+static void usage (void);
902+static void process_flags (int argc, char **argv);
903
904 static void fail_exit (int status)
905 {
906@@ -75,6 +85,76 @@
907 exit (status);
908 }
909
910+/*
911+ * usage - display usage message and exit
912+ */
913+static void usage (void)
914+{
915+ (void) fprintf (stderr,
916+ _("Usage: pwunconv [options]\n"
917+ "\n"
918+ "Options:\n"),
919+ Prog);
920+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
921+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
922+ (void) fputs ("\n", stderr);
923+ exit (E_USAGE);
924+}
925+
926+/*
927+ * process_flags - perform command line argument setting
928+ *
929+ * process_flags() interprets the command line arguments and sets
930+ * the values that the user will be created with accordingly. The
931+ * values are checked for sanity.
932+ */
933+static void process_flags (int argc, char **argv)
934+{
935+ {
936+ /*
937+ * Parse the command line options.
938+ */
939+ int c;
940+ static struct option long_options[] = {
941+ {"help", no_argument, NULL, 'h'},
942+ {"root", required_argument, NULL, 'R'},
943+ {NULL, 0, NULL, '\0'}
944+ };
945+ while ((c = getopt_long (argc, argv,
946+ "R:",
947+ long_options, NULL)) != -1) {
948+ switch (c) {
949+ case 'h':
950+ usage ();
951+ break;
952+ case 'R':
953+ if ('/' != optarg[0]) {
954+ fprintf (stderr,
955+ _("%s: invalid chroot path '%s'\n"),
956+ Prog, optarg);
957+ exit (E_BAD_ARG);
958+ }
959+ newroot = optarg;
960+
961+ if (access (newroot, F_OK) != 0) {
962+ fprintf(stderr,
963+ _("%s: chroot directory %s does not exist\n"),
964+ Prog, newroot);
965+ exit (E_BAD_ARG);
966+ }
967+ if ( chroot(newroot) != 0 ) {
968+ fprintf(stderr,
969+ _("%s: unable to chroot to directory %s\n"),
970+ Prog, newroot);
971+ exit (E_BAD_ARG);
972+ }
973+ break;
974+ default:
975+ usage ();
976+ }
977+ }
978+ }
979+}
980
981 int main (int argc, char **argv)
982 {
983@@ -93,6 +173,8 @@
984
985 OPENLOG ("pwunconv");
986
987+ process_flags (argc, argv);
988+
989 if (!spw_file_present ()) {
990 /* shadow not installed, do nothing */
991 exit (0);
992diff -urN shadow-4.1.4.3.orig//src/useradd.c shadow-4.1.4.3//src/useradd.c
993--- shadow-4.1.4.3.orig//src/useradd.c 2011-09-29 12:00:45.215000091 +0100
994+++ shadow-4.1.4.3//src/useradd.c 2011-09-29 11:59:28.520000092 +0100
995@@ -112,6 +112,7 @@
996 #ifdef WITH_SELINUX
997 static const char *user_selinux = "";
998 #endif
999+static const char *newroot = "";
1000
1001 static long user_expire = -1;
1002 static bool is_shadow_pwd;
1003@@ -189,6 +190,7 @@
1004 static void new_spent (struct spwd *);
1005 static void grp_update (void);
1006
1007+static void process_root_flag (int argc, char **argv);
1008 static void process_flags (int argc, char **argv);
1009 static void close_files (void);
1010 static void open_files (void);
1011@@ -711,6 +713,7 @@
1012 (void) fputs (_(" -o, --non-unique allow to create users with duplicate\n"
1013 " (non-unique) UID\n"), stderr);
1014 (void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), stderr);
1015+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
1016 (void) fputs (_(" -r, --system create a system account\n"), stderr);
1017 (void) fputs (_(" -s, --shell SHELL login shell of the new account\n"), stderr);
1018 (void) fputs (_(" -u, --uid UID user ID of the new account\n"), stderr);
1019@@ -943,6 +946,57 @@
1020 }
1021
1022 /*
1023+ * process_root_flag - chroot if given the --root option
1024+ *
1025+ * We do this outside of process_flags() because
1026+ * the is_shadow_pwd boolean needs to be set before
1027+ * process_flags(), and if we do need to chroot() we
1028+ * must do so before is_shadow_pwd gets set.
1029+ */
1030+static void process_root_flag (int argc, char **argv)
1031+{
1032+ /*
1033+ * Parse the command line options.
1034+ */
1035+ int i;
1036+ char *root;
1037+
1038+ for (i = 0; i < argc; i++) {
1039+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-R")) {
1040+ if (i + 1 == argc) {
1041+ fprintf (stderr,
1042+ _("%s: option '%s' requires an argument\n"),
1043+ Prog, argv[i]);
1044+ exit (E_BAD_ARG);
1045+ }
1046+ root = argv[i + 1];
1047+
1048+ if ('/' != root[0]) {
1049+ fprintf (stderr,
1050+ _("%s: invalid chroot path '%s'\n"),
1051+ Prog, root);
1052+ exit (E_BAD_ARG);
1053+ }
1054+ newroot = root;
1055+
1056+ if (access (newroot, F_OK) != 0) {
1057+ fprintf(stderr,
1058+ _("%s: chroot directory %s does not exist\n"),
1059+ Prog, newroot);
1060+ exit (E_BAD_ARG);
1061+ }
1062+ if ( chroot(newroot) != 0 ) {
1063+ fprintf(stderr,
1064+ _("%s: unable to chroot to directory %s\n"),
1065+ Prog, newroot);
1066+ exit (E_BAD_ARG);
1067+ }
1068+ break;
1069+ }
1070+ }
1071+}
1072+
1073+/*
1074 * process_flags - perform command line argument setting
1075 *
1076 * process_flags() interprets the command line arguments and sets
1077@@ -978,6 +1032,7 @@
1078 {"no-user-group", no_argument, NULL, 'N'},
1079 {"non-unique", no_argument, NULL, 'o'},
1080 {"password", required_argument, NULL, 'p'},
1081+ {"root", required_argument, NULL, 'R'},
1082 {"system", no_argument, NULL, 'r'},
1083 {"shell", required_argument, NULL, 's'},
1084 #ifdef WITH_SELINUX
1085@@ -989,9 +1044,9 @@
1086 };
1087 while ((c = getopt_long (argc, argv,
1088 #ifdef WITH_SELINUX
1089- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
1090+ "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:UZ:",
1091 #else
1092- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
1093+ "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:U",
1094 #endif
1095 long_options, NULL)) != -1) {
1096 switch (c) {
1097@@ -1156,6 +1211,9 @@
1098 }
1099 user_pass = optarg;
1100 break;
1101+ case 'R':
1102+ /* no-op since we handled this in process_root_flag() earlier */
1103+ break;
1104 case 'r':
1105 rflg = true;
1106 break;
1107@@ -1735,6 +1793,36 @@
1108 }
1109 }
1110 #endif
1111+
1112+/*
1113+ * mkdir_p - create directories, including parent directories when needed
1114+ *
1115+ * similar to mkdir -p
1116+ */
1117+void mkdir_p(const char *path) {
1118+ int len = strlen(path);
1119+ char newdir[len + 1];
1120+ mode_t mode = 0755;
1121+ int i = 0;
1122+
1123+ if (path[i] == '\0') {
1124+ return;
1125+ }
1126+
1127+ /* skip the leading '/' */
1128+ i++;
1129+
1130+ while(path[i] != '\0') {
1131+ if (path[i] == '/') {
1132+ strncpy(newdir, path, i);
1133+ newdir[i] = '\0';
1134+ mkdir(newdir, mode);
1135+ }
1136+ i++;
1137+ }
1138+ mkdir(path, mode);
1139+}
1140+
1141 /*
1142 * create_home - create the user's home directory
1143 *
1144@@ -1748,34 +1836,31 @@
1145 #ifdef WITH_SELINUX
1146 selinux_file_context (user_home);
1147 #endif
1148- /* XXX - create missing parent directories. --marekm */
1149- if (mkdir (user_home, 0) != 0) {
1150- fprintf (stderr,
1151- _("%s: cannot create directory %s\n"),
1152- Prog, user_home);
1153-#ifdef WITH_AUDIT
1154- audit_logger (AUDIT_ADD_USER, Prog,
1155- "adding home directory",
1156- user_name, (unsigned int) user_id,
1157- SHADOW_AUDIT_FAILURE);
1158-#endif
1159- fail_exit (E_HOMEDIR);
1160- }
1161- chown (user_home, user_id, user_gid);
1162- chmod (user_home,
1163- 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
1164- home_added = true;
1165+ mkdir_p(user_home);
1166+ }
1167+ if (access (user_home, F_OK) != 0) {
1168 #ifdef WITH_AUDIT
1169 audit_logger (AUDIT_ADD_USER, Prog,
1170 "adding home directory",
1171 user_name, (unsigned int) user_id,
1172- SHADOW_AUDIT_SUCCESS);
1173+ SHADOW_AUDIT_FAILURE);
1174+#endif
1175+ fail_exit (E_HOMEDIR);
1176+ }
1177+ chown (user_home, user_id, user_gid);
1178+ chmod (user_home,
1179+ 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
1180+ home_added = true;
1181+#ifdef WITH_AUDIT
1182+ audit_logger (AUDIT_ADD_USER, Prog,
1183+ "adding home directory",
1184+ user_name, (unsigned int) user_id,
1185+ SHADOW_AUDIT_SUCCESS);
1186 #endif
1187 #ifdef WITH_SELINUX
1188- /* Reset SELinux to create files with default contexts */
1189- setfscreatecon (NULL);
1190+ /* Reset SELinux to create files with default contexts */
1191+ setfscreatecon (NULL);
1192 #endif
1193- }
1194 }
1195
1196 /*
1197@@ -1861,6 +1946,7 @@
1198 */
1199 user_groups[0] = (char *) 0;
1200
1201+ process_root_flag (argc, argv);
1202
1203 is_shadow_pwd = spw_file_present ();
1204 #ifdef SHADOWGRP
1205diff -urN shadow-4.1.4.3.orig//src/userdel.c shadow-4.1.4.3//src/userdel.c
1206--- shadow-4.1.4.3.orig//src/userdel.c 2011-09-29 12:00:45.216000091 +0100
1207+++ shadow-4.1.4.3//src/userdel.c 2011-09-29 11:59:28.389000092 +0100
1208@@ -79,6 +79,7 @@
1209 static char *user_name;
1210 static uid_t user_id;
1211 static char *user_home;
1212+static const char *newroot = "";
1213
1214 static bool fflg = false;
1215 static bool rflg = false;
1216@@ -119,6 +120,7 @@
1217 " -f, --force force removal of files,\n"
1218 " even if not owned by user\n"
1219 " -h, --help display this help message and exit\n"
1220+ " -R, --root CHROOT_DIR directory to chroot into\n"
1221 " -r, --remove remove home directory and mail spool\n"
1222 "\n"), stderr);
1223 exit (E_USAGE);
1224@@ -768,12 +770,34 @@
1225 {"remove", no_argument, NULL, 'r'},
1226 {NULL, 0, NULL, '\0'}
1227 };
1228- while ((c = getopt_long (argc, argv, "fhr",
1229+ while ((c = getopt_long (argc, argv, "fhR:r",
1230 long_options, NULL)) != -1) {
1231 switch (c) {
1232 case 'f': /* force remove even if not owned by user */
1233 fflg = true;
1234 break;
1235+ case 'R':
1236+ if ('/' != optarg[0]) {
1237+ fprintf (stderr,
1238+ _("%s: invalid chroot path '%s'\n"),
1239+ Prog, optarg);
1240+ exit (E_BAD_ARG);
1241+ }
1242+ newroot = optarg;
1243+
1244+ if (access (newroot, F_OK) != 0) {
1245+ fprintf(stderr,
1246+ _("%s: chroot directory %s does not exist\n"),
1247+ Prog, newroot);
1248+ exit (E_BAD_ARG);
1249+ }
1250+ if ( chroot(newroot) != 0 ) {
1251+ fprintf(stderr,
1252+ _("%s: unable to chroot to directory %s\n"),
1253+ Prog, newroot);
1254+ exit (E_BAD_ARG);
1255+ }
1256+ break;
1257 case 'r': /* remove home dir and mailbox */
1258 rflg = true;
1259 break;
1260diff -urN shadow-4.1.4.3.orig//src/usermod.c shadow-4.1.4.3//src/usermod.c
1261--- shadow-4.1.4.3.orig//src/usermod.c 2011-09-29 12:00:45.216000091 +0100
1262+++ shadow-4.1.4.3//src/usermod.c 2011-09-29 11:59:28.390000092 +0100
1263@@ -110,6 +110,7 @@
1264 static long user_newinactive;
1265 static long sys_ngroups;
1266 static char **user_groups; /* NULL-terminated list */
1267+static const char *newroot = "";
1268
1269 static bool
1270 aflg = false, /* append to existing secondary group set */
1271@@ -164,6 +165,7 @@
1272 #endif
1273 static void grp_update (void);
1274
1275+static void process_root_flag (int, char **);
1276 static void process_flags (int, char **);
1277 static void close_files (void);
1278 static void open_files (void);
1279@@ -323,6 +325,7 @@
1280 " new location (use only with -d)\n"
1281 " -o, --non-unique allow using duplicate (non-unique) UID\n"
1282 " -p, --password PASSWORD use encrypted password for the new password\n"
1283+ " -R --root CHROOT_DIR directory to chroot into\n"
1284 " -s, --shell SHELL new login shell for the user account\n"
1285 " -u, --uid UID new UID for the user account\n"
1286 " -U, --unlock unlock the user account\n"
1287@@ -802,6 +805,58 @@
1288 }
1289
1290 /*
1291+ * process_root_flag - chroot if given the --root option
1292+ *
1293+ * We do this outside of process_flags() because
1294+ * the is_shadow_pwd boolean needs to be set before
1295+ * process_flags(), and if we do need to chroot() we
1296+ * must do so before is_shadow_pwd gets set.
1297+ */
1298+static void process_root_flag (int argc, char **argv)
1299+{
1300+ /*
1301+ * Parse the command line options.
1302+ */
1303+ int i;
1304+ char *root;
1305+
1306+ for (i = 0; i < argc; i++) {
1307+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-R")) {
1308+ if (i + 1 == argc) {
1309+ fprintf (stderr,
1310+ _("%s: option '%s' requires an argument\n"),
1311+ Prog, argv[i]);
1312+ exit (E_BAD_ARG);
1313+ }
1314+ root = argv[i + 1];
1315+
1316+ if ( (!VALID (root) )
1317+ || ( ('/' != root[0]) ) ) {
1318+ fprintf (stderr,
1319+ _("%s: invalid chroot path '%s'\n"),
1320+ Prog, root);
1321+ exit (E_BAD_ARG);
1322+ }
1323+ newroot = root;
1324+
1325+ if (access (newroot, F_OK) != 0) {
1326+ fprintf(stderr,
1327+ _("%s: chroot directory %s does not exist\n"),
1328+ Prog, newroot);
1329+ exit (E_BAD_ARG);
1330+ }
1331+ if ( chroot(newroot) != 0 ) {
1332+ fprintf(stderr,
1333+ _("%s: unable to chroot to directory %s\n"),
1334+ Prog, newroot);
1335+ exit (E_BAD_ARG);
1336+ }
1337+ break;
1338+ }
1339+ }
1340+}
1341+
1342+/*
1343 * process_flags - perform command line argument setting
1344 *
1345 * process_flags() interprets the command line arguments and sets the
1346@@ -895,6 +950,7 @@
1347 {"move-home", no_argument, NULL, 'm'},
1348 {"non-unique", no_argument, NULL, 'o'},
1349 {"password", required_argument, NULL, 'p'},
1350+ {"root", required_argument, NULL, 'R'},
1351 #ifdef WITH_SELINUX
1352 {"selinux-user", required_argument, NULL, 'Z'},
1353 #endif
1354@@ -905,9 +961,9 @@
1355 };
1356 while ((c = getopt_long (argc, argv,
1357 #ifdef WITH_SELINUX
1358- "ac:d:e:f:g:G:hl:Lmop:s:u:UZ:",
1359+ "ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
1360 #else
1361- "ac:d:e:f:g:G:hl:Lmop:s:u:U",
1362+ "ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
1363 #endif
1364 long_options, NULL)) != -1) {
1365 switch (c) {
1366@@ -999,6 +1055,9 @@
1367 user_pass = optarg;
1368 pflg = true;
1369 break;
1370+ case 'R':
1371+ /* no-op since we handled this in process_root_flag() earlier */
1372+ break;
1373 case 's':
1374 if (!VALID (optarg)) {
1375 fprintf (stderr,
1376@@ -1715,6 +1774,8 @@
1377
1378 OPENLOG ("usermod");
1379
1380+ process_root_flag (argc, argv);
1381+
1382 is_shadow_pwd = spw_file_present ();
1383 #ifdef SHADOWGRP
1384 is_shadow_grp = sgr_file_present ();