Module Name: src
Committed By: mlelstv
Date: Thu Dec 31 19:59:31 UTC 2009
Modified Files:
src/usr.sbin/user: user.c usermgmt.conf.5
Log Message:
Add new keyword gid_range to usermgmt.conf which specifies a default
GID range for groupadd(8).
To generate a diff of this commit:
cvs rdiff -u -r1.124 -r1.125 src/usr.sbin/user/user.c
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/user/usermgmt.conf.5
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/user/user.c
diff -u src/usr.sbin/user/user.c:1.124 src/usr.sbin/user/user.c:1.125
--- src/usr.sbin/user/user.c:1.124 Thu Oct 15 23:03:02 2009
+++ src/usr.sbin/user/user.c Thu Dec 31 19:59:31 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: user.c,v 1.124 2009/10/15 23:03:02 hubertf Exp $ */
+/* $NetBSD: user.c,v 1.125 2009/12/31 19:59:31 mlelstv Exp $ */
/*
* Copyright (c) 1999 Alistair G. Crooks. All rights reserved.
@@ -33,7 +33,7 @@
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1999\
The NetBSD Foundation, Inc. All rights reserved.");
-__RCSID("$NetBSD: user.c,v 1.124 2009/10/15 23:03:02 hubertf Exp $");
+__RCSID("$NetBSD: user.c,v 1.125 2009/12/31 19:59:31 mlelstv Exp $");
#endif
#include <sys/types.h>
@@ -71,7 +71,14 @@
int r_to; /* high uid */
} range_t;
-/* this struct encapsulates the user information */
+typedef struct rangelist_t {
+ unsigned rl_rsize; /* size of range array */
+ unsigned rl_rc; /* # of ranges */
+ range_t *rl_rv; /* the ranges */
+ unsigned rl_defrc; /* # of ranges in defaults */
+} rangelist_t;
+
+/* this struct encapsulates the user and group information */
typedef struct user_t {
int u_flags; /* see below */
int u_uid; /* uid of user */
@@ -88,14 +95,30 @@
char *u_inactive; /* when account will expire */
char *u_skeldir; /* directory for startup files */
char *u_class; /* login class */
- unsigned u_rsize; /* size of range array */
- unsigned u_rc; /* # of ranges */
- range_t *u_rv; /* the ranges */
+ rangelist_t u_r; /* list of ranges */
unsigned u_defrc; /* # of ranges in defaults */
int u_preserve; /* preserve uids on deletion */
int u_allow_samba; /* allow trailing '$' for samba login names */
int u_locked; /* user account lock */
} user_t;
+#define u_rsize u_r.rl_rsize
+#define u_rc u_r.rl_rc
+#define u_rv u_r.rl_rv
+#define u_defrc u_r.rl_defrc
+
+/* this struct encapsulates the user and group information */
+typedef struct group_t {
+ rangelist_t g_r; /* list of ranges */
+} group_t;
+#define g_rsize g_r.rl_rsize
+#define g_rc g_r.rl_rc
+#define g_rv g_r.rl_rv
+#define g_defrc g_r.rl_defrc
+
+typedef struct def_t {
+ user_t user;
+ group_t group;
+} def_t;
/* flags for which fields of the user_t replace the passwd entry */
enum {
@@ -182,9 +205,6 @@
PasswordLength = 2048,
DES_Len = 13,
-
- LowGid = DEF_LOWUID,
- HighGid = DEF_HIGHUID
};
/* Full paths of programs used here */
@@ -682,30 +702,30 @@
#ifdef EXTENSIONS
/* save a range of uids */
static int
-save_range(user_t *up, char *cp)
+save_range(rangelist_t *rlp, char *cp)
{
int from;
int to;
int i;
- if (up->u_rsize == 0) {
- up->u_rsize = 32;
- NEWARRAY(range_t, up->u_rv, up->u_rsize, return(0));
- } else if (up->u_rc == up->u_rsize) {
- up->u_rsize *= 2;
- RENEW(range_t, up->u_rv, up->u_rsize, return(0));
- }
- if (up->u_rv && sscanf(cp, "%d..%d", &from, &to) == 2) {
- for (i = up->u_defrc ; i < up->u_rc ; i++) {
- if (up->u_rv[i].r_from == from &&
- up->u_rv[i].r_to == to) {
+ if (rlp->rl_rsize == 0) {
+ rlp->rl_rsize = 32;
+ NEWARRAY(range_t, rlp->rl_rv, rlp->rl_rsize, return(0));
+ } else if (rlp->rl_rc == rlp->rl_rsize) {
+ rlp->rl_rsize *= 2;
+ RENEW(range_t, rlp->rl_rv, rlp->rl_rsize, return(0));
+ }
+ if (rlp->rl_rv && sscanf(cp, "%d..%d", &from, &to) == 2) {
+ for (i = rlp->rl_defrc ; i < rlp->rl_rc ; i++) {
+ if (rlp->rl_rv[i].r_from == from &&
+ rlp->rl_rv[i].r_to == to) {
break;
}
}
- if (i == up->u_rc) {
- up->u_rv[up->u_rc].r_from = from;
- up->u_rv[up->u_rc].r_to = to;
- up->u_rc += 1;
+ if (i == rlp->rl_rc) {
+ rlp->rl_rv[rlp->rl_rc].r_from = from;
+ rlp->rl_rv[rlp->rl_rc].r_to = to;
+ rlp->rl_rc += 1;
}
} else {
warnx("Bad range `%s'", cp);
@@ -778,7 +798,7 @@
/* read the defaults file */
static void
-read_defaults(user_t *up)
+read_defaults(def_t *dp)
{
struct stat st;
size_t lineno;
@@ -786,6 +806,10 @@
FILE *fp;
char *cp;
char *s;
+ user_t *up = &dp->user;
+ group_t *gp = &dp->group;
+
+ (void)memset(dp, 0, sizeof(*dp));
memsave(&up->u_primgrp, DEF_GROUP, strlen(DEF_GROUP));
memsave(&up->u_basedir, DEF_BASEDIR, strlen(DEF_BASEDIR));
@@ -800,6 +824,9 @@
NEWARRAY(range_t, up->u_rv, up->u_rsize, exit(1));
up->u_inactive = DEF_INACTIVE;
up->u_expire = DEF_EXPIRE;
+ gp->g_rsize = 16;
+ gp->g_defrc = 0;
+ NEWARRAY(range_t, gp->g_rv, gp->g_rsize, exit(1));
if ((fp = fopen(_PATH_USERMGMT_CONF, "r")) == NULL) {
if (stat(_PATH_USERMGMT_CONF, &st) < 0 && !setdefaults(up)) {
warn("Can't create `%s' defaults file",
@@ -846,7 +873,7 @@
#ifdef EXTENSIONS
} else if (strncmp(s, "range", 5) == 0) {
cp = skipspace(s + 5);
- (void)save_range(up, cp);
+ (void)save_range(&up->u_r, cp);
#endif
#ifdef EXTENSIONS
} else if (strncmp(s, "preserve", 8) == 0) {
@@ -865,6 +892,11 @@
} else {
memsave(&up->u_expire, cp, strlen(cp));
}
+#ifdef EXTENSIONS
+ } else if (strncmp(s, "gid_range", 9) == 0) {
+ cp = skipspace(s + 9);
+ (void)save_range(&gp->g_r, cp);
+#endif
}
(void)free(s);
}
@@ -1808,7 +1840,8 @@
int
useradd(int argc, char **argv)
{
- user_t u;
+ def_t def;
+ user_t *up = &def.user;
int defaultfield;
int bigD;
int c;
@@ -1816,9 +1849,8 @@
int i;
#endif
- (void)memset(&u, 0, sizeof(u));
- read_defaults(&u);
- u.u_uid = -1;
+ read_defaults(&def);
+ up->u_uid = -1;
defaultfield = bigD = 0;
while ((c = getopt(argc, argv, "DFG:b:c:d:e:f:g:k:mou:s:"
ADD_OPT_EXTENSIONS)) != -1) {
@@ -1833,13 +1865,13 @@
* next log in - passwd(5).
*/
defaultfield = 1;
- memsave(&u.u_inactive, "-1", strlen("-1"));
+ memsave(&up->u_inactive, "-1", strlen("-1"));
break;
case 'G':
- while (u.u_groupc < NGROUPS_MAX &&
- (u.u_groupv[u.u_groupc] = strsep(&optarg, ",")) != NULL) {
- if (u.u_groupv[u.u_groupc][0] != 0) {
- u.u_groupc++;
+ while (up->u_groupc < NGROUPS_MAX &&
+ (up->u_groupv[up->u_groupc] = strsep(&optarg, ",")) != NULL) {
+ if (up->u_groupv[up->u_groupc][0] != 0) {
+ up->u_groupc++;
}
}
if (optarg != NULL) {
@@ -1849,72 +1881,72 @@
break;
#ifdef EXTENSIONS
case 'S':
- u.u_allow_samba = 1;
+ up->u_allow_samba = 1;
break;
#endif
case 'b':
defaultfield = 1;
- memsave(&u.u_basedir, optarg, strlen(optarg));
+ memsave(&up->u_basedir, optarg, strlen(optarg));
break;
case 'c':
- memsave(&u.u_comment, optarg, strlen(optarg));
+ memsave(&up->u_comment, optarg, strlen(optarg));
break;
case 'd':
- memsave(&u.u_home, optarg, strlen(optarg));
- u.u_flags |= F_HOMEDIR;
+ memsave(&up->u_home, optarg, strlen(optarg));
+ up->u_flags |= F_HOMEDIR;
break;
case 'e':
defaultfield = 1;
- memsave(&u.u_expire, optarg, strlen(optarg));
+ memsave(&up->u_expire, optarg, strlen(optarg));
break;
case 'f':
defaultfield = 1;
- memsave(&u.u_inactive, optarg, strlen(optarg));
+ memsave(&up->u_inactive, optarg, strlen(optarg));
break;
case 'g':
defaultfield = 1;
- memsave(&u.u_primgrp, optarg, strlen(optarg));
+ memsave(&up->u_primgrp, optarg, strlen(optarg));
break;
case 'k':
defaultfield = 1;
- memsave(&u.u_skeldir, optarg, strlen(optarg));
+ memsave(&up->u_skeldir, optarg, strlen(optarg));
break;
#ifdef EXTENSIONS
case 'L':
defaultfield = 1;
- memsave(&u.u_class, optarg, strlen(optarg));
+ memsave(&up->u_class, optarg, strlen(optarg));
break;
#endif
case 'm':
- u.u_flags |= F_MKDIR;
+ up->u_flags |= F_MKDIR;
break;
#ifdef EXTENSIONS
case 'M':
defaultfield = 1;
- u.u_homeperm = strtoul(optarg, NULL, 8);
+ up->u_homeperm = strtoul(optarg, NULL, 8);
break;
#endif
case 'o':
- u.u_flags |= F_DUPUID;
+ up->u_flags |= F_DUPUID;
break;
#ifdef EXTENSIONS
case 'p':
- memsave(&u.u_password, optarg, strlen(optarg));
+ memsave(&up->u_password, optarg, strlen(optarg));
break;
#endif
#ifdef EXTENSIONS
case 'r':
defaultfield = 1;
- (void)save_range(&u, optarg);
+ (void)save_range(&up->u_r, optarg);
break;
#endif
case 's':
- u.u_flags |= F_SHELL;
+ up->u_flags |= F_SHELL;
defaultfield = 1;
- memsave(&u.u_shell, optarg, strlen(optarg));
+ memsave(&up->u_shell, optarg, strlen(optarg));
break;
case 'u':
- u.u_uid = check_numeric(optarg, "uid");
+ up->u_uid = check_numeric(optarg, "uid");
break;
#ifdef EXTENSIONS
case 'v':
@@ -1929,24 +1961,24 @@
if (bigD) {
if (defaultfield) {
checkeuid();
- return setdefaults(&u) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return setdefaults(up) ? EXIT_SUCCESS : EXIT_FAILURE;
}
- (void)printf("group\t\t%s\n", u.u_primgrp);
- (void)printf("base_dir\t%s\n", u.u_basedir);
- (void)printf("skel_dir\t%s\n", u.u_skeldir);
- (void)printf("shell\t\t%s\n", u.u_shell);
-#ifdef EXTENSIONS
- (void)printf("class\t\t%s\n", u.u_class);
- (void)printf("homeperm\t0%o\n", u.u_homeperm);
-#endif
- (void)printf("inactive\t%s\n", (u.u_inactive == NULL) ?
- UNSET_INACTIVE : u.u_inactive);
- (void)printf("expire\t\t%s\n", (u.u_expire == NULL) ?
- UNSET_EXPIRY : u.u_expire);
+ (void)printf("group\t\t%s\n", up->u_primgrp);
+ (void)printf("base_dir\t%s\n", up->u_basedir);
+ (void)printf("skel_dir\t%s\n", up->u_skeldir);
+ (void)printf("shell\t\t%s\n", up->u_shell);
+#ifdef EXTENSIONS
+ (void)printf("class\t\t%s\n", up->u_class);
+ (void)printf("homeperm\t0%o\n", up->u_homeperm);
+#endif
+ (void)printf("inactive\t%s\n", (up->u_inactive == NULL) ?
+ UNSET_INACTIVE : up->u_inactive);
+ (void)printf("expire\t\t%s\n", (up->u_expire == NULL) ?
+ UNSET_EXPIRY : up->u_expire);
#ifdef EXTENSIONS
- for (i = 0 ; i < u.u_rc ; i++) {
+ for (i = 0 ; i < up->u_rc ; i++) {
(void)printf("range\t\t%d..%d\n",
- u.u_rv[i].r_from, u.u_rv[i].r_to);
+ up->u_rv[i].r_from, up->u_rv[i].r_to);
}
#endif
return EXIT_SUCCESS;
@@ -1958,7 +1990,7 @@
}
checkeuid();
openlog("useradd", LOG_PID, LOG_USER);
- return adduser(*argv, &u) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return adduser(*argv, up) ? EXIT_SUCCESS : EXIT_FAILURE;
}
#ifdef EXTENSIONS
@@ -1970,46 +2002,46 @@
int
usermod(int argc, char **argv)
{
- user_t u;
+ def_t def;
+ user_t *up = &def.user;
char newuser[MaxUserNameLen + 1];
int c, have_new_user;
- (void)memset(&u, 0, sizeof(u));
(void)memset(newuser, 0, sizeof(newuser));
- read_defaults(&u);
+ read_defaults(&def);
have_new_user = 0;
- u.u_locked = -1;
+ up->u_locked = -1;
while ((c = getopt(argc, argv, "C:FG:c:d:e:f:g:l:mos:u:"
MOD_OPT_EXTENSIONS)) != -1) {
switch(c) {
case 'G':
- while (u.u_groupc < NGROUPS_MAX &&
- (u.u_groupv[u.u_groupc] =
+ while (up->u_groupc < NGROUPS_MAX &&
+ (up->u_groupv[up->u_groupc] =
strsep(&optarg, ",")) != NULL) {
- if (u.u_groupv[u.u_groupc][0] != 0) {
- u.u_groupc++;
+ if (up->u_groupv[up->u_groupc][0] != 0) {
+ up->u_groupc++;
}
}
if (optarg != NULL) {
warnx("Truncated list of secondary groups "
"to %d entries", NGROUPS_MAX);
}
- u.u_flags |= F_SECGROUP;
+ up->u_flags |= F_SECGROUP;
break;
#ifdef EXTENSIONS
case 'S':
- u.u_allow_samba = 1;
+ up->u_allow_samba = 1;
break;
#endif
case 'c':
- memsave(&u.u_comment, optarg, strlen(optarg));
- u.u_flags |= F_COMMENT;
+ memsave(&up->u_comment, optarg, strlen(optarg));
+ up->u_flags |= F_COMMENT;
break;
case 'C':
if (strcasecmp(optarg, "yes") == 0) {
- u.u_locked = LOCK;
+ up->u_locked = LOCK;
} else if (strcasecmp(optarg, "no") == 0) {
- u.u_locked = UNLOCK;
+ up->u_locked = UNLOCK;
} else {
/* No idea. */
errx(EXIT_FAILURE,
@@ -2017,55 +2049,55 @@
}
break;
case 'F':
- memsave(&u.u_inactive, "-1", strlen("-1"));
- u.u_flags |= F_INACTIVE;
+ memsave(&up->u_inactive, "-1", strlen("-1"));
+ up->u_flags |= F_INACTIVE;
break;
case 'd':
- memsave(&u.u_home, optarg, strlen(optarg));
- u.u_flags |= F_HOMEDIR;
+ memsave(&up->u_home, optarg, strlen(optarg));
+ up->u_flags |= F_HOMEDIR;
break;
case 'e':
- memsave(&u.u_expire, optarg, strlen(optarg));
- u.u_flags |= F_EXPIRE;
+ memsave(&up->u_expire, optarg, strlen(optarg));
+ up->u_flags |= F_EXPIRE;
break;
case 'f':
- memsave(&u.u_inactive, optarg, strlen(optarg));
- u.u_flags |= F_INACTIVE;
+ memsave(&up->u_inactive, optarg, strlen(optarg));
+ up->u_flags |= F_INACTIVE;
break;
case 'g':
- memsave(&u.u_primgrp, optarg, strlen(optarg));
- u.u_flags |= F_GROUP;
+ memsave(&up->u_primgrp, optarg, strlen(optarg));
+ up->u_flags |= F_GROUP;
break;
case 'l':
(void)strlcpy(newuser, optarg, sizeof(newuser));
have_new_user = 1;
- u.u_flags |= F_USERNAME;
+ up->u_flags |= F_USERNAME;
break;
#ifdef EXTENSIONS
case 'L':
- memsave(&u.u_class, optarg, strlen(optarg));
- u.u_flags |= F_CLASS;
+ memsave(&up->u_class, optarg, strlen(optarg));
+ up->u_flags |= F_CLASS;
break;
#endif
case 'm':
- u.u_flags |= F_MKDIR;
+ up->u_flags |= F_MKDIR;
break;
case 'o':
- u.u_flags |= F_DUPUID;
+ up->u_flags |= F_DUPUID;
break;
#ifdef EXTENSIONS
case 'p':
- memsave(&u.u_password, optarg, strlen(optarg));
- u.u_flags |= F_PASSWORD;
+ memsave(&up->u_password, optarg, strlen(optarg));
+ up->u_flags |= F_PASSWORD;
break;
#endif
case 's':
- memsave(&u.u_shell, optarg, strlen(optarg));
- u.u_flags |= F_SHELL;
+ memsave(&up->u_shell, optarg, strlen(optarg));
+ up->u_flags |= F_SHELL;
break;
case 'u':
- u.u_uid = check_numeric(optarg, "uid");
- u.u_flags |= F_UID;
+ up->u_uid = check_numeric(optarg, "uid");
+ up->u_flags |= F_UID;
break;
#ifdef EXTENSIONS
case 'v':
@@ -2077,10 +2109,10 @@
/* NOTREACHED */
}
}
- if ((u.u_flags & F_MKDIR) && !(u.u_flags & F_HOMEDIR) &&
- !(u.u_flags & F_USERNAME)) {
+ if ((up->u_flags & F_MKDIR) && !(up->u_flags & F_HOMEDIR) &&
+ !(up->u_flags & F_USERNAME)) {
warnx("Option 'm' useless without 'd' or 'l' -- ignored");
- u.u_flags &= ~F_MKDIR;
+ up->u_flags &= ~F_MKDIR;
}
argc -= optind;
argv += optind;
@@ -2089,8 +2121,8 @@
}
checkeuid();
openlog("usermod", LOG_PID, LOG_USER);
- return moduser(*argv, (have_new_user) ? newuser : *argv, &u,
- u.u_allow_samba) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return moduser(*argv, (have_new_user) ? newuser : *argv, up,
+ up->u_allow_samba) ? EXIT_SUCCESS : EXIT_FAILURE;
}
#ifdef EXTENSIONS
@@ -2103,15 +2135,15 @@
userdel(int argc, char **argv)
{
struct passwd *pwp;
- user_t u;
+ def_t def;
+ user_t *up = &def.user;
char password[PasswordLength + 1];
int defaultfield;
int rmhome;
int bigD;
int c;
- (void)memset(&u, 0, sizeof(u));
- read_defaults(&u);
+ read_defaults(&def);
defaultfield = bigD = rmhome = 0;
while ((c = getopt(argc, argv, "r" DEL_OPT_EXTENSIONS)) != -1) {
switch(c) {
@@ -2122,13 +2154,13 @@
#endif
#ifdef EXTENSIONS
case 'S':
- u.u_allow_samba = 1;
+ up->u_allow_samba = 1;
break;
#endif
#ifdef EXTENSIONS
case 'p':
defaultfield = 1;
- u.u_preserve = (strcmp(optarg, "true") == 0) ? 1 :
+ up->u_preserve = (strcmp(optarg, "true") == 0) ? 1 :
(strcmp(optarg, "yes") == 0) ? 1 :
atoi(optarg);
break;
@@ -2150,9 +2182,9 @@
if (bigD) {
if (defaultfield) {
checkeuid();
- return setdefaults(&u) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return setdefaults(up) ? EXIT_SUCCESS : EXIT_FAILURE;
}
- (void)printf("preserve\t%s\n", (u.u_preserve) ? "true" :
+ (void)printf("preserve\t%s\n", (up->u_preserve) ? "true" :
"false");
return EXIT_SUCCESS;
}
@@ -2170,22 +2202,22 @@
if (rmhome) {
(void)removehomedir(pwp);
}
- if (u.u_preserve) {
- u.u_flags |= F_SHELL;
- memsave(&u.u_shell, NOLOGIN, strlen(NOLOGIN));
+ if (up->u_preserve) {
+ up->u_flags |= F_SHELL;
+ memsave(&up->u_shell, NOLOGIN, strlen(NOLOGIN));
(void)memset(password, '*', DES_Len);
password[DES_Len] = 0;
- memsave(&u.u_password, password, strlen(password));
- u.u_flags |= F_PASSWORD;
+ memsave(&up->u_password, password, strlen(password));
+ up->u_flags |= F_PASSWORD;
openlog("userdel", LOG_PID, LOG_USER);
- return moduser(*argv, *argv, &u, u.u_allow_samba) ?
+ return moduser(*argv, *argv, up, up->u_allow_samba) ?
EXIT_SUCCESS : EXIT_FAILURE;
}
if (!rm_user_from_groups(*argv)) {
return 0;
}
openlog("userdel", LOG_PID, LOG_USER);
- return moduser(*argv, *argv, NULL, u.u_allow_samba) ?
+ return moduser(*argv, *argv, NULL, up->u_allow_samba) ?
EXIT_SUCCESS : EXIT_FAILURE;
}
@@ -2199,16 +2231,15 @@
int
groupadd(int argc, char **argv)
{
+ def_t def;
+ group_t *gp = &def.group;
int dupgid;
int gid;
int c;
- int lowgid;
- int highgid;
gid = -1;
dupgid = 0;
- lowgid = LowGid;
- highgid = HighGid;
+ read_defaults(&def);
while ((c = getopt(argc, argv, "g:o" GROUP_ADD_OPT_EXTENSIONS)) != -1) {
switch(c) {
case 'g':
@@ -2219,9 +2250,7 @@
break;
#ifdef EXTENSIONS
case 'r':
- if (sscanf(optarg, "%d..%d", &lowgid, &highgid) != 2) {
- errx(EXIT_FAILURE, "Bad range `%s'", optarg);
- }
+ (void)save_range(&gp->g_r, optarg);
break;
case 'v':
verbose = 1;
@@ -2237,9 +2266,36 @@
if (argc != 1) {
usermgmt_usage("groupadd");
}
+ if (gp->g_rc == 0) {
+ gp->g_rv[gp->g_rc].r_from = DEF_LOWUID;
+ gp->g_rv[gp->g_rc].r_to = DEF_HIGHUID;
+ gp->g_rc += 1;
+ }
+ gp->g_defrc = gp->g_rc;
checkeuid();
- if (gid < 0 && !getnextgid(&gid, lowgid, highgid)) {
- err(EXIT_FAILURE, "Can't add group: can't get next gid");
+ if (gid == -1) {
+ int got_id = 0;
+ int i;
+
+ /*
+ * Look for a free GID in the command line ranges (if any).
+ * These start after the ranges specified in the config file.
+ */
+ for (i = gp->g_defrc; !got_id && i < gp->g_rc ; i++) {
+ got_id = getnextgid(&gid,
+ gp->g_rv[i].r_from, gp->g_rv[i].r_to);
+ }
+ /*
+ * If there were no free GIDs in the command line ranges,
+ * try the ranges from the config file (there will always
+ * be at least one default).
+ */
+ for (i = 0; !got_id && i < gp->g_defrc; i++) {
+ got_id = getnextgid(&gid,
+ gp->g_rv[i].r_from, gp->g_rv[i].r_to);
+ }
+ if (!got_id)
+ errx(EXIT_FAILURE, "Can't add group: can't get next gid");
}
if (!dupgid && getgrgid((gid_t) gid) != NULL) {
errx(EXIT_FAILURE, "Can't add group: gid %d is a duplicate",
Index: src/usr.sbin/user/usermgmt.conf.5
diff -u src/usr.sbin/user/usermgmt.conf.5:1.5 src/usr.sbin/user/usermgmt.conf.5:1.6
--- src/usr.sbin/user/usermgmt.conf.5:1.5 Fri Jul 18 21:03:03 2008
+++ src/usr.sbin/user/usermgmt.conf.5 Thu Dec 31 19:59:31 2009
@@ -1,4 +1,4 @@
-.\" $NetBSD: usermgmt.conf.5,v 1.5 2008/07/18 21:03:03 apb Exp $
+.\" $NetBSD: usermgmt.conf.5,v 1.6 2009/12/31 19:59:31 mlelstv Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -121,6 +121,14 @@
.Bd -unfilled -offset indent -compact
.Ic range Ar starting-uid Ns Li .. Ns Ar ending-uid
.Ed
+.It Ic gid_range
+specifies the gid boundaries for new groups.
+If unspecified, the default is
+.Dq 1000..60000 .
+It has the format:
+.Bd -unfilled -offset indent -compact
+.Ic gid_range Ar starting-gid Ns Li .. Ns Ar ending-gid
+.Ed
.It Ic shell
sets the default login shell for new users.
.It Ic skel_dir