doc: correct a diagnostic in man page to match actual
[debian/gzip] / gzip.c
diff --git a/gzip.c b/gzip.c
index f40cd219abf97749d9109a41eee03ef74c83b679..a013540c4960609e3dae62f9741afaba4ac00da3 100644 (file)
--- a/gzip.c
+++ b/gzip.c
@@ -1,6 +1,6 @@
 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
 
-   Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2013 Free Software
+   Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2016 Free Software
    Foundation, Inc.
    Copyright (C) 1992-1993 Jean-loup Gailly
 
@@ -29,7 +29,7 @@
  */
 
 static char const *const license_msg[] = {
-"Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.",
+"Copyright (C) 2016 Free Software Foundation, Inc.",
 "Copyright (C) 1993 Jean-loup Gailly.",
 "This is free software.  You may redistribute copies of it under the terms of",
 "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.",
@@ -65,6 +65,7 @@ static char const *const license_msg[] = {
 #include "closein.h"
 #include "tailor.h"
 #include "gzip.h"
+#include "intprops.h"
 #include "lzw.h"
 #include "revision.h"
 #include "timespec.h"
@@ -114,12 +115,8 @@ static char const *const license_msg[] = {
   off_t lseek (int fd, off_t offset, int whence);
 #endif
 
-#ifndef OFF_T_MIN
-#define OFF_T_MIN (~ (off_t) 0 << (sizeof (off_t) * CHAR_BIT - 1))
-#endif
-
 #ifndef OFF_T_MAX
-#define OFF_T_MAX (~ (off_t) 0 - OFF_T_MIN)
+# define OFF_T_MAX TYPE_MAXIMUM (off_t)
 #endif
 
 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
@@ -188,7 +185,6 @@ static int part_nb;          /* number of parts in .gz file */
        struct timespec time_stamp; /* original time stamp (modification time) */
        off_t ifile_size;      /* input file size, -1 for devices (debug only) */
 static char *env;            /* contents of GZIP env variable */
-static char **args = NULL;   /* argv pointer if GZIP env variable defined */
 static char const *z_suffix; /* default suffix (can be set with --suffix) */
 static size_t z_len;         /* strlen(z_suffix) */
 
@@ -242,9 +238,15 @@ static int handled_sig[] =
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
 {
-  PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1
+  PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1,
+
+  /* A value greater than all valid long options, used as a flag to
+     distinguish options derived from the GZIP environment variable.  */
+  ENV_OPTION
 };
 
+static char const shortopts[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
+
 static const struct option longopts[] =
 {
  /* { name  has_arg  *flag  val } */
@@ -401,7 +403,9 @@ int main (int argc, char **argv)
 {
     int file_count;     /* number of files to process */
     size_t proglen;     /* length of program_name */
-    int optc;           /* current option */
+    char **argv_copy;
+    int env_argc;
+    char **env_argv;
 
     EXPAND(argc, argv); /* wild card expansion if necessary */
 
@@ -415,8 +419,9 @@ int main (int argc, char **argv)
       program_name[proglen - 4] = '\0';
 
     /* Add options in GZIP environment variable if there is one */
-    env = add_envopt(&argc, &argv, OPTIONS_VAR);
-    if (env != NULL) args = argv;
+    argv_copy = argv;
+    env = add_envopt (&env_argc, &argv_copy, OPTIONS_VAR);
+    env_argv = env ? argv_copy : NULL;
 
 #ifndef GNU_STANDARD
 # define GNU_STANDARD 1
@@ -440,8 +445,53 @@ int main (int argc, char **argv)
     z_suffix = Z_SUFFIX;
     z_len = strlen(z_suffix);
 
-    while ((optc = getopt_long (argc, argv, "ab:cdfhH?klLmMnNqrS:tvVZ123456789",
-                                longopts, (int *)0)) != -1) {
+    while (true) {
+        int optc;
+        int longind = -1;
+
+        if (env_argv)
+          {
+            if (env_argv[optind] && strequ (env_argv[optind], "--"))
+              optc = ENV_OPTION + '-';
+            else
+              {
+                optc = getopt_long (env_argc, env_argv, shortopts, longopts,
+                                    &longind);
+                if (0 <= optc)
+                  optc += ENV_OPTION;
+                else
+                  {
+                    if (optind != env_argc)
+                      {
+                        fprintf (stderr,
+                                 ("%s: %s: non-option in "OPTIONS_VAR
+                                  " environment variable\n"),
+                                 program_name, env_argv[optind]);
+                        try_help ();
+                      }
+
+                    /* Wait until here before warning, so that GZIP='-q'
+                       doesn't warn.  */
+                    if (env_argc != 1 && !quiet)
+                      fprintf (stderr,
+                               ("%s: warning: "OPTIONS_VAR" environment variable"
+                                " is deprecated; use an alias or script\n"),
+                               program_name);
+
+                    /* Start processing ARGC and ARGV instead.  */
+                    free (env_argv);
+                    env_argv = NULL;
+                    optind = 1;
+                    longind = -1;
+                  }
+              }
+          }
+
+        if (!env_argv)
+          optc = getopt_long (argc, argv, shortopts, longopts, &longind);
+        if (optc < 0)
+          break;
+
         switch (optc) {
         case 'a':
             ascii = 1; break;
@@ -474,12 +524,15 @@ int main (int argc, char **argv)
         case 'M': /* undocumented, may change later */
             no_time = 0; break;
         case 'n':
+        case 'n' + ENV_OPTION:
             no_name = no_time = 1; break;
         case 'N':
+        case 'N' + ENV_OPTION:
             no_name = no_time = 0; break;
         case PRESUME_INPUT_TTY_OPTION:
             presume_input_tty = true; break;
         case 'q':
+        case 'q' + ENV_OPTION:
             quiet = 1; verbose = 0; break;
         case 'r':
 #if NO_DIR
@@ -501,6 +554,7 @@ int main (int argc, char **argv)
             test = decompress = to_stdout = 1;
             break;
         case 'v':
+        case 'v' + ENV_OPTION:
             verbose++; quiet = 0; break;
         case 'V':
             version(); do_exit(OK); break;
@@ -513,12 +567,28 @@ int main (int argc, char **argv)
             try_help ();
             break;
 #endif
+        case '1' + ENV_OPTION:  case '2' + ENV_OPTION:  case '3' + ENV_OPTION:
+        case '4' + ENV_OPTION:  case '5' + ENV_OPTION:  case '6' + ENV_OPTION:
+        case '7' + ENV_OPTION:  case '8' + ENV_OPTION:  case '9' + ENV_OPTION:
+            optc -= ENV_OPTION;
+            /* Fall through.  */
         case '1':  case '2':  case '3':  case '4':
         case '5':  case '6':  case '7':  case '8':  case '9':
             level = optc - '0';
             break;
+
         default:
-            /* Error message already emitted by getopt_long. */
+            if (ENV_OPTION <= optc && optc != ENV_OPTION + '?')
+              {
+                /* Output a diagnostic, since getopt_long didn't.  */
+                fprintf (stderr, "%s: ", program_name);
+                if (longind < 0)
+                  fprintf (stderr, "-%c: ", optc - ENV_OPTION);
+                else
+                  fprintf (stderr, "--%s: ", longopts[longind].name);
+                fprintf (stderr, ("option not valid in "OPTIONS_VAR
+                                  " environment variable\n"));
+              }
             try_help ();
         }
     } /* loop on all arguments */
@@ -898,9 +968,9 @@ local void treat_file(iname)
         } else {
             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
         }
-        if (!test && !to_stdout) {
-            fprintf(stderr, " -- replaced with %s", ofname);
-        }
+        if (!test && !to_stdout)
+          fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
+                  ofname);
         fprintf(stderr, "\n");
     }
 }
@@ -989,11 +1059,25 @@ local char *get_suffix(name)
 #ifdef MAX_EXT_CHARS
           "z",
 #endif
-          NULL};
-    char const **suf = known_suffixes;
+        NULL, NULL};
+    char const **suf;
+    bool suffix_of_builtin = false;
 
-    *suf = z_suffix;
-    if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
+    /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
+       is a suffix of one of them, put it at the end.  */
+    for (suf = known_suffixes + 1; *suf; suf++)
+      {
+        size_t suflen = strlen (*suf);
+        if (z_len < suflen && strequ (z_suffix, *suf + suflen - z_len))
+          {
+            suffix_of_builtin = true;
+            break;
+          }
+      }
+    known_suffixes[suffix_of_builtin
+                   ? sizeof known_suffixes / sizeof *known_suffixes - 2
+                   : 0] = z_suffix;
+    suf = known_suffixes + suffix_of_builtin;
 
 #ifdef SUFFIX_SEP
     /* strip a version number from the file name */
@@ -1797,7 +1881,7 @@ local void treat_dir (fd, dir)
         return ;
     }
 
-    entries = streamsavedir (dirp);
+    entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
     if (! entries)
       progerror (dir);
     if (closedir (dirp) != 0)
@@ -1888,8 +1972,6 @@ local void do_exit(exitcode)
     in_exit = 1;
     free(env);
     env  = NULL;
-    free(args);
-    args = NULL;
     FREE(inbuf);
     FREE(outbuf);
     FREE(d_buf);