79c2e98
diff -up shadow-4.1.2/libmisc/find_new_ids.c.sysAccountDownhill shadow-4.1.2/libmisc/find_new_ids.c
79c2e98
--- shadow-4.1.2/libmisc/find_new_ids.c.sysAccountDownhill	2008-05-26 14:52:49.000000000 +0200
79c2e98
+++ shadow-4.1.2/libmisc/find_new_ids.c	2008-05-26 14:58:55.000000000 +0200
79c2e98
@@ -52,6 +52,7 @@ int find_new_uid (int sys_user, uid_t *u
b83095d
 {
b83095d
 	const struct passwd *pwd;
b83095d
 	uid_t uid_min, uid_max, user_id;
b83095d
+	char * index;
b83095d
 
b83095d
 	assert (uid != NULL);
b83095d
 
79c2e98
@@ -62,6 +63,8 @@ int find_new_uid (int sys_user, uid_t *u
b83095d
 		uid_min = getdef_unum ("SYS_UID_MIN", 1);
b83095d
 		uid_max = getdef_unum ("UID_MIN", 500) - 1;
b83095d
 		uid_max = getdef_unum ("SYS_UID_MAX", uid_max);
b83095d
+                index = alloca (sizeof (char) * uid_max +1);
b83095d
+                memset (index, 0, sizeof (char) * uid_max + 1);
b83095d
 	}
b83095d
 
b83095d
 	if (   (NULL != preferred_uid)
79c2e98
@@ -91,12 +94,28 @@ int find_new_uid (int sys_user, uid_t *u
b83095d
 	pw_rewind ();
b83095d
 	while (   ((pwd = getpwent ()) != NULL)
b83095d
 	       || ((pwd = pw_next ()) != NULL)) {
b83095d
-		if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
b83095d
-			user_id = pwd->pw_uid + 1;
b83095d
+		if (sys_user == 0) {
b83095d
+			if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
b83095d
+				user_id = pwd->pw_uid + 1;
b83095d
+			}
b83095d
+		}
b83095d
+		else {
b83095d
+			/* create index of occupied system accounts UIDs */
b83095d
+ 	 		if (pwd->pw_uid <= uid_max)
b83095d
+				index[pwd->pw_uid] = 1;
79c2e98
 		}
79c2e98
 	}
79c2e98
 	endpwent ();
79c2e98
 
b83095d
+	/* find free system account */
b83095d
+        if(sys_user) {
b83095d
+                for( user_id = uid_max; (user_id >= uid_min) && index[user_id]; user_id--);
b83095d
+                if ( user_id < uid_min ) {
b83095d
+               		fputs (_("Can't get unique UID (no more available UIDs)\n"), stderr);
b83095d
+			return -1;
79c2e98
+		}
79c2e98
+	}
79c2e98
+
79c2e98
 	/*
79c2e98
 	 * If a user with UID equal to UID_MAX exists, the above algorithm
79c2e98
 	 * will give us UID_MAX+1 even if not unique. Search for the first
79c2e98
@@ -135,6 +154,7 @@ int find_new_gid (int sys_group, gid_t *
b83095d
 {
b83095d
 	const struct group *grp;
b83095d
 	gid_t gid_min, gid_max, group_id;
b83095d
+        char * index;
b83095d
 
b83095d
 	assert (gid != NULL);
b83095d
 
79c2e98
@@ -145,6 +165,8 @@ int find_new_gid (int sys_group, gid_t *
b83095d
 		gid_min = getdef_unum ("SYS_GID_MIN", 1);
b83095d
 		gid_max = getdef_unum ("GID_MIN", 500) - 1;
b83095d
 		gid_max = getdef_unum ("SYS_GID_MAX", gid_max);
b83095d
+                index = alloca (sizeof (char) * gid_max +1);
b83095d
+                memset (index, 0, sizeof (char) * gid_max + 1);
b83095d
 	}
b83095d
 
b83095d
 	if (   (NULL != preferred_gid)
79c2e98
@@ -173,12 +195,28 @@ int find_new_gid (int sys_group, gid_t *
b83095d
 	gr_rewind ();
b83095d
 	while (   ((grp = getgrent ()) != NULL)
b83095d
 	       || ((grp = gr_next ()) != NULL)) {
b83095d
-		if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
b83095d
-			group_id = grp->gr_gid + 1;
79c2e98
+                if (sys_group == 0) {
79c2e98
+                        if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
79c2e98
+                                group_id = grp->gr_gid + 1;
79c2e98
+                        }
79c2e98
+                }
79c2e98
+                else {
79c2e98
+                        /* create index of occupied system accounts GIDs */
79c2e98
+                        if (grp->gr_gid <= gid_max)
79c2e98
+                                index[grp->gr_gid] = 1;
b83095d
 		}
b83095d
 	}
79c2e98
 	endgrent ();
b83095d
 
b83095d
+        /* find free system account */
b83095d
+        if(sys_group) {
b83095d
+                for( group_id = gid_max; (group_id >= gid_min) && index[group_id]; group_id--);
b83095d
+                if ( group_id < gid_min ) {
79c2e98
+                        fputs (_("Can't get unique GID (no more available GIDs)\n"), stderr);
79c2e98
+                        return -1;
79c2e98
+                }
b83095d
+        }
b83095d
+
b83095d
 	/*
b83095d
 	 * If a group with GID equal to GID_MAX exists, the above algorithm
b83095d
 	 * will give us GID_MAX+1 even if not unique. Search for the first