The attached patch was written back in November for Debian bug #333706. It adds the "-r" switch to useradd to make it compliant with LSB.
Tomasz has emitted some reserves about it. Matt Taggart admitted that this requirement by the LSB is certainly not the best example of how LSB standards should be defined but proposed adding the option anyway so that Debian can be LSB-compliant with that matter. So, as Matt said, accepting this upstream would make our job easier even if you're not fond of the patch, Tomasz. The patch also amends the manpage. Please note that something might be slightly broken in my patch because "--system" works as intended while "-r" does not. I intend to now apply it (when Nicolas will have found my error) and close the relevant Debian bug, no matter it's applied upstream or not. But, Tomasz, can you give us an indication whether you think it's OK for you... --
Goal: Add a "-r" option to useradd Fixes: #333706 Status wrt upstream: Forwarded but not applied yet. This patch is still incomplete ad "--system" works as expected while "-" does ot Index: shadow-4.0.14/src/useradd.c =================================================================== --- shadow-4.0.14.orig/src/useradd.c 2006-01-11 18:29:28.166697078 +0100 +++ shadow-4.0.14/src/useradd.c 2006-01-11 18:29:28.472634866 +0100 @@ -127,6 +127,7 @@ mflg = 0, /* create user's home directory if it doesn't exist */ nflg = 0, /* create a group having the same name as the user */ oflg = 0, /* permit non-unique user ID to be specified with -u */ + rflg = 0, /* create a system account (LSB compliance) */ sflg = 0, /* shell program for new account */ uflg = 0; /* specify user ID for new account */ @@ -633,6 +634,7 @@ " (non-unique) UID\n" " -p, --password PASSWORD use encrypted password for the new user\n" " account\n" + " -r, --system create a system account\n" " -s, --shell SHELL the login shell for the new user account\n" " -u, --uid UID force use the UID for the new user account\n")); exit (E_USAGE); @@ -680,11 +682,19 @@ spent->sp_namp = (char *) user_name; spent->sp_pwdp = (char *) user_pass; spent->sp_lstchg = time ((time_t *) 0) / SCALE; - spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1)); - spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1)); - spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1)); - spent->sp_inact = scale_age (def_inactive); - spent->sp_expire = scale_age (user_expire); + if (!rflg) { + spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1)); + spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1)); + spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1)); + spent->sp_inact = scale_age (def_inactive); + spent->sp_expire = scale_age (user_expire); + } else { + spent->sp_min = scale_age(-1); + spent->sp_max = scale_age(-1); + spent->sp_warn = scale_age(-1); + spent->sp_inact = scale_age(-1); + spent->sp_expire = scale_age(-1); + } spent->sp_flag = -1; } @@ -832,8 +842,13 @@ const struct passwd *pwd; uid_t uid_min, uid_max; - uid_min = getdef_unum ("UID_MIN", 1000); - uid_max = getdef_unum ("UID_MAX", 60000); + if (!rflg) { + uid_min = getdef_unum ("UID_MIN", 1000); + uid_max = getdef_unum ("UID_MAX", 60000); + } else { + uid_min = 1; + uid_max = getdef_unum ("UID_MIN", 1000) - 1; + } /* * Start with some UID value if the user didn't provide us with @@ -1012,12 +1027,13 @@ {"create-home", no_argument, NULL, 'm'}, {"non-unique", no_argument, NULL, 'o'}, {"password", required_argument, NULL, 'p'}, + {"system", no_argument, NULL, 'r'}, {"shell", required_argument, NULL, 's'}, {"uid", required_argument, NULL, 'u'}, {NULL, 0, NULL, '\0'} }; while ((c = - getopt_long (argc, argv, "b:c:d:De:f:g:G:k:O:K:mMop:s:u:", + getopt_long (argc, argv, "b:c:d:De:f:g:G:k:O:K:mMop:r:s:u:", long_options, NULL)) != -1) { switch (c) { case 'b': @@ -1171,6 +1187,9 @@ } user_pass = optarg; break; + case 'r': + rflg++; + break; case 's': if (!VALID (optarg) || (optarg[0] @@ -1556,23 +1575,25 @@ */ static void create_home (void) { - if (access (user_home, F_OK)) { - /* XXX - create missing parent directories. --marekm */ - if (mkdir (user_home, 0)) { - fprintf (stderr, - _ - ("%s: cannot create directory %s\n"), - Prog, user_home); - fail_exit (E_HOMEDIR); - } - chown (user_home, user_id, user_gid); - chmod (user_home, 0777 & ~getdef_num ("UMASK", 022)); - home_added++; + if (!rflg) /* for system accounts defaults are ignored and we + * do not create a home dir -- gafton */ + if (access (user_home, F_OK)) { + /* XXX - create missing parent directories. --marekm */ + if (mkdir (user_home, 0)) { + fprintf (stderr, + _ + ("%s: cannot create directory %s\n"), + Prog, user_home); + fail_exit (E_HOMEDIR); + } + chown (user_home, user_id, user_gid); + chmod (user_home, 0777 & ~getdef_num ("UMASK", 022)); + home_added++; #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding home directory", user_name, user_id, 1); #endif - } + } } /* Index: shadow-4.0.14/man/useradd.8.xml =================================================================== --- shadow-4.0.14.orig/man/useradd.8.xml 2006-01-11 18:29:28.257678577 +0100 +++ shadow-4.0.14/man/useradd.8.xml 2006-01-11 18:42:51.525455088 +0100 @@ -233,6 +233,20 @@ </varlistentry> <varlistentry> <term> + <option>-r</option>, <option>--system</option> + </term> + <listitem> + <para> + Add a system account, that is a user with a UID lower than + the value of UID_MIN defined in + <filename>login.defs</filename> and whose password does + not expire. This option is required by the Linux Standard + Base. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> <option>-s</option>, <option>--shell</option> <replaceable>SHELL</replaceable> </term>