(root)/
coreutils-9.4/
src/
users.c
       1  /* GNU's users.
       2     Copyright (C) 1992-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 jla; revised by djm */
      18  
      19  #include <config.h>
      20  #include <stdio.h>
      21  
      22  #include <sys/types.h>
      23  #include "system.h"
      24  
      25  #include "long-options.h"
      26  #include "quote.h"
      27  #include "readutmp.h"
      28  
      29  /* The official name of this program (e.g., no 'g' prefix).  */
      30  #define PROGRAM_NAME "users"
      31  
      32  #define AUTHORS \
      33    proper_name ("Joseph Arceneaux"), \
      34    proper_name ("David MacKenzie")
      35  
      36  static int
      37  userid_compare (const void *v_a, const void *v_b)
      38  {
      39    char **a = (char **) v_a;
      40    char **b = (char **) v_b;
      41    return strcmp (*a, *b);
      42  }
      43  
      44  static void
      45  list_entries_users (idx_t n, struct gl_utmp const *this)
      46  {
      47    char **u = xinmalloc (n, sizeof *u);
      48    idx_t i;
      49    idx_t n_entries = 0;
      50  
      51    while (n--)
      52      {
      53        if (IS_USER_PROCESS (this))
      54          {
      55            char *trimmed_name;
      56  
      57            trimmed_name = extract_trimmed_name (this);
      58  
      59            u[n_entries] = trimmed_name;
      60            ++n_entries;
      61          }
      62        this++;
      63      }
      64  
      65    qsort (u, n_entries, sizeof (u[0]), userid_compare);
      66  
      67    for (i = 0; i < n_entries; i++)
      68      {
      69        char c = (i < n_entries - 1 ? ' ' : '\n');
      70        fputs (u[i], stdout);
      71        putchar (c);
      72      }
      73  
      74    for (i = 0; i < n_entries; i++)
      75      free (u[i]);
      76    free (u);
      77  }
      78  
      79  /* Display a list of users on the system, according to utmp file FILENAME.
      80     Use read_utmp OPTIONS to read FILENAME.  */
      81  
      82  static void
      83  users (char const *filename, int options)
      84  {
      85    idx_t n_users;
      86    struct gl_utmp *utmp_buf;
      87    options |= READ_UTMP_USER_PROCESS;
      88    if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
      89      error (EXIT_FAILURE, errno, "%s", quotef (filename));
      90  
      91    list_entries_users (n_users, utmp_buf);
      92  
      93    free (utmp_buf);
      94  }
      95  
      96  void
      97  usage (int status)
      98  {
      99    if (status != EXIT_SUCCESS)
     100      emit_try_help ();
     101    else
     102      {
     103        printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);
     104        printf (_("\
     105  Output who is currently logged in according to FILE.\n\
     106  If FILE is not specified, use %s.  %s as FILE is common.\n\
     107  \n\
     108  "),
     109                UTMP_FILE, WTMP_FILE);
     110        fputs (HELP_OPTION_DESCRIPTION, stdout);
     111        fputs (VERSION_OPTION_DESCRIPTION, stdout);
     112        emit_ancillary_info (PROGRAM_NAME);
     113      }
     114    exit (status);
     115  }
     116  
     117  int
     118  main (int argc, char **argv)
     119  {
     120    initialize_main (&argc, &argv);
     121    set_program_name (argv[0]);
     122    setlocale (LC_ALL, "");
     123    bindtextdomain (PACKAGE, LOCALEDIR);
     124    textdomain (PACKAGE);
     125  
     126    atexit (close_stdout);
     127  
     128    parse_gnu_standard_options_only (argc, argv, PROGRAM_NAME, PACKAGE_NAME,
     129                                     Version, true, usage, AUTHORS,
     130                                     (char const *) nullptr);
     131  
     132    switch (argc - optind)
     133      {
     134      case 0:			/* users */
     135        users (UTMP_FILE, READ_UTMP_CHECK_PIDS);
     136        break;
     137  
     138      case 1:			/* users <utmp file> */
     139        users (argv[optind], 0);
     140        break;
     141  
     142      default:			/* lose */
     143        error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
     144        usage (EXIT_FAILURE);
     145      }
     146  
     147    return EXIT_SUCCESS;
     148  }