+static int uid_is_admissible(uint32_t uid, struct uid_range *urs)
+{
+ struct uid_range *ur;
+ int ret = 1;
+
+ if (!urs) /* empty array means all uids are allowed */
+ return 1;
+ FOR_EACH_UID_RANGE(ur, urs)
+ if (ur->low <= uid && ur->high >= uid)
+ goto out;
+ ret = 0;
+out:
+ DEBUG_LOG("uid %u is %sadmissible\n", (unsigned)uid,
+ ret? "" : "not ");
+ return ret;
+}
+
+/**
+ * Add each given user to the array of admissible users.
+ *
+ * \param users Array of user names to add.
+ * \param num_users Length of \a users.
+ * \param admissible_uids The users which are already admissible.
+ * \param num_uid_ranges The number of intervals of \a admissible_uids.
+ *
+ * For each given user, the function checks whether that user is already
+ * admissible, i.e. its uid is contained in one of the ranges given by \a
+ * admissible_uids. If it is, the function ignores that user. Otherwise, a new
+ * length-one range consisting of that uid only is appended to \a
+ * admissible_uids.
+ *
+ * \return Negative on errors, the new number of uid ranges on success.
+ */
+int append_users(char **users, int num_users,
+ struct uid_range **admissible_uids, int num_uid_ranges)
+{
+ int i;
+ struct uid_range *au = *admissible_uids;
+
+ for (i = 0; i < num_users; i++) {
+ char *u = users[i];
+ struct uid_range *ur;
+ struct passwd *pw = getpwnam(u);
+
+ if (!pw) {
+ ERROR_LOG("user %s not found\n", u);
+ return -ERRNO_TO_ERROR(EINVAL);
+ }
+ if (au && uid_is_admissible(pw->pw_uid, au))
+ continue; /* nothing to do */
+ /* add a range consisting of this uid only */
+ num_uid_ranges++;
+ au = adu_realloc(au, (num_uid_ranges + 1) *
+ sizeof(struct uid_range));
+ *admissible_uids = au;
+ ur = au + num_uid_ranges - 1; /* the new uid range */
+ ur->low = ur->high = pw->pw_uid;
+ /* terminate the list */
+ ur++;
+ ur->low = 1;
+ ur->high = 0;
+ }
+ return num_uid_ranges;
+}