coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] id: add feature to accept multiple usernames


From: Achilles Gaikwad
Subject: Re: [PATCH] id: add feature to accept multiple usernames
Date: Sat, 14 Jul 2018 16:20:52 +0530

I sincerely apologize for the spam.
Please ignore the current email. There already exists a different
email with the subject
[PATCH] id: RFE to accept multiple usernames,

Sorry again!
Best,
- Achilles
---


On Sat, Jul 14, 2018 at 2:29 PM, Achilles Gaikwad <address@hidden> wrote:
> Adds a feature to id command to accept multiple usernames and/or uid
> as arguments.
>
> $ id root nobody
> uid=0(root) gid=0(root) groups=0(root)
> uid=99(nobody) gid=99(nobody) groups=99(nobody)
>
> * src/id.c (main): make varibles opt_zero, just_group_list,
> just_group, use_real, just_user global to be used in a new
> function.
> (print_stuff): new function that will print user and group information
> for the specified USER.
> Restructure the code in the file to have global variables followed by
> functions to make the file look pretty.
>
> Signed-off-by: Achilles Gaikwad <address@hidden>
> ---
>  src/id.c | 155 +++++++++++++++++++++++++++++--------------------------
>  1 file changed, 82 insertions(+), 73 deletions(-)
>
> diff --git a/src/id.c b/src/id.c
> index be0758059..65117ec5c 100644
> --- a/src/id.c
> +++ b/src/id.c
> @@ -43,10 +43,18 @@
>
>  /* If nonzero, output only the SELinux context.  */
>  static bool just_context = 0;
> -
> -static void print_user (uid_t uid);
> -static void print_full_info (const char *username);
> -
> +/* If true, delimit entries with NUL characters, not whitespace */
> +bool opt_zero = false;
> +/* If true, output the list of all group IDs. -G */
> +bool just_group_list = false;
> +/* If true, output only the group ID(s). -g */
> +bool just_group = false;
> +/* If true, output real UID/GID instead of default effective UID/GID. -r */
> +bool use_real = false;
> +/* If true, output only the user ID(s). -u */
> +bool just_user = false;
> +/* True unless errors have been encountered.  */
> +static bool ok = true;
>  /* If true, output user/group name instead of ID number. -n */
>  static bool use_name = false;
>
> @@ -54,13 +62,14 @@ static bool use_name = false;
>  static uid_t ruid, euid;
>  static gid_t rgid, egid;
>
> -/* True unless errors have been encountered.  */
> -static bool ok = true;
> -
>  /* The SELinux context.  Start with a known invalid value so print_full_info
>     knows when 'context' has not been set to a meaningful value.  */
>  static char *context = NULL;
>
> +static void print_user (uid_t uid);
> +static void print_full_info (const char *username);
> +static void print_stuff(const char *pw_name);
> +
>  static struct option const longopts[] =
>  {
>    {"context", no_argument, NULL, 'Z'},
> @@ -116,18 +125,8 @@ main (int argc, char **argv)
>    int optc;
>    int selinux_enabled = (is_selinux_enabled () > 0);
>    bool smack_enabled = is_smack_enabled ();
> -  bool opt_zero = false;
>    char *pw_name = NULL;
>
> -  /* If true, output the list of all group IDs. -G */
> -  bool just_group_list = false;
> -  /* If true, output only the group ID(s). -g */
> -  bool just_group = false;
> -  /* If true, output real UID/GID instead of default effective UID/GID. -r */
> -  bool use_real = false;
> -  /* If true, output only the user ID(s). -u */
> -  bool just_user = false;
> -
>    initialize_main (&argc, &argv);
>    set_program_name (argv[0]);
>    setlocale (LC_ALL, "");
> @@ -185,11 +184,6 @@ main (int argc, char **argv)
>      }
>
>    size_t n_ids = argc - optind;
> -  if (1 < n_ids)
> -    {
> -      error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
> -      usage (EXIT_FAILURE);
> -    }
>
>    if (n_ids && just_context)
>      die (EXIT_FAILURE, 0,
> @@ -228,29 +222,43 @@ main (int argc, char **argv)
>          die (EXIT_FAILURE, 0, _("can't get process context"));
>      }
>
> -  if (n_ids == 1)
> -    {
> -      struct passwd *pwd = NULL;
> -      const char *spec = argv[optind];
> -      /* Disallow an empty spec here as parse_user_spec() doesn't
> -         give an error for that as it seems it's a valid way to
> -         specify a noop or "reset special bits" depending on the system.  */
> -      if (*spec)
> -        {
> -          if (parse_user_spec (spec, &euid, NULL, NULL, NULL) == NULL)
> -            {
> -              /* parse_user_spec will only extract a numeric spec,
> -                 so we lookup that here to verify and also retrieve
> -                 the PW_NAME used subsequently in group lookup.  */
> -              pwd = getpwuid (euid);
> -            }
> -        }
> -      if (pwd == NULL)
> -        die (EXIT_FAILURE, 0, _("%s: no such user"), quote (spec));
> -      pw_name = xstrdup (pwd->pw_name);
> -      ruid = euid = pwd->pw_uid;
> -      rgid = egid = pwd->pw_gid;
> -    }
> +  if (n_ids >= 1)
> +  {
> +      /* Changing the value of n_ids to the last index in the array where we
> +         have the last possible user id. This helps us because we don't have
> +         to declare a different variable to keep a track of where the last 
> username
> +         lies in argv[]. */
> +      n_ids += optind;
> +
> +      /* For each username/userid to get its pw_name field */
> +      for (; optind < n_ids; optind++)
> +      {
> +          struct passwd *pwd = NULL;
> +          const char *spec = argv[optind];
> +          /* Disallow an empty spec here as parse_user_spec() doesn't
> +             give an error for that as it seems it's a valid way to
> +             specify a noop or "reset special bits" depending on the system. 
>  */
> +          if (*spec) {
> +              if (parse_user_spec(spec, &euid, NULL, NULL, NULL) == NULL) {
> +                  /* parse_user_spec will only extract a numeric spec,
> +                     so we lookup that here to verify and also retrieve
> +                     the PW_NAME used subsequently in group lookup.  */
> +                  pwd = getpwuid(euid);
> +              }
> +          }
> +          if (pwd == NULL)
> +          {
> +                       error (0, errno, _("%s: no such user"), quote 
> (argv[optind]));
> +                       ok &= false;
> +                       continue;
> +                 }
> +          pw_name = xstrdup(pwd->pw_name);
> +          ruid = euid = pwd->pw_uid;
> +          rgid = egid = pwd->pw_gid;
> +          print_stuff(pw_name);
> +          IF_LINT (free (pw_name));
> +      }
> +  }
>    else
>      {
>        /* POSIX says identification functions (getuid, getgid, and
> @@ -289,34 +297,10 @@ main (int argc, char **argv)
>            if (rgid == NO_GID && errno)
>              die (EXIT_FAILURE, errno, _("cannot get real GID"));
>          }
> +        print_stuff(pw_name);
> +           IF_LINT (free (pw_name));
>      }
>
> -  if (just_user)
> -    {
> -      print_user (use_real ? ruid : euid);
> -    }
> -  else if (just_group)
> -    {
> -      if (!print_group (use_real ? rgid : egid, use_name))
> -        ok = false;
> -    }
> -  else if (just_group_list)
> -    {
> -      if (!print_group_list (pw_name, ruid, rgid, egid, use_name,
> -                             opt_zero ? '\0' : ' '))
> -        ok = false;
> -    }
> -  else if (just_context)
> -    {
> -      fputs (context, stdout);
> -    }
> -  else
> -    {
> -      print_full_info (pw_name);
> -    }
> -  putchar (opt_zero ? '\0' : '\n');
> -
> -  IF_LINT (free (pw_name));
>    return ok ? EXIT_SUCCESS : EXIT_FAILURE;
>  }
>
> @@ -356,7 +340,7 @@ print_user (uid_t uid)
>          {
>            error (0, 0, _("cannot find name for user ID %s"),
>                   uidtostr (uid));
> -          ok = false;
> +          ok &= false;
>          }
>      }
>
> @@ -415,7 +399,7 @@ print_full_info (const char *username)
>                   quote (username));
>          else
>            error (0, errno, _("failed to get groups for the current 
> process"));
> -        ok = false;
> +        ok &= false;
>          return;
>        }
>
> @@ -438,3 +422,28 @@ print_full_info (const char *username)
>    if (context)
>      printf (_(" context=%s"), context);
>  }
> +
> +/* Print information about the user based on the arguments passed. */
> +
> +static void
> +print_stuff(const char *pw_name)
> +{
> +  if (just_user)
> +      print_user (use_real ? ruid : euid);
> +
> +  /* print_group and print_group_lists functions return true on successful
> +     execution but false if something goes wrong. We then AND this value with
> +     the current value of 'ok' because we want to know if one of the previous
> +     users faced a problem in these functions. This value of 'ok' is later 
> used
> +     to understand what status program should exit with. */
> +  else if (just_group)
> +         ok &= print_group (use_real ? rgid : egid, use_name);
> +  else if (just_group_list)
> +         ok &= print_group_list (pw_name, ruid, rgid, egid,
> +                                        use_name, opt_zero ? '\0' : ' ');
> +  else if (just_context)
> +      fputs (context, stdout);
> +  else
> +      print_full_info (pw_name);
> +  putchar (opt_zero ? '\0' : '\n');
> +}
> --
> 2.17.1
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]