(root)/
coreutils-9.4/
src/
groups.c
       1  /* groups -- print the groups a user is in
       2     Copyright (C) 1989-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by James Youngman based on id.c and groups.sh,
      18     which were written by Arnold Robbins and David MacKenzie. */
      19  
      20  #include <config.h>
      21  #include <stdio.h>
      22  #include <sys/types.h>
      23  #include <pwd.h>
      24  #include <grp.h>
      25  #include <getopt.h>
      26  
      27  #include "system.h"
      28  #include "group-list.h"
      29  #include "quote.h"
      30  
      31  /* The official name of this program (e.g., no 'g' prefix).  */
      32  #define PROGRAM_NAME "groups"
      33  
      34  #define AUTHORS \
      35    proper_name ("David MacKenzie"), \
      36    proper_name ("James Youngman")
      37  
      38  
      39  static struct option const longopts[] =
      40  {
      41    {GETOPT_HELP_OPTION_DECL},
      42    {GETOPT_VERSION_OPTION_DECL},
      43    {nullptr, 0, nullptr, 0}
      44  };
      45  
      46  void
      47  usage (int status)
      48  {
      49    if (status != EXIT_SUCCESS)
      50      emit_try_help ();
      51    else
      52      {
      53        printf (_("Usage: %s [OPTION]... [USERNAME]...\n"), program_name);
      54        fputs (_("\
      55  Print group memberships for each USERNAME or, if no USERNAME is specified, for\
      56  \n\
      57  the current process (which may differ if the groups database has changed).\n"),
      58               stdout);
      59        fputs (HELP_OPTION_DESCRIPTION, stdout);
      60        fputs (VERSION_OPTION_DESCRIPTION, stdout);
      61        emit_ancillary_info (PROGRAM_NAME);
      62      }
      63    exit (status);
      64  }
      65  
      66  int
      67  main (int argc, char **argv)
      68  {
      69    int optc;
      70    bool ok = true;
      71    gid_t rgid, egid;
      72    uid_t ruid;
      73  
      74    initialize_main (&argc, &argv);
      75    set_program_name (argv[0]);
      76    setlocale (LC_ALL, "");
      77    bindtextdomain (PACKAGE, LOCALEDIR);
      78    textdomain (PACKAGE);
      79  
      80    atexit (close_stdout);
      81  
      82    /* Processing the arguments this way makes groups.c behave differently to
      83     * groups.sh if one of the arguments is "--".
      84     */
      85    while ((optc = getopt_long (argc, argv, "", longopts, nullptr)) != -1)
      86      {
      87        switch (optc)
      88          {
      89          case_GETOPT_HELP_CHAR;
      90          case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
      91          default:
      92            usage (EXIT_FAILURE);
      93          }
      94      }
      95  
      96    if (optind == argc)
      97      {
      98        /* No arguments.  Divulge the details of the current process. */
      99        uid_t NO_UID = -1;
     100        gid_t NO_GID = -1;
     101  
     102        errno = 0;
     103        ruid = getuid ();
     104        if (ruid == NO_UID && errno)
     105          error (EXIT_FAILURE, errno, _("cannot get real UID"));
     106  
     107        errno = 0;
     108        egid = getegid ();
     109        if (egid == NO_GID && errno)
     110          error (EXIT_FAILURE, errno, _("cannot get effective GID"));
     111  
     112        errno = 0;
     113        rgid = getgid ();
     114        if (rgid == NO_GID && errno)
     115          error (EXIT_FAILURE, errno, _("cannot get real GID"));
     116  
     117        if (!print_group_list (nullptr, ruid, rgid, egid, true, ' '))
     118          ok = false;
     119        putchar ('\n');
     120      }
     121    else
     122      {
     123        /* At least one argument.  Divulge the details of the specified users.  */
     124        for ( ; optind < argc; optind++)
     125          {
     126            struct passwd *pwd = getpwnam (argv[optind]);
     127            if (pwd == nullptr)
     128              {
     129                error (0, 0, _("%s: no such user"), quote (argv[optind]));
     130                ok = false;
     131                continue;
     132              }
     133            ruid = pwd->pw_uid;
     134            rgid = egid = pwd->pw_gid;
     135  
     136            printf ("%s : ", argv[optind]);
     137            if (!print_group_list (argv[optind], ruid, rgid, egid, true, ' '))
     138              ok = false;
     139            putchar ('\n');
     140          }
     141      }
     142  
     143    return ok ? EXIT_SUCCESS : EXIT_FAILURE;
     144  }