Print this page
4078 groupadd execs getent unnecessarily
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
Reviewed by: Milan Jurik <milan.jurik@xylab.cz>
Reviewed by: Gordon Ross <Gordon.W.Ross@gmail.com>

@@ -25,94 +25,88 @@
  */
 
 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
 /*        All Rights Reserved   */
 
+/*
+ * Copyright (c) 2013 RackTop Systems.
+ */
 
-#pragma ident   "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.5 */
-
+#include <errno.h>
 #include <sys/types.h>
 #include <stdio.h>
 #include <userdefs.h>
 #include <pwd.h>
+#include <libcmdutils.h>
 
-#include <sys/param.h>
-#ifndef MAXUID
-#include <limits.h>
-#ifdef UID_MAX
-#define MAXUID  UID_MAX
-#else
-#define MAXUID  60000
-#endif
-#endif
-
-static uid_t getrangeboundid(uid_t start, uid_t stop);
-static int isreserveduid(uid_t uid);
+static int findunuseduid(uid_t start, uid_t stop, uid_t *ret);
+static boolean_t isreserveduid(uid_t uid);
 
 /*
- * Find the highest uid currently in use and return it. If the highest unused
- * uid is MAXUID, then attempt to find a hole in the range. If there are no
- * more unused uids, then return -1.
+ * Find the highest unused uid. If the highest unused uid is "stop",
+ * then attempt to find a hole in the range. Returns 0 on success.
  */
-uid_t
-findnextuid(void)
+int
+findnextuid(uid_t start, uid_t stop, uid_t *ret)
 {
-        uid_t uid = DEFRID + 1;
+        uid_t uid = start;
         struct passwd *pwd;
-        uchar_t overflow = 0;
+        boolean_t overflow = B_FALSE;
 
         setpwent();
         for (pwd = getpwent(); pwd != NULL; pwd = getpwent()) {
                 if (isreserveduid(pwd->pw_uid))         /* Skip reserved IDs */
                         continue;
                 if (pwd->pw_uid >= uid) {
-                        if (pwd->pw_uid == MAXUID) {    /* Overflow check */
-                                overflow = 1;
+                        if (pwd->pw_uid == stop) {      /* Overflow check */
+                                overflow = B_TRUE;
                                 break;
                         }
                         uid = pwd->pw_uid + 1;
-                        while (isreserveduid(uid) &&
-                            uid < MAXUID) {             /* Skip reserved IDs */
-                                uid++;
                         }
                 }
+        if (pwd == NULL && errno != 0) {
+                endpwent();
+                return (-1);
         }
         endpwent();
-        if (overflow == 1)                              /* Find a hole */
-                return (getrangeboundid(DEFRID + 1, MAXUID));
-        return (uid);
+        if (overflow == B_TRUE)                         /* Find a hole */
+                return (findunuseduid(start, stop, ret));
+        while (isreserveduid(uid) && uid < stop)        /* Skip reserved IDs */
+                uid++;
+        *ret = uid;
+        return (0);
 }
 
 /*
- * Check to see that the uid is a reserved uid
+ * Check to see whether the uid is a reserved uid
  * -- nobody, noaccess or nobody4
  */
-static int
+static boolean_t
 isreserveduid(uid_t uid)
 {
         return (uid == 60001 || uid == 60002 || uid == 65534);
 }
 
-
 /*
- * getrangeboundid() attempts to return the next valid usable id between the
- * supplied upper and lower limits. If these limits exceed the system
- * boundaries of DEFRID +1 and MAXUID (lower and upper bound respectively),
- * then they are ignored and DEFRID + 1 and MAXUID are used.
- *
- * Returns a valid uid_t between DEFRID +1 and MAXUID, -1 is returned on fail
+ * findunuseduid() attempts to return the next valid usable id between the
+ * supplied upper and lower limits. Returns 0 on success.
  */
-static uid_t
-getrangeboundid(uid_t start, uid_t stop)
+static int
+findunuseduid(uid_t start, uid_t stop, uid_t *ret)
 {
-        uid_t low = (start <= DEFRID) ? DEFRID + 1 : start;
-        uid_t high = (stop < MAXUID) ? stop : MAXUID;
         uid_t uid;
 
-        for (uid = low; uid <= high; uid++) {
+        for (uid = start; uid <= stop; uid++) {
                 if (isreserveduid(uid))
                         continue;
-                if (getpwuid(uid) == NULL)
+                if (getpwuid(uid) == NULL) {
+                        if (errno != 0)
+                                return (-1);
                         break;
         }
-        return ((uid > high) ? -1 : uid);
+        }
+        if (uid > stop)
+                return (-1);
+        *ret = uid;
+        return (0);
 }