/* readlink -- display value of a symbolic link.                                This is the readlink utility
   Copyright (C) 2002-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 Dmitry V. Levin */                                                
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <getopt.h>                                                             ...!includes auto-comment...
#include <sys/types.h>                                                          Provides system data types
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "canonicalize.h"                                                       ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "areadlink.h"                                                          ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "readlink"                                                 Line 30
                                                                                
#define AUTHORS proper_name ("Dmitry V. Levin")                                 Line 32
                                                                                
/* If true, do not output the trailing newline.  */                             
static bool no_newline;                                                         Line 35
                                                                                
/* If true, report error messages.  */                                          
static bool verbose;                                                            Line 38
                                                                                
static struct option const longopts[] =                                         Line 40
{                                                                               
  {"canonicalize", no_argument, NULL, 'f'},                                     Line 42
  {"canonicalize-existing", no_argument, NULL, 'e'},                            Line 43
  {"canonicalize-missing", no_argument, NULL, 'm'},                             Line 44
  {"no-newline", no_argument, NULL, 'n'},                                       Line 45
  {"quiet", no_argument, NULL, 'q'},                                            Line 46
  {"silent", no_argument, NULL, 's'},                                           Line 47
  {"verbose", no_argument, NULL, 'v'},                                          Line 48
  {"zero", no_argument, NULL, 'z'},                                             Line 49
  {GETOPT_HELP_OPTION_DECL},                                                    Line 50
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 51
  {NULL, 0, NULL, 0}                                                            Line 52
};                                                                              Block 1
                                                                                
void                                                                            Line 55
usage (int status)                                                              Line 56
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 58
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 60
    {                                                                           
      printf (_("Usage: %s [OPTION]... FILE...\n"), program_name);              Line 62
      fputs (_("Print value of a symbolic link or canonical file name\n\n"),    Line 63
             stdout);                                                           Line 64
      fputs (_("\                                                               Line 65
  -f, --canonicalize            canonicalize by following every symlink in\n\   Line 66
                                every component of the given name recursively;\ Line 67
\n\                                                                             
                                all but the last component must exist\n\        Line 69
  -e, --canonicalize-existing   canonicalize by following every symlink in\n\   Line 70
                                every component of the given name recursively,\ Line 71
\n\                                                                             
                                all components must exist\n\                    Line 73
"), stdout);                                                                    Line 74
      fputs (_("\                                                               Line 75
  -m, --canonicalize-missing    canonicalize by following every symlink in\n\   Line 76
                                every component of the given name recursively,\ Line 77
\n\                                                                             
                                without requirements on components existence\n\ Line 79
  -n, --no-newline              do not output the trailing delimiter\n\         Line 80
  -q, --quiet\n\                                                                Line 81
  -s, --silent                  suppress most error messages (on by default)\n\ Line 82
  -v, --verbose                 report error messages\n\                        Line 83
  -z, --zero                    end each output line with NUL, not newline\n\   Line 84
"), stdout);                                                                    Line 85
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 86
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 87
      emit_ancillary_info (PROGRAM_NAME);                                       Line 88
    }                                                                           
  exit (status);                                                                Line 90
}                                                                               Block 2
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 94
{                                                                               
  /* If not -1, use this method to canonicalize.  */                            
  int can_mode = -1;                                                            Line 97
  int status = EXIT_SUCCESS;                                                    Line 98
  int optc;                                                                     Line 99
  bool use_nuls = false;                                                        Line 100
                                                                                
  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)
                                                                                
  while ((optc = getopt_long (argc, argv, "efmnqsvz", longopts, NULL)) != -1)   Line 110
    {                                                                           
      switch (optc)                                                             Line 112
        {                                                                       
        case 'e':                                                               Line 114
          can_mode = CAN_EXISTING;                                              Line 115
          break;                                                                Line 116
        case 'f':                                                               Line 117
          can_mode = CAN_ALL_BUT_LAST;                                          Line 118
          break;                                                                Line 119
        case 'm':                                                               Line 120
          can_mode = CAN_MISSING;                                               Line 121
          break;                                                                Line 122
        case 'n':                                                               Line 123
          no_newline = true;                                                    Line 124
          break;                                                                Line 125
        case 'q':                                                               Line 126
        case 's':                                                               Line 127
          verbose = false;                                                      Line 128
          break;                                                                Line 129
        case 'v':                                                               Line 130
          verbose = true;                                                       Line 131
          break;                                                                Line 132
        case 'z':                                                               Line 133
          use_nuls = true;                                                      Line 134
          break;                                                                Line 135
        case_GETOPT_HELP_CHAR;                                                  Line 136
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 137
        default:                                                                Line 138
          usage (EXIT_FAILURE);                                                 Line 139
        }                                                                       
    }                                                                           
                                                                                
  if (optind >= argc)                                                           Line 143
    {                                                                           
      error (0, 0, _("missing operand"));                                       Line 145
      usage (EXIT_FAILURE);                                                     Line 146
    }                                                                           
                                                                                
  if (argc - optind > 1)                                                        Line 149
    {                                                                           
      if (no_newline)                                                           Line 151
        error (0, 0, _("ignoring --no-newline with multiple arguments"));       Line 152
      no_newline = false;                                                       Line 153
    }                                                                           
                                                                                
  for (; optind < argc; ++optind)                                               Line 156
    {                                                                           
      const char *fname = argv[optind];                                         Line 158
      char *value = (can_mode != -1                                             Line 159
                     ? canonicalize_filename_mode (fname, can_mode)             Line 160
                     : areadlink_with_size (fname, 63));                        Line 161
      if (value)                                                                Line 162
        {                                                                       
          fputs (value, stdout);                                                Line 164
          if (! no_newline)                                                     Line 165
            putchar (use_nuls ? '\0' : '\n');                                   Line 166
          free (value);                                                         Line 167
        }                                                                       
      else                                                                      Line 169
        {                                                                       
          status = EXIT_FAILURE;                                                Line 171
          if (verbose)                                                          Line 172
            error (0, errno, "%s", quotef (fname));                             Line 173
        }                                                                       
    }                                                                           
                                                                                
  return status;                                                                Line 177
}