/* GNU's users.                                                                 This is the users utility
   Copyright (C) 1992-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 jla; revised by djm */                                            
                                                                                
#include <config.h>                                                             Provides system specific information
#include <getopt.h>                                                             ...!includes auto-comment...
#include <stdio.h>                                                              Provides standard I/O capability
                                                                                
#include <sys/types.h>                                                          Provides system data types
#include "system.h"                                                             ...!includes auto-comment...
                                                                                
#include "die.h"                                                                ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "long-options.h"                                                       ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
#include "readutmp.h"                                                           ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "users"                                                    Line 33
                                                                                
#define AUTHORS \                                                               Line 35
  proper_name ("Joseph Arceneaux"), \                                           Line 36
  proper_name ("David MacKenzie")                                               Line 37
                                                                                
static struct option const long_options[] =                                     Line 39
{                                                                               
  {NULL, 0, NULL, 0}                                                            Line 41
};                                                                              Block 1
                                                                                
static int                                                                      Line 44
userid_compare (const void *v_a, const void *v_b)                               Line 45
{                                                                               
  char **a = (char **) v_a;                                                     Line 47
  char **b = (char **) v_b;                                                     Line 48
  return strcmp (*a, *b);                                                       Line 49
}                                                                               Block 2
                                                                                
static void                                                                     Line 52
list_entries_users (size_t n, const STRUCT_UTMP *this)                          Line 53
{                                                                               
  char **u = xnmalloc (n, sizeof *u);                                           Line 55
  size_t i;                                                                     Line 56
  size_t n_entries = 0;                                                         Line 57
                                                                                
  while (n--)                                                                   Line 59
    {                                                                           
      if (IS_USER_PROCESS (this))                                               Line 61
        {                                                                       
          char *trimmed_name;                                                   Line 63
                                                                                
          trimmed_name = extract_trimmed_name (this);                           Line 65
                                                                                
          u[n_entries] = trimmed_name;                                          Line 67
          ++n_entries;                                                          Line 68
        }                                                                       
      this++;                                                                   Line 70
    }                                                                           
                                                                                
  qsort (u, n_entries, sizeof (u[0]), userid_compare);                          Line 73
                                                                                
  for (i = 0; i < n_entries; i++)                                               Line 75
    {                                                                           
      char c = (i < n_entries - 1 ? ' ' : '\n');                                Line 77
      fputs (u[i], stdout);                                                     Line 78
      putchar (c);                                                              Line 79
    }                                                                           
                                                                                
  for (i = 0; i < n_entries; i++)                                               Line 82
    free (u[i]);                                                                Line 83
  free (u);                                                                     Line 84
}                                                                               Block 3
                                                                                
/* Display a list of users on the system, according to utmp file FILENAME.      
   Use read_utmp OPTIONS to read FILENAME.  */                                  
                                                                                
static void                                                                     Line 90
users (const char *filename, int options)                                       Line 91
{                                                                               
  size_t n_users;                                                               Line 93
  STRUCT_UTMP *utmp_buf;                                                        Line 94
                                                                                
  if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)                  Line 96
    die (EXIT_FAILURE, errno, "%s", quotef (filename));                         Line 97
                                                                                
  list_entries_users (n_users, utmp_buf);                                       Line 99
                                                                                
  free (utmp_buf);                                                              Line 101
}                                                                               Block 4
                                                                                
void                                                                            Line 104
usage (int status)                                                              Line 105
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 107
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 109
    {                                                                           
      printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);               Line 111
      printf (_("\                                                              Line 112
Output who is currently logged in according to FILE.\n\                         Line 113
If FILE is not specified, use %s.  %s as FILE is common.\n\                     Line 114
\n\                                                                             
"),                                                                             Line 116
              UTMP_FILE, WTMP_FILE);                                            Line 117
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 118
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 119
      emit_ancillary_info (PROGRAM_NAME);                                       Line 120
    }                                                                           
  exit (status);                                                                Line 122
}                                                                               Block 5
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 126
{                                                                               
  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)
                                                                                
  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,          ...!common auto-comment...
                      usage, AUTHORS, (char const *) NULL);                     Line 137
  if (getopt_long (argc, argv, "", long_options, NULL) != -1)                   Line 138
    usage (EXIT_FAILURE);                                                       Line 139
                                                                                
  switch (argc - optind)                                                        Line 141
    {                                                                           
    case 0:   /* users */                                                       Line 143
      users (UTMP_FILE, READ_UTMP_CHECK_PIDS);                                  Line 144
      break;                                                                    Line 145
                                                                                
    case 1:   /* users <utmp file> */                                           Line 147
      users (argv[optind], 0);                                                  Line 148
      break;                                                                    Line 149
                                                                                
    default:   /* lose */                                                       Line 151
      error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));            Line 152
      usage (EXIT_FAILURE);                                                     Line 153
    }                                                                           
                                                                                
  return EXIT_SUCCESS;                                                          Line 156
}