diff --git a/ChangeLog b/ChangeLog index 0082fe10..c3b25f85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-06-15 Nicolas François + + * libmisc/find_new_ids.c, libmisc/find_new_gid.c, + libmisc/find_new_uid.c, libmisc/Makefile.am, lib/prototypes.h: + Split find_new_ids.c into find_new_gid.c and find_new_uid.c to + ease the description of login.defs variables in the different + tools. + 2008-06-15 Nicolas François * libmisc/failure.c: Ignore the return value of strftime() and diff --git a/lib/prototypes.h b/lib/prototypes.h index c4aacfc3..5137608e 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -99,10 +99,12 @@ extern void sanitize_env (void); extern void change_field (char *, size_t, const char *); extern int valid_field (const char *, const char *); -/* find_new_ids.c */ -extern int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid); +/* find_new_gid.c */ extern int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid); +/* find_new_uid.c */ +extern int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid); + /* getlong.c */ extern int getlong(const char *numstr, long int *result); diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index d940f5de..a93f6d66 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -21,7 +21,8 @@ libmisc_a_SOURCES = \ failure.c \ failure.h \ fields.c \ - find_new_ids.c \ + find_new_gid.c \ + find_new_uid.c \ getdate.h \ getdate.y \ getlong.c \ diff --git a/libmisc/find_new_ids.c b/libmisc/find_new_gid.c similarity index 63% rename from libmisc/find_new_ids.c rename to libmisc/find_new_gid.c index 3e7ed905..c1f7f0a9 100644 --- a/libmisc/find_new_ids.c +++ b/libmisc/find_new_gid.c @@ -34,93 +34,9 @@ #include #include "prototypes.h" -#include "pwio.h" #include "groupio.h" #include "getdef.h" -/* - * find_new_uid - Find a new unused UID. - * - * If successful, find_new_uid provides an unused user ID in the - * [UID_MIN:UID_MAX] range. - * This ID should be higher than all the used UID, but if not possible, - * the lowest unused ID in the range will be returned. - * - * Return 0 on success, -1 if no unused UIDs are available. - */ -int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid) -{ - const struct passwd *pwd; - uid_t uid_min, uid_max, user_id; - - assert (uid != NULL); - - if (!sys_user) { - uid_min = getdef_ulong ("UID_MIN", 1000L); - uid_max = getdef_ulong ("UID_MAX", 60000L); - } else { - uid_min = getdef_ulong ("SYS_UID_MIN", 1L); - uid_max = getdef_ulong ("UID_MIN", 1000L) - 1; - uid_max = getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); - } - - if ( (NULL != preferred_uid) - && (*preferred_uid >= uid_min) - && (*preferred_uid <= uid_max) - /* Check if the user exists according to NSS */ - && (getpwuid (*preferred_uid) == NULL) - /* Check also the local database in case of uncommitted - * changes */ - && (pw_locate_uid (*preferred_uid) == NULL)) { - *uid = *preferred_uid; - return 0; - } - - - user_id = uid_min; - - /* - * Search the entire password file, - * looking for the largest unused value. - * - * We check the list of users according to NSS (setpwent/getpwent), - * but we also check the local database (pw_rewind/pw_next) in case - * some users were created but the changes were not committed yet. - */ - setpwent (); - pw_rewind (); - while ( ((pwd = getpwent ()) != NULL) - || ((pwd = pw_next ()) != NULL)) { - if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { - user_id = pwd->pw_uid + 1; - } - } - endpwent (); - - /* - * If a user with UID equal to UID_MAX exists, the above algorithm - * will give us UID_MAX+1 even if not unique. Search for the first - * free UID starting with UID_MIN (it's O(n*n) but can be avoided - * by not having users with UID equal to UID_MAX). --marekm - */ - if (user_id == uid_max + 1) { - for (user_id = uid_min; user_id < uid_max; user_id++) { - /* local, no need for xgetpwuid */ - if ( (getpwuid (user_id) == NULL) - && (pw_locate_uid (user_id) == NULL)) { - break; - } - } - if (user_id == uid_max) { - fputs (_("Can't get unique UID (no more available UIDs)\n"), stderr); - return -1; - } - } - - *uid = user_id; - return 0; -} - /* * find_new_gid - Find a new unused GID. * diff --git a/libmisc/find_new_uid.c b/libmisc/find_new_uid.c new file mode 100644 index 00000000..7a90420c --- /dev/null +++ b/libmisc/find_new_uid.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1991 - 1994, Julianne Frances Haugh + * Copyright (c) 2008 , Nicolas François + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +#include "prototypes.h" +#include "pwio.h" +#include "getdef.h" + +/* + * find_new_uid - Find a new unused UID. + * + * If successful, find_new_uid provides an unused user ID in the + * [UID_MIN:UID_MAX] range. + * This ID should be higher than all the used UID, but if not possible, + * the lowest unused ID in the range will be returned. + * + * Return 0 on success, -1 if no unused UIDs are available. + */ +int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid) +{ + const struct passwd *pwd; + uid_t uid_min, uid_max, user_id; + + assert (uid != NULL); + + if (!sys_user) { + uid_min = getdef_ulong ("UID_MIN", 1000L); + uid_max = getdef_ulong ("UID_MAX", 60000L); + } else { + uid_min = getdef_ulong ("SYS_UID_MIN", 1L); + uid_max = getdef_ulong ("UID_MIN", 1000L) - 1; + uid_max = getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); + } + + if ( (NULL != preferred_uid) + && (*preferred_uid >= uid_min) + && (*preferred_uid <= uid_max) + /* Check if the user exists according to NSS */ + && (getpwuid (*preferred_uid) == NULL) + /* Check also the local database in case of uncommitted + * changes */ + && (pw_locate_uid (*preferred_uid) == NULL)) { + *uid = *preferred_uid; + return 0; + } + + + user_id = uid_min; + + /* + * Search the entire password file, + * looking for the largest unused value. + * + * We check the list of users according to NSS (setpwent/getpwent), + * but we also check the local database (pw_rewind/pw_next) in case + * some users were created but the changes were not committed yet. + */ + setpwent (); + pw_rewind (); + while ( ((pwd = getpwent ()) != NULL) + || ((pwd = pw_next ()) != NULL)) { + if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { + user_id = pwd->pw_uid + 1; + } + } + endpwent (); + + /* + * If a user with UID equal to UID_MAX exists, the above algorithm + * will give us UID_MAX+1 even if not unique. Search for the first + * free UID starting with UID_MIN (it's O(n*n) but can be avoided + * by not having users with UID equal to UID_MAX). --marekm + */ + if (user_id == uid_max + 1) { + for (user_id = uid_min; user_id < uid_max; user_id++) { + /* local, no need for xgetpwuid */ + if ( (getpwuid (user_id) == NULL) + && (pw_locate_uid (user_id) == NULL)) { + break; + } + } + if (user_id == uid_max) { + fputs (_("Can't get unique UID (no more available UIDs)\n"), stderr); + return -1; + } + } + + *uid = user_id; + return 0; +} +