* Noteworthy changes in release ?.? (????-??-??) [?]
+** Changes in behavior
+
+ The GZIP environment variable is now obsolescent; gzip now warns if
+ it is used, and rejects attempts to use dangerous options or operands.
+ You can use an alias or script instead.
+
** Bug fixes
gzip -k -v no longer reports that files are replaced.
@chapter Environment
@cindex Environment
-The environment variable @env{GZIP} can hold a set of default options for
-@command{gzip}. These options are interpreted first and can be overwritten by
-explicit command line parameters. For example:
+The obsolescent environment variable @env{GZIP} can hold a set of
+default options for @command{gzip}. These options are interpreted
+first and can be overwritten by explicit command line parameters. As
+this can cause problems when using scripts, this feature is supported
+only for options that are reasonably likely to not cause too much
+harm, and @command{gzip} warns if it is used. This feature will be
+removed in a future release of @command{gzip}.
+
+You can use an alias or script instead. For example, if
+@command{gzip} is in the directory @samp{/usr/bin} you can prepend
+@file{$HOME/bin} to your @env{PATH} and create an executable script
+@file{$HOME/bin/gzip} containing the following:
@example
-for sh: GZIP="-8v --name"; export GZIP
-for csh: setenv GZIP "-8v --name"
-for MSDOS: set GZIP=-8v --name
+#! /bin/sh
+export PATH=/usr/bin
+exec gzip -9 "$@@"
@end example
-On @abbr{VMS}, the name of the environment variable is @env{GZIP_OPT}, to
-avoid a conflict with the symbol set for invocation of the program.
+On @abbr{VMS}, the name of the obsolescent environment variable is
+@env{GZIP_OPT}, to avoid a conflict with the symbol set for invocation
+of the program.
@node Tapes
@chapter Using @command{gzip} on tapes
the whole block is passed to @command{gunzip} for decompression,
@command{gunzip} detects that there is extra trailing garbage after the
compressed data and emits a warning by default if the garbage contains
-nonzero bytes. You have to use the
-@option{--quiet} option to suppress the warning. This option can be set in the
-@env{GZIP} environment variable, as in:
-
-@example
-for sh: GZIP="-q" tar -xfz --block-compress /dev/rst0
-for csh: (setenv GZIP "-q"; tar -xfz --block-compress /dev/rst0)
-@end example
-
-In the above example, @command{gzip} is invoked implicitly by the @option{-z}
-option of @acronym{GNU} @command{tar}. Make sure that the same block
-size (@option{-b}
-option of @command{tar}) is used for reading and writing compressed data on
-tapes. (This example assumes you are using the @acronym{GNU} version of
-@command{tar}.)
+nonzero bytes. You can use the @option{--quiet} option to suppress
+the warning.
@node Problems
@chapter Reporting Bugs
transparently. gzip is designed as a complement to tar, not as a
replacement.
.SH "ENVIRONMENT"
-The environment variable
+The obsolescent environment variable
.B GZIP
can hold a set of default options for
.IR gzip .
-These options are interpreted first and can be overwritten by
-explicit command line parameters. For example:
- for sh: GZIP="-8v --name"; export GZIP
- for csh: setenv GZIP "-8v --name"
- for MSDOS: set GZIP=-8v --name
+These options are interpreted first and can be overwritten by explicit
+command line parameters. As this can cause problems when using
+scripts, this feature is supported only for options that are
+reasonably likely to not cause too much harm, and
+.I gzip
+warns if it is used.
+This feature will be removed in a future release of
+.IR gzip .
+.PP
+You can use an alias or script instead. For example, if
+.I gzip
+is in the directory
+.B /usr/bin
+you can prepend
+.B $HOME/bin
+to your
+.B PATH
+and create an executable script
+.B $HOME/bin/gzip
+containing the following:
-On Vax/VMS, the name of the environment variable is GZIP_OPT, to
+ #! /bin/sh
+ export PATH=/usr/bin
+ exec gzip \-9 "$@"
+
+On VMS, the name of the obsolescent environment variable is GZIP_OPT, to
avoid a conflict with the symbol set for invocation of the program.
.SH "SEE ALSO"
znew(1), zcmp(1), zmore(1), zforce(1), gzexe(1), zip(1), unzip(1), compress(1)
for decompression,
.I gunzip
detects that there is extra trailing garbage after the compressed data
-and emits a warning by default. You have to use the --quiet option to
-suppress the warning. This option can be set in the
-.B GZIP
-environment variable as in:
- for sh: GZIP="-q" tar -xfz --block-compress /dev/rst0
- for csh: (setenv GZIP -q; tar -xfz --block-compr /dev/rst0
-
-In the above example, gzip is invoked implicitly by the -z option of
-GNU tar. Make sure that the same block size (-b option of tar) is used
-for reading and writing compressed data on tapes. (This example
-assumes you are using the GNU version of tar.)
+and emits a warning by default. You can use the --quiet option to
+suppress the warning.
.SH BUGS
The gzip format represents the input size modulo 2^32, so the
--list option reports incorrect uncompressed sizes and compression
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) */
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 } */
{
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 */
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
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;
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
test = decompress = to_stdout = 1;
break;
case 'v':
+ case 'v' + ENV_OPTION:
verbose++; quiet = 0; break;
case 'V':
version(); do_exit(OK); break;
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 */
in_exit = 1;
free(env);
env = NULL;
- free(args);
- args = NULL;
FREE(inbuf);
FREE(outbuf);
FREE(d_buf);
# along with this program. If not, see <http://www.gnu.org/licenses/>.
TESTS = \
+ gzip-env \
helin-segv \
help-version \
hufts \
--- /dev/null
+#!/bin/sh
+# Test the obsolescent GZIP environment variable.
+
+# Copyright 2015 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 <http://www.gnu.org/licenses/>.
+# limit so don't run it by default.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ..
+
+echo a >exp || framework_failure_
+gzip <exp >in || framework_failure_
+
+fail=0
+GZIP=-qv gzip -d <in >out 2>err || fail=1
+compare exp out || fail=1
+
+for badopt in -- -c --stdout -d --decompress -f --force -h --help -k --keep \
+ -l --list -L --license -r --recursive -Sxxx --suffix=xxx '--suffix xxx' \
+ -t --test -V --version
+do
+ GZIP=$badopt gzip -d <in >out 2>err && fail=1
+done
+
+for goodopt in -n --no-name -N --name -q --quiet -v --verbose \
+ -1 --fast -2 -3 -4 -5 -6 -7 -8 -9 --best
+do
+ GZIP=$goodopt gzip -d <in >out 2>err || fail=1
+ compare exp out || fail=1
+done
+
+Exit $fail
} while (p != name);
}
-/* ========================================================================
- * Add an environment variable (if any) before argv, and update argc.
- * Return the expanded environment variable to be freed later, or NULL
- * if no options were added to argv.
- */
+/* Convert the value of the environment variable ENVVAR_NAME
+ to a newly allocated argument vector, and set *ARGCP and *ARGVP
+ to the number of arguments and to the vector, respectively.
+ Make the new vector's zeroth element equal to the old **ARGVP.
+ Return a pointer to the newly allocated string storage.
+
+ If the vector would be empty, do not allocate storage,
+ do not set *ARGCP and *ARGVP, and return NULL. */
+
#define SEPARATOR " \t" /* separators in env variable */
char *add_envopt(
char *p; /* running pointer through env variable */
char **oargv; /* runs through old argv array */
char **nargv; /* runs through new argv array */
- int oargc = *argcp; /* old argc */
int nargc = 0; /* number of arguments in env variable */
char *env_val;
free(env_val);
return NULL;
}
- *argcp += nargc;
+ *argcp = nargc + 1;
/* Allocate the new argv array, with an extra element just in case
* the original arg list did not end with a NULL.
*/
*argvp = nargv;
/* Copy the program name first */
- if (oargc-- < 0)
- gzip_error ("argc<=0");
- *(nargv++) = *(oargv++);
+ *nargv++ = *oargv;
/* Then copy the environment args */
for (p = env_val; nargc > 0; nargc--) {
while (*p++) ; /* skip over word */
}
- /* Finally copy the old args and add a NULL (usual convention) */
- while (oargc--) *(nargv++) = *(oargv++);
*nargv = NULL;
return env_val;
}