/* groups -- print the groups a user is in                                      This is the groups utility
   Copyright (C) 1989-2018 Free Software Foundation, Inc.                       
                                                                                
   This program is free software: you can redistribute it and/or modify         
   it under the terms of the GNU General Public License as published by         
   the Free Software Foundation, either version 3 of the License, or            
   (at your option) any later version.                                          
                                                                                
   This program is distributed in the hope that it will be useful,              
   but WITHOUT ANY WARRANTY; without even the implied warranty of               
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
   GNU General Public License for more details.                                 
                                                                                
   You should have received a copy of the GNU General Public License            
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */   The GNUv3 license
                                                                                
/* Written by James Youngman based on id.c and groups.sh,                       
   which were written by Arnold Robbins and David MacKenzie. */                 
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
#include <pwd.h>                                                                ...!includes auto-comment...
#include <grp.h>                                                                ...!includes auto-comment...
#include <getopt.h>                                                             ...!includes auto-comment...
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "group-list.h"                                                         ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "groups"                                                   Line 33
                                                                                
#define AUTHORS \                                                               Line 35
  proper_name ("David MacKenzie"), \                                            Line 36
  proper_name ("James Youngman")                                                Line 37
                                                                                
                                                                                
static struct option const longopts[] =                                         Line 40
{                                                                               
  {GETOPT_HELP_OPTION_DECL},                                                    Line 42
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 43
  {NULL, 0, NULL, 0}                                                            Line 44
};                                                                              Block 1
                                                                                
void                                                                            Line 47
usage (int status)                                                              Line 48
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 50
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 52
    {                                                                           
      printf (_("Usage: %s [OPTION]... [USERNAME]...\n"), program_name);        Line 54
      fputs (_("\                                                               Line 55
Print group memberships for each USERNAME or, if no USERNAME is specified, for\ Line 56
\n\                                                                             
the current process (which may differ if the groups database has changed).\n"), Line 58
             stdout);                                                           Line 59
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 60
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 61
      emit_ancillary_info (PROGRAM_NAME);                                       Line 62
    }                                                                           
  exit (status);                                                                Line 64
}                                                                               Block 2
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 68
{                                                                               
  int optc;                                                                     Line 70
  bool ok = true;                                                               Line 71
  gid_t rgid, egid;                                                             Line 72
  uid_t ruid;                                                                   Line 73
                                                                                
  initialize_main (&argc, &argv);                                               VMS-specific entry point handling wildcard expansion
  set_program_name (argv[0]);                                                   Retains program name and discards path
  setlocale (LC_ALL, "");                                                       Sets up internationalization (i18n)
  bindtextdomain (PACKAGE, LOCALEDIR);                                          Assigns i18n directorySets text domain for _() [gettext()] function
  textdomain (PACKAGE);                                                         Sets text domain for _() [gettext()] function
                                                                                
  atexit (close_stdout);                                                        Close stdout on exit (see gnulib)
                                                                                
  /* Processing the arguments this way makes groups.c behave differently to     
   * groups.sh if one of the arguments is "--".                                 
   */                                                                           
  while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)           Line 86
    {                                                                           
      switch (optc)                                                             Line 88
        {                                                                       
        case_GETOPT_HELP_CHAR;                                                  Line 90
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 91
        default:                                                                Line 92
          usage (EXIT_FAILURE);                                                 Line 93
        }                                                                       
    }                                                                           
                                                                                
  if (optind == argc)                                                           Line 97
    {                                                                           
      /* No arguments.  Divulge the details of the current process. */          
      uid_t NO_UID = -1;                                                        Line 100
      gid_t NO_GID = -1;                                                        Line 101
                                                                                
      errno = 0;                                                                Line 103
      ruid = getuid ();                                                         Line 104...!syscalls auto-comment...
      if (ruid == NO_UID && errno)                                              Line 105
        die (EXIT_FAILURE, errno, _("cannot get real UID"));                    Line 106
                                                                                
      errno = 0;                                                                Line 108
      egid = getegid ();                                                        Line 109...!syscalls auto-comment...
      if (egid == NO_GID && errno)                                              Line 110
        die (EXIT_FAILURE, errno, _("cannot get effective GID"));               Line 111
                                                                                
      errno = 0;                                                                Line 113
      rgid = getgid ();                                                         Line 114...!syscalls auto-comment...
      if (rgid == NO_GID && errno)                                              Line 115
        die (EXIT_FAILURE, errno, _("cannot get real GID"));                    Line 116
                                                                                
      if (!print_group_list (NULL, ruid, rgid, egid, true, ' '))                Line 118
        ok = false;                                                             Line 119
      putchar ('\n');                                                           Line 120
    }                                                                           
  else                                                                          Line 122
    {                                                                           
      /* At least one argument.  Divulge the details of the specified users.  */
      for ( ; optind < argc; optind++)                                          Line 125
        {                                                                       
          struct passwd *pwd = getpwnam (argv[optind]);                         Line 127
          if (pwd == NULL)                                                      Line 128
            {                                                                   
              error (0, 0, _("%s: no such user"), quote (argv[optind]));        Line 130
              ok = false;                                                       Line 131
              continue;                                                         Line 132
            }                                                                   
          ruid = pwd->pw_uid;                                                   Line 134
          rgid = egid = pwd->pw_gid;                                            Line 135
                                                                                
          printf ("%s : ", argv[optind]);                                       Line 137
          if (!print_group_list (argv[optind], ruid, rgid, egid, true, ' '))    Line 138
            ok = false;                                                         Line 139
          putchar ('\n');                                                       Line 140
        }                                                                       
    }                                                                           
                                                                                
  return ok ? EXIT_SUCCESS : EXIT_FAILURE;                                      Line 144
}                                                                               Block 3