Add new select option to specify users by name.
authorAndre Noll <maan@systemlinux.org>
Thu, 6 Nov 2008 23:09:50 +0000 (00:09 +0100)
committerAndre Noll <maan@systemlinux.org>
Thu, 6 Nov 2008 23:09:50 +0000 (00:09 +0100)
This patch renames the short option -u for --uid to -U and introduces
the new --user option (short: -u) to specify admissible users by name.

The new option may be given mutltiple times to allow more than one user.

select.c
select.ggo
user.c
user.h

index 46b5372..e66b2dd 100644 (file)
--- a/select.c
+++ b/select.c
@@ -657,7 +657,7 @@ static int setup_format_string(char *fmt, struct format_info **fi)
 int parse_select_options(char *string, struct select_cmdline_parser_params *params,
                struct uid_range **admissible_uids, struct format_info **fi)
 {
-       int ret;
+       int ret, num_uid_ranges;
        const char **line;
        char *fmt = NULL;
 
@@ -678,6 +678,11 @@ int parse_select_options(char *string, struct select_cmdline_parser_params *para
                fmt = select_conf.format_arg;
        }
        ret = parse_uid_arg(select_conf.uid_arg, admissible_uids);
+       if (ret < 0)
+               return ret;
+       num_uid_ranges = ret;
+       ret = append_users(select_conf.user_arg, select_conf.user_given,
+               admissible_uids, num_uid_ranges);
        if (ret < 0)
                return ret;
        return setup_format_string(fmt, fi);
index a93007a..5ea4e8e 100644 (file)
@@ -1,11 +1,22 @@
+option "user" u
+#~~~~~~~~~~~~~~
+"users to take into account"
+string typestr="user_name"
+optional
+multiple
+details="
+       This option may be given multiple times in which case all given
+       user names are considered admissible. See also --uid below.
+"
 
-option "uid" u
+option "uid" U
 #~~~~~~~~~~~~~
 "user id(s) to take into account"
 string typestr="uid_spec"
 optional
 details="
-       An uid specifier may be a single number, or a range of uids.
+       An uid specifier may be a single uid, a range of uids,
+       or a comma-separated list of single uids or ranges.
        Example:
 
        Only consider uid 42:
@@ -19,6 +30,9 @@ details="
 
        Consider uids 23-42, 666-777 and 88:
                --uid 23-42,666-777,88
+
+       If no --user option is given and also --uid option is not given
+       (the default), all users are taken into account.
 "
 
 option "limit" L
diff --git a/user.c b/user.c
index 233764f..1f7e04a 100644 (file)
--- a/user.c
+++ b/user.c
@@ -169,6 +169,54 @@ int parse_uid_arg(const char *orig_arg, struct uid_range **ur)
        return n;
 }
 
+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;
+}
+
+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;
+}
 
 static inline int ui_used(struct user_info *ui)
 {
@@ -304,23 +352,6 @@ static uint32_t double_hash(uint32_t uid, uint32_t probe_num)
                % uid_hash_table_size;
 }
 
-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;
-}
-
 int search_uid(uint32_t uid, struct uid_range *urs,
                enum search_uid_flags flags, struct user_info **ui_ptr)
 {
diff --git a/user.h b/user.h
index 3eefab1..0eba5bb 100644 (file)
--- a/user.h
+++ b/user.h
@@ -50,4 +50,6 @@ void free_hash_table(void);
 int for_each_admissible_user(int (*func)(struct user_info *, void *),
                void *data);
 int parse_uid_arg(const char *orig_arg, struct uid_range **ur);
+int append_users(char **users, int num_users,
+               struct uid_range **admissible_uids, int num_uid_ranges);
 void close_user_tables(void);