/* GNU's uptime.                                                                This is the uptime 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
                                                                                
/* Created by hacking who.c by Kaveh Ghazi ghazi@caip.rutgers.edu.  */          
                                                                                
#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...
                                                                                
#if HAVE_SYSCTL && HAVE_SYS_SYSCTL_H                                            Line 26
# include <sys/sysctl.h>                                                        Line 27
#endif                                                                          Line 28
                                                                                
#if HAVE_OS_H                                                                   Line 30
# include <OS.h>                                                                Line 31
#endif                                                                          Line 32
                                                                                
#include "c-strtod.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...
#include "fprintftime.h"                                                        ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "uptime"                                                   Line 43
                                                                                
#define AUTHORS \                                                               Line 45
  proper_name ("Joseph Arceneaux"), \                                           Line 46
  proper_name ("David MacKenzie"), \                                            Line 47
  proper_name ("Kaveh Ghazi")                                                   Line 48
                                                                                
static struct option const long_options[] =                                     Line 50
{                                                                               
  {NULL, 0, NULL, 0}                                                            Line 52
};                                                                              Block 1
                                                                                
static void                                                                     Line 55
print_uptime (size_t n, const STRUCT_UTMP *this)                                Line 56
{                                                                               
  size_t entries = 0;                                                           Line 58
  time_t boot_time = 0;                                                         Line 59
  time_t time_now;                                                              Line 60
  time_t uptime = 0;                                                            Line 61
  long int updays;                                                              Line 62
  int uphours;                                                                  Line 63
  int upmins;                                                                   Line 64
  struct tm *tmn;                                                               Line 65
  double avg[3];                                                                Line 66
  int loads;                                                                    Line 67
#ifdef HAVE_PROC_UPTIME                                                         Line 68
  FILE *fp;                                                                     Line 69
                                                                                
  fp = fopen ("/proc/uptime", "r");                                             Line 71...!syscalls auto-comment...
  if (fp != NULL)                                                               Line 72
    {                                                                           
      char buf[BUFSIZ];                                                         Line 74
      char *b = fgets (buf, BUFSIZ, fp);                                        Line 75
      if (b == buf)                                                             Line 76
        {                                                                       
          char *end_ptr;                                                        Line 78
          double upsecs = c_strtod (buf, &end_ptr);                             Line 79
          if (buf != end_ptr)                                                   Line 80
            uptime = (0 <= upsecs && upsecs < TYPE_MAXIMUM (time_t)             Line 81
                      ? upsecs : -1);                                           Line 82
        }                                                                       
                                                                                
      fclose (fp);                                                              Line 85...!syscalls auto-comment...
    }                                                                           
#endif /* HAVE_PROC_UPTIME */                                                   Line 87
                                                                                
#if HAVE_SYSCTL && defined CTL_KERN && defined KERN_BOOTTIME                    Line 89
  {                                                                             
    /* FreeBSD specific: fetch sysctl "kern.boottime".  */                      
    static int request[2] = { CTL_KERN, KERN_BOOTTIME };                        Line 92
    struct timeval result;                                                      Line 93
    size_t result_len = sizeof result;                                          Line 94
                                                                                
    if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)                Line 96
      boot_time = result.tv_sec;                                                Line 97
  }                                                                             
#endif                                                                          Line 99
                                                                                
#if HAVE_OS_H /* BeOS */                                                        Line 101
  {                                                                             
    system_info si;                                                             Line 103
                                                                                
    get_system_info (&si);                                                      Line 105
    boot_time = si.boot_time / 1000000;                                         Line 106
  }                                                                             
#endif                                                                          Line 108
                                                                                
#if HAVE_UTMPX_H || HAVE_UTMP_H                                                 Line 110
  /* Loop through all the utmp entries we just read and count up the valid      
     ones, also in the process possibly gleaning boottime. */                   
  while (n--)                                                                   Line 113
    {                                                                           
      entries += IS_USER_PROCESS (this);                                        Line 115
      if (UT_TYPE_BOOT_TIME (this))                                             Line 116
        boot_time = UT_TIME_MEMBER (this);                                      Line 117
      ++this;                                                                   Line 118
    }                                                                           
#else                                                                           Line 120
  (void) n;                                                                     Line 121
  (void) this;                                                                  Line 122
#endif                                                                          Line 123
                                                                                
  time_now = time (NULL);                                                       Line 125
#if defined HAVE_PROC_UPTIME                                                    Line 126
  if (uptime == 0)                                                              Line 127
#endif                                                                          Line 128
    {                                                                           
      if (boot_time == 0)                                                       Line 130
        die (EXIT_FAILURE, errno, _("couldn't get boot time"));                 Line 131
      uptime = time_now - boot_time;                                            Line 132
    }                                                                           
  updays = uptime / 86400;                                                      Line 134
  uphours = (uptime - (updays * 86400)) / 3600;                                 Line 135
  upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;                 Line 136
  tmn = localtime (&time_now);                                                  Line 137
  /* procps' version of uptime also prints the seconds field, but               
     previous versions of coreutils don't. */                                   
  if (tmn)                                                                      Line 140
    /* TRANSLATORS: This prints the current clock time. */                      
    fprintftime (stdout, _(" %H:%M:%S  "), tmn, 0, 0);                          Line 142
  else                                                                          Line 143
    printf (_(" ??:????  "));                                                   Line 144
  if (uptime == (time_t) -1)                                                    Line 145
    printf (_("up ???? days ??:??,  "));                                        Line 146
  else                                                                          Line 147
    {                                                                           
      if (0 < updays)                                                           Line 149
        printf (ngettext ("up %ld day %2d:%02d,  ",                             Line 150
                          "up %ld days %2d:%02d,  ",                            Line 151
                          select_plural (updays)),                              Line 152
                updays, uphours, upmins);                                       Line 153
      else                                                                      Line 154
        printf (_("up  %2d:%02d,  "), uphours, upmins);                         Line 155
    }                                                                           
  printf (ngettext ("%lu user", "%lu users", select_plural (entries)),          Line 157
          (unsigned long int) entries);                                         Line 158
                                                                                
  loads = getloadavg (avg, 3);                                                  Line 160
                                                                                
  if (loads == -1)                                                              Line 162
    putchar ('\n');                                                             Line 163
  else                                                                          Line 164
    {                                                                           
      if (loads > 0)                                                            Line 166
        printf (_(",  load average: %.2f"), avg[0]);                            Line 167
      if (loads > 1)                                                            Line 168
        printf (", %.2f", avg[1]);                                              Line 169
      if (loads > 2)                                                            Line 170
        printf (", %.2f", avg[2]);                                              Line 171
      if (loads > 0)                                                            Line 172
        putchar ('\n');                                                         Line 173
    }                                                                           
}                                                                               Block 2
                                                                                
/* Display the system uptime and the number of users on the system,             
   according to utmp file FILENAME.  Use read_utmp OPTIONS to read the          
   utmp file.  */                                                               
                                                                                
static void                                                                     Line 181
uptime (const char *filename, int options)                                      Line 182
{                                                                               
  size_t n_users;                                                               Line 184
  STRUCT_UTMP *utmp_buf = NULL;                                                 Line 185
                                                                                
#if HAVE_UTMPX_H || HAVE_UTMP_H                                                 Line 187
  if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)                  Line 188
    die (EXIT_FAILURE, errno, "%s", quotef (filename));                         Line 189
#endif                                                                          Line 190
                                                                                
  print_uptime (n_users, utmp_buf);                                             Line 192
                                                                                
  IF_LINT (free (utmp_buf));                                                    Line 194
}                                                                               Block 3
                                                                                
void                                                                            Line 197
usage (int status)                                                              Line 198
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 200
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 202
    {                                                                           
      printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);               Line 204
      printf (_("\                                                              Line 205
Print the current time, the length of time the system has been up,\n\           Line 206
the number of users on the system, and the average number of jobs\n\            Line 207
in the run queue over the last 1, 5 and 15 minutes."));                         Line 208
#ifdef __linux__                                                                Line 209
      /* It would be better to introduce a configure test for this,             
         but such a test is hard to write.  For the moment then, we             
         have a hack which depends on the preprocessor used at compile          
         time to tell us what the running kernel is.  Ugh.  */                  
      printf (_("  \                                                            Line 214
Processes in\n\                                                                 Line 215
an uninterruptible sleep state also contribute to the load average.\n"));       Line 216
#else                                                                           Line 217
      printf (_("\n"));                                                         Line 218
#endif                                                                          Line 219
      printf (_("\                                                              Line 220
If FILE is not specified, use %s.  %s as FILE is common.\n\                     Line 221
\n"),                                                                           Line 222
              UTMP_FILE, WTMP_FILE);                                            Line 223
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 224
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 225
      emit_ancillary_info (PROGRAM_NAME);                                       Line 226
    }                                                                           
  exit (status);                                                                Line 228
}                                                                               Block 4
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 232
{                                                                               
  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 243
  if (getopt_long (argc, argv, "", long_options, NULL) != -1)                   Line 244
    usage (EXIT_FAILURE);                                                       Line 245
                                                                                
  switch (argc - optind)                                                        Line 247
    {                                                                           
    case 0:   /* uptime */                                                      Line 249
      uptime (UTMP_FILE, READ_UTMP_CHECK_PIDS);                                 Line 250
      break;                                                                    Line 251
                                                                                
    case 1:   /* uptime <utmp file> */                                          Line 253
      uptime (argv[optind], 0);                                                 Line 254
      break;                                                                    Line 255
                                                                                
    default:   /* lose */                                                       Line 257
      error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));            Line 258
      usage (EXIT_FAILURE);                                                     Line 259
    }                                                                           
                                                                                
  return EXIT_SUCCESS;                                                          Line 262
}