try setting preference for /bin/sh in configure call
[debian/gzip] / gzip.c
diff --git a/gzip.c b/gzip.c
index 3131e860873cdc5f70fc6cb3260db732df445550..cceb42000d48e80536f3c352a103c6cea63aa644 100644 (file)
--- a/gzip.c
+++ b/gzip.c
@@ -1,11 +1,12 @@
 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
 
 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
 
-   Copyright (C) 1999, 2001, 2002, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2013 Free Software
+   Foundation, Inc.
    Copyright (C) 1992-1993 Jean-loup Gailly
 
    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
    Copyright (C) 1992-1993 Jean-loup Gailly
 
    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 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    This program is distributed in the hope that it will be useful,
    any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -27,8 +28,8 @@
  * See the file algorithm.doc for the compression algorithms and file formats.
  */
 
  * See the file algorithm.doc for the compression algorithms and file formats.
  */
 
-static char  *license_msg[] = {
-"Copyright (C) 2007 Free Software Foundation, Inc.",
+static char const *const license_msg[] = {
+"Copyright (C) 2007, 2010, 2011 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>.",
 "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>.",
@@ -53,60 +54,42 @@ static char  *license_msg[] = {
  * For the meaning of all compilation flags, see comments in Makefile.in.
  */
 
  * For the meaning of all compilation flags, see comments in Makefile.in.
  */
 
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.16 2007/03/20 05:09:51 eggert Exp $";
-#endif
-
 #include <config.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <signal.h>
 #include <config.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <errno.h>
 
 #include <sys/stat.h>
 #include <errno.h>
 
+#include "closein.h"
 #include "tailor.h"
 #include "gzip.h"
 #include "lzw.h"
 #include "revision.h"
 #include "tailor.h"
 #include "gzip.h"
 #include "lzw.h"
 #include "revision.h"
+#include "timespec.h"
 
 #include "fcntl-safer.h"
 #include "getopt.h"
 
 #include "fcntl-safer.h"
 #include "getopt.h"
+#include "ignore-value.h"
 #include "stat-time.h"
 #include "stat-time.h"
+#include "version.h"
+#include "yesno.h"
 
 
-               /* configuration */
+                /* configuration */
 
 
-#ifdef HAVE_FCNTL_H
-#  include <fcntl.h>
-#endif
-
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-#  include <stdlib.h>
-#else
-   extern int errno;
-#endif
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
 
 #ifndef NO_DIR
 # define NO_DIR 0
 #endif
 #if !NO_DIR
 # include <dirent.h>
 
 #ifndef NO_DIR
 # define NO_DIR 0
 #endif
 #if !NO_DIR
 # include <dirent.h>
-# ifndef _D_EXACT_NAMLEN
-#  define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
-# endif
-#endif
-
-#ifdef CLOSEDIR_VOID
-# define CLOSEDIR(d) (closedir(d), 0)
-#else
-# define CLOSEDIR(d) closedir(d)
+# include <savedir.h>
 #endif
 
 #ifndef NO_UTIME
 #endif
 
 #ifndef NO_UTIME
@@ -128,7 +111,7 @@ static char rcsid[] = "$Id: gzip.c,v 1.16 2007/03/20 05:09:51 eggert Exp $";
 #endif
 
 #ifdef off_t
 #endif
 
 #ifdef off_t
-  off_t lseek OF((int fd, off_t offset, int whence));
+  off_t lseek (int fd, off_t offset, int whence);
 #endif
 
 #ifndef OFF_T_MIN
 #endif
 
 #ifndef OFF_T_MIN
@@ -154,10 +137,6 @@ static char rcsid[] = "$Id: gzip.c,v 1.16 2007/03/20 05:09:51 eggert Exp $";
 # define HAVE_WORKING_O_NOFOLLOW 0
 #endif
 
 # define HAVE_WORKING_O_NOFOLLOW 0
 #endif
 
-#ifndef ELOOP
-# define ELOOP EINVAL
-#endif
-
 /* Separator for file name parts (see shorten_name()) */
 #ifdef NO_MULTIPLE_DOTS
 #  define PART_SEP "-"
 /* Separator for file name parts (see shorten_name()) */
 #ifdef NO_MULTIPLE_DOTS
 #  define PART_SEP "-"
@@ -165,7 +144,7 @@ static char rcsid[] = "$Id: gzip.c,v 1.16 2007/03/20 05:09:51 eggert Exp $";
 #  define PART_SEP "."
 #endif
 
 #  define PART_SEP "."
 #endif
 
-               /* global buffers */
+                /* global buffers */
 
 DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
 
 DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
@@ -178,35 +157,40 @@ DECLARE(uch, window, 2L*WSIZE);
     DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
 #endif
 
     DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
 #endif
 
-               /* local variables */
-
-int ascii = 0;        /* convert end-of-lines to local OS conventions */
-int to_stdout = 0;    /* output to stdout (-c) */
-int decompress = 0;   /* decompress (-d) */
-int force = 0;        /* don't ask questions, compress links (-f) */
-int no_name = -1;     /* don't save or restore the original file name */
-int no_time = -1;     /* don't save or restore the original file time */
-int recursive = 0;    /* recurse through directories (-r) */
-int list = 0;         /* list the file contents (-l) */
-int verbose = 0;      /* be verbose (-v) */
-int quiet = 0;        /* be very quiet (-q) */
-int do_lzw = 0;       /* generate output compatible with old compress (-Z) */
-int test = 0;         /* test .gz file integrity */
-int foreground = 0;   /* set if program run in foreground */
-char *program_name;   /* program name */
-int maxbits = BITS;   /* max bits per code for LZW */
-int method = DEFLATED;/* compression method */
-int level = 6;        /* compression level */
-int exit_code = OK;   /* program exit code */
-int save_orig_name;   /* set if original name must be saved */
-int last_member;      /* set for .zip and .Z files */
-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) */
-char *env;            /* contents of GZIP env variable */
-char **args = NULL;   /* argv pointer if GZIP env variable defined */
-char *z_suffix;       /* default suffix (can be set with --suffix) */
-size_t z_len;         /* strlen(z_suffix) */
+                /* local variables */
+
+/* If true, pretend that standard input is a tty.  This option
+   is deliberately not documented, and only for testing.  */
+static bool presume_input_tty;
+
+static int ascii = 0;        /* convert end-of-lines to local OS conventions */
+       int to_stdout = 0;    /* output to stdout (-c) */
+static int decompress = 0;   /* decompress (-d) */
+static int force = 0;        /* don't ask questions, compress links (-f) */
+static int keep = 0;         /* keep (don't delete) input files */
+static int no_name = -1;     /* don't save or restore the original file name */
+static int no_time = -1;     /* don't save or restore the original file time */
+static int recursive = 0;    /* recurse through directories (-r) */
+static int list = 0;         /* list the file contents (-l) */
+       int verbose = 0;      /* be verbose (-v) */
+       int quiet = 0;        /* be very quiet (-q) */
+static int do_lzw = 0;       /* generate output compatible with old compress (-Z) */
+       int test = 0;         /* test .gz file integrity */
+static int foreground = 0;   /* set if program run in foreground */
+       char *program_name;   /* program name */
+       int maxbits = BITS;   /* max bits per code for LZW */
+       int method = DEFLATED;/* compression method */
+       int level = 6;        /* compression level */
+       int exit_code = OK;   /* program exit code */
+       int save_orig_name;   /* set if original name must be saved */
+static int last_member;      /* set for .zip and .Z files */
+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) */
 
 /* The set of signals that are caught.  */
 static sigset_t caught_signals;
 
 /* The set of signals that are caught.  */
 static sigset_t caught_signals;
@@ -221,11 +205,11 @@ static int volatile remove_ofname_fd = -1;
 
 off_t bytes_in;             /* number of input bytes */
 off_t bytes_out;            /* number of output bytes */
 
 off_t bytes_in;             /* number of input bytes */
 off_t bytes_out;            /* number of output bytes */
-off_t total_in;                    /* input bytes for all files */
-off_t total_out;           /* output bytes for all files */
+static off_t total_in;      /* input bytes for all files */
+static off_t total_out;            /* output bytes for all files */
 char ifname[MAX_PATH_LEN]; /* input file name */
 char ofname[MAX_PATH_LEN]; /* output file name */
 char ifname[MAX_PATH_LEN]; /* input file name */
 char ofname[MAX_PATH_LEN]; /* output file name */
-struct stat istat;         /* status for input file */
+static struct stat istat;         /* status for input file */
 int  ifd;                  /* input file descriptor */
 int  ofd;                  /* output file descriptor */
 unsigned insize;           /* valid bytes in inbuf */
 int  ifd;                  /* input file descriptor */
 int  ofd;                  /* output file descriptor */
 unsigned insize;           /* valid bytes in inbuf */
@@ -233,7 +217,36 @@ unsigned inptr;            /* index of next byte to be processed in inbuf */
 unsigned outcnt;           /* bytes in output buffer */
 int rsync = 0;             /* make ryncable chunks */
 
 unsigned outcnt;           /* bytes in output buffer */
 int rsync = 0;             /* make ryncable chunks */
 
-struct option longopts[] =
+static int handled_sig[] =
+  {
+    /* SIGINT must be first, as 'foreground' depends on it.  */
+    SIGINT
+
+#ifdef SIGHUP
+    , SIGHUP
+#endif
+#if SIGPIPE
+    , SIGPIPE
+#endif
+#ifdef SIGTERM
+    , SIGTERM
+#endif
+#ifdef SIGXCPU
+    , SIGXCPU
+#endif
+#ifdef SIGXFSZ
+    , SIGXFSZ
+#endif
+  };
+
+/* For long options that have no equivalent short option, use a
+   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
+enum
+{
+  PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1
+};
+
+static const struct option longopts[] =
 {
  /* { name  has_arg  *flag  val } */
     {"ascii",      0, 0, 'a'}, /* ascii text mode */
 {
  /* { name  has_arg  *flag  val } */
     {"ascii",      0, 0, 'a'}, /* ascii text mode */
@@ -245,10 +258,12 @@ struct option longopts[] =
     {"force",      0, 0, 'f'}, /* force overwrite of output file */
     {"help",       0, 0, 'h'}, /* give help */
  /* {"pkzip",      0, 0, 'k'},    force output in pkzip format */
     {"force",      0, 0, 'f'}, /* force overwrite of output file */
     {"help",       0, 0, 'h'}, /* give help */
  /* {"pkzip",      0, 0, 'k'},    force output in pkzip format */
+    {"keep",       0, 0, 'k'}, /* keep (don't delete) input files */
     {"list",       0, 0, 'l'}, /* list .gz file contents */
     {"license",    0, 0, 'L'}, /* display software license */
     {"no-name",    0, 0, 'n'}, /* don't save or restore original name & time */
     {"name",       0, 0, 'N'}, /* save or restore original name & time */
     {"list",       0, 0, 'l'}, /* list .gz file contents */
     {"license",    0, 0, 'L'}, /* display software license */
     {"no-name",    0, 0, 'n'}, /* don't save or restore original name & time */
     {"name",       0, 0, 'N'}, /* save or restore original name & time */
+    {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION},
     {"quiet",      0, 0, 'q'}, /* quiet mode */
     {"silent",     0, 0, 'q'}, /* quiet mode */
     {"recursive",  0, 0, 'r'}, /* recurse through directories */
     {"quiet",      0, 0, 'q'}, /* quiet mode */
     {"silent",     0, 0, 'q'}, /* quiet mode */
     {"recursive",  0, 0, 'r'}, /* recurse through directories */
@@ -267,31 +282,32 @@ struct option longopts[] =
 
 /* local functions */
 
 
 /* local functions */
 
-local void try_help     OF((void)) ATTRIBUTE_NORETURN;
-local void help         OF((void));
-local void license      OF((void));
-local void version      OF((void));
-local int input_eof    OF((void));
-local void treat_stdin  OF((void));
-local void treat_file   OF((char *iname));
-local int create_outfile OF((void));
-local char *get_suffix  OF((char *name));
-local int  open_input_file OF((char *iname, struct stat *sbuf));
-local int  make_ofname  OF((void));
-local void shorten_name  OF((char *name));
-local int  get_method   OF((int in));
-local void do_list      OF((int ifd, int method));
-local int  check_ofname OF((void));
-local void copy_stat    OF((struct stat *ifstat));
-local void install_signal_handlers OF((void));
-local void remove_output_file OF((void));
-local RETSIGTYPE abort_gzip_signal OF((int));
-local void do_exit      OF((int exitcode)) ATTRIBUTE_NORETURN;
-      int main          OF((int argc, char **argv));
-int (*work) OF((int infile, int outfile)) = zip; /* function to call */
+local void try_help     (void) ATTRIBUTE_NORETURN;
+local void help         (void);
+local void license      (void);
+local void version      (void);
+local int input_eof    (void);
+local void treat_stdin  (void);
+local void treat_file   (char *iname);
+local int create_outfile (void);
+local char *get_suffix  (char *name);
+local int  open_input_file (char *iname, struct stat *sbuf);
+local void discard_input_bytes (size_t nbytes, unsigned int flags);
+local int  make_ofname  (void);
+local void shorten_name  (char *name);
+local int  get_method   (int in);
+local void do_list      (int ifd, int method);
+local int  check_ofname (void);
+local void copy_stat    (struct stat *ifstat);
+local void install_signal_handlers (void);
+local void remove_output_file (void);
+local RETSIGTYPE abort_gzip_signal (int);
+local void do_exit      (int exitcode) ATTRIBUTE_NORETURN;
+      int main          (int argc, char **argv);
+static int (*work) (int infile, int outfile) = zip; /* function to call */
 
 #if ! NO_DIR
 
 #if ! NO_DIR
-local void treat_dir    OF((int fd, char *dir));
+local void treat_dir    (int fd, char *dir);
 #endif
 
 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
 #endif
 
 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
@@ -300,14 +316,14 @@ static void
 try_help ()
 {
   fprintf (stderr, "Try `%s --help' for more information.\n",
 try_help ()
 {
   fprintf (stderr, "Try `%s --help' for more information.\n",
-          program_name);
+           program_name);
   do_exit (ERROR);
 }
 
 /* ======================================================================== */
 local void help()
 {
   do_exit (ERROR);
 }
 
 /* ======================================================================== */
 local void help()
 {
-    static char  *help_msg[] = {
+    static char const* const help_msg[] = {
  "Compress or uncompress FILEs (by default, compress FILES in-place).",
  "",
  "Mandatory arguments to long options are mandatory for short options too.",
  "Compress or uncompress FILEs (by default, compress FILES in-place).",
  "",
  "Mandatory arguments to long options are mandatory for short options too.",
@@ -321,6 +337,7 @@ local void help()
  "  -f, --force       force overwrite of output file and compress links",
  "  -h, --help        give this help",
 /*  -k, --pkzip       force output in pkzip format */
  "  -f, --force       force overwrite of output file and compress links",
  "  -h, --help        give this help",
 /*  -k, --pkzip       force output in pkzip format */
+ "  -k, --keep        keep (don't delete) input files",
  "  -l, --list        list compressed file contents",
  "  -L, --license     display software license",
 #ifdef UNDOCUMENTED
  "  -l, --list        list compressed file contents",
  "  -L, --license     display software license",
 #ifdef UNDOCUMENTED
@@ -343,13 +360,13 @@ local void help()
  "  -Z, --lzw         produce output compatible with old compress",
  "  -b, --bits=BITS   max number of bits per code (implies -Z)",
 #endif
  "  -Z, --lzw         produce output compatible with old compress",
  "  -b, --bits=BITS   max number of bits per code (implies -Z)",
 #endif
- "    --rsyncable   Make rsync-friendly archive",
+ "  --rsyncable       Make rsync-friendly archive",
  "",
  "With no FILE, or when FILE is -, read standard input.",
  "",
  "Report bugs to <bug-gzip@gnu.org>.",
   0};
  "",
  "With no FILE, or when FILE is -, read standard input.",
  "",
  "Report bugs to <bug-gzip@gnu.org>.",
   0};
-    char **p = help_msg;
+    char const *const *p = help_msg;
 
     printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
     while (*p) printf ("%s\n", *p++);
 
     printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
     while (*p) printf ("%s\n", *p++);
@@ -358,9 +375,9 @@ local void help()
 /* ======================================================================== */
 local void license()
 {
 /* ======================================================================== */
 local void license()
 {
-    char **p = license_msg;
+    char const *const *p = license_msg;
 
 
-    printf ("%s %s\n", program_name, VERSION);
+    printf ("%s %s\n", program_name, Version);
     while (*p) printf ("%s\n", *p++);
 }
 
     while (*p) printf ("%s\n", *p++);
 }
 
@@ -372,8 +389,7 @@ local void version()
     printf ("Written by Jean-loup Gailly.\n");
 }
 
     printf ("Written by Jean-loup Gailly.\n");
 }
 
-local void progerror (string)
-    char *string;
+local void progerror (char const *string)
 {
     int e = errno;
     fprintf (stderr, "%s: ", program_name);
 {
     int e = errno;
     fprintf (stderr, "%s: ", program_name);
@@ -383,9 +399,7 @@ local void progerror (string)
 }
 
 /* ======================================================================== */
 }
 
 /* ======================================================================== */
-int main (argc, argv)
-    int argc;
-    char **argv;
+int main (int argc, char **argv)
 {
     int file_count;     /* number of files to process */
     size_t proglen;     /* length of program_name */
 {
     int file_count;     /* number of files to process */
     size_t proglen;     /* length of program_name */
@@ -396,6 +410,8 @@ int main (argc, argv)
     program_name = gzip_base_name (argv[0]);
     proglen = strlen (program_name);
 
     program_name = gzip_base_name (argv[0]);
     proglen = strlen (program_name);
 
+    atexit (close_stdin);
+
     /* Suppress .exe for MSDOS, OS/2 and VMS: */
     if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
       program_name[proglen - 4] = '\0';
     /* Suppress .exe for MSDOS, OS/2 and VMS: */
     if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
       program_name[proglen - 4] = '\0';
@@ -416,62 +432,67 @@ int main (argc, argv)
      * Ignore an .exe extension for MSDOS, OS/2 and VMS.
      */
     if (strncmp (program_name, "un",  2) == 0     /* ungzip, uncompress */
      * Ignore an .exe extension for MSDOS, OS/2 and VMS.
      */
     if (strncmp (program_name, "un",  2) == 0     /* ungzip, uncompress */
-       || strncmp (program_name, "gun", 3) == 0) /* gunzip */
-       decompress = 1;
+        || strncmp (program_name, "gun", 3) == 0) /* gunzip */
+        decompress = 1;
     else if (strequ (program_name + 1, "cat")     /* zcat, pcat, gcat */
     else if (strequ (program_name + 1, "cat")     /* zcat, pcat, gcat */
-            || strequ (program_name, "gzcat"))   /* gzcat */
-       decompress = to_stdout = 1;
+             || strequ (program_name, "gzcat"))   /* gzcat */
+        decompress = to_stdout = 1;
 #endif
 
     z_suffix = Z_SUFFIX;
     z_len = strlen(z_suffix);
 
 #endif
 
     z_suffix = Z_SUFFIX;
     z_len = strlen(z_suffix);
 
-    while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789",
-                               longopts, (int *)0)) != -1) {
-       switch (optc) {
+    while ((optc = getopt_long (argc, argv, "ab:cdfhH?klLmMnNqrS:tvVZ123456789",
+                                longopts, (int *)0)) != -1) {
+        switch (optc) {
         case 'a':
             ascii = 1; break;
         case 'a':
             ascii = 1; break;
-       case 'b':
-           maxbits = atoi(optarg);
-           for (; *optarg; optarg++)
-             if (! ('0' <= *optarg && *optarg <= '9'))
-               {
-                 fprintf (stderr, "%s: -b operand is not an integer\n",
-                          program_name);
-                 try_help ();
-               }
-           break;
-       case 'c':
-           to_stdout = 1; break;
-       case 'd':
-           decompress = 1; break;
-       case 'f':
-           force++; break;
-       case 'h': case 'H':
-           help(); do_exit(OK); break;
-       case 'l':
-           list = decompress = to_stdout = 1; break;
-       case 'L':
-           license(); do_exit(OK); break;
-       case 'm': /* undocumented, may change later */
-           no_time = 1; break;
-       case 'M': /* undocumented, may change later */
-           no_time = 0; break;
-       case 'n':
-           no_name = no_time = 1; break;
-       case 'N':
-           no_name = no_time = 0; break;
-       case 'q':
-           quiet = 1; verbose = 0; break;
-       case 'r':
+        case 'b':
+            maxbits = atoi(optarg);
+            for (; *optarg; optarg++)
+              if (! ('0' <= *optarg && *optarg <= '9'))
+                {
+                  fprintf (stderr, "%s: -b operand is not an integer\n",
+                           program_name);
+                  try_help ();
+                }
+            break;
+        case 'c':
+            to_stdout = 1; break;
+        case 'd':
+            decompress = 1; break;
+        case 'f':
+            force++; break;
+        case 'h': case 'H':
+            help(); do_exit(OK); break;
+        case 'k':
+            keep = 1; break;
+        case 'l':
+            list = decompress = to_stdout = 1; break;
+        case 'L':
+            license(); do_exit(OK); break;
+        case 'm': /* undocumented, may change later */
+            no_time = 1; break;
+        case 'M': /* undocumented, may change later */
+            no_time = 0; break;
+        case 'n':
+            no_name = no_time = 1; break;
+        case 'N':
+            no_name = no_time = 0; break;
+        case PRESUME_INPUT_TTY_OPTION:
+            presume_input_tty = true; break;
+        case 'q':
+            quiet = 1; verbose = 0; break;
+        case 'r':
 #if NO_DIR
 #if NO_DIR
-           fprintf (stderr, "%s: -r not supported on this system\n",
-                    program_name);
-           try_help ();
+            fprintf (stderr, "%s: -r not supported on this system\n",
+                     program_name);
+            try_help ();
 #else
 #else
-           recursive = 1;
+            recursive = 1;
 #endif
 #endif
-       case 'R':
+           break;
+        case 'R':
            rsync = 1; break;
 
        case 'S':
            rsync = 1; break;
 
        case 'S':
@@ -479,32 +500,32 @@ int main (argc, argv)
             if (*optarg == '.') optarg++;
 #endif
             z_len = strlen(optarg);
             if (*optarg == '.') optarg++;
 #endif
             z_len = strlen(optarg);
-           z_suffix = optarg;
+            z_suffix = optarg;
             break;
             break;
-       case 't':
-           test = decompress = to_stdout = 1;
-           break;
-       case 'v':
-           verbose++; quiet = 0; break;
-       case 'V':
-           version(); do_exit(OK); break;
-       case 'Z':
+        case 't':
+            test = decompress = to_stdout = 1;
+            break;
+        case 'v':
+            verbose++; quiet = 0; break;
+        case 'V':
+            version(); do_exit(OK); break;
+        case 'Z':
 #ifdef LZW
 #ifdef LZW
-           do_lzw = 1; break;
+            do_lzw = 1; break;
 #else
 #else
-           fprintf(stderr, "%s: -Z not supported in this version\n",
-                   program_name);
-           try_help ();
-           break;
+            fprintf(stderr, "%s: -Z not supported in this version\n",
+                    program_name);
+            try_help ();
+            break;
 #endif
 #endif
-       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. */
-           try_help ();
-       }
+        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. */
+            try_help ();
+        }
     } /* loop on all arguments */
 
     /* By default, save name and timestamp on compression but do not
     } /* loop on all arguments */
 
     /* By default, save name and timestamp on compression but do not
@@ -518,15 +539,15 @@ int main (argc, argv)
 #if O_BINARY
 #else
     if (ascii && !quiet) {
 #if O_BINARY
 #else
     if (ascii && !quiet) {
-       fprintf(stderr, "%s: option --ascii ignored on this system\n",
-               program_name);
+        fprintf(stderr, "%s: option --ascii ignored on this system\n",
+                program_name);
     }
 #endif
     }
 #endif
-    if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) {
-        fprintf(stderr, "%s: incorrect suffix '%s'\n",
-                program_name, z_suffix);
+    if (z_len == 0 || z_len > MAX_SUFFIX) {
+        fprintf(stderr, "%s: invalid suffix '%s'\n", program_name, z_suffix);
         do_exit(ERROR);
     }
         do_exit(ERROR);
     }
+
     if (do_lzw && !decompress) work = lzw;
 
     /* Allocate all global buffers (for DYN_ALLOC option) */
     if (do_lzw && !decompress) work = lzw;
 
     /* Allocate all global buffers (for DYN_ALLOC option) */
@@ -541,22 +562,26 @@ int main (argc, argv)
     ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
 #endif
 
     ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
 #endif
 
+#ifdef SIGPIPE
     exiting_signal = quiet ? SIGPIPE : 0;
     exiting_signal = quiet ? SIGPIPE : 0;
+#else
+    exiting_signal = 0;
+#endif
     install_signal_handlers ();
 
     /* And get to work */
     if (file_count != 0) {
     install_signal_handlers ();
 
     /* And get to work */
     if (file_count != 0) {
-       if (to_stdout && !test && !list && (!decompress || !ascii)) {
-           SET_BINARY_MODE(fileno(stdout));
-       }
+        if (to_stdout && !test && !list && (!decompress || !ascii)) {
+            SET_BINARY_MODE(fileno(stdout));
+        }
         while (optind < argc) {
         while (optind < argc) {
-           treat_file(argv[optind++]);
-       }
+            treat_file(argv[optind++]);
+        }
     } else {  /* Standard input */
     } else {  /* Standard input */
-       treat_stdin();
+        treat_stdin();
     }
     if (list && !quiet && file_count > 1) {
     }
     if (list && !quiet && file_count > 1) {
-       do_list(-1, -1); /* print totals */
+        do_list(-1, -1); /* print totals */
     }
     do_exit(exit_code);
     return exit_code; /* just to avoid lint warning */
     }
     do_exit(exit_code);
     return exit_code; /* just to avoid lint warning */
@@ -572,7 +597,7 @@ input_eof ()
   if (inptr == insize)
     {
       if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
   if (inptr == insize)
     {
       if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
-       return 1;
+        return 1;
 
       /* Unget the char that fill_inbuf got.  */
       inptr = 0;
 
       /* Unget the char that fill_inbuf got.  */
       inptr = 0;
@@ -586,33 +611,38 @@ input_eof ()
  */
 local void treat_stdin()
 {
  */
 local void treat_stdin()
 {
-    if (!force && !list &&
-       isatty(fileno((FILE *)(decompress ? stdin : stdout)))) {
-       /* Do not send compressed data to the terminal or read it from
-        * the terminal. We get here when user invoked the program
-        * without parameters, so be helpful. According to the GNU standards:
-        *
-        *   If there is one behavior you think is most useful when the output
-        *   is to a terminal, and another that you think is most useful when
-        *   the output is a file or a pipe, then it is usually best to make
-        *   the default behavior the one that is useful with output to a
-        *   terminal, and have an option for the other behavior.
-        *
-        * Here we use the --force option to get the other behavior.
-        */
-       fprintf(stderr,
-    "%s: compressed data not %s a terminal. Use -f to force %scompression.\n",
-               program_name, decompress ? "read from" : "written to",
-               decompress ? "de" : "");
-       fprintf (stderr, "For help, type: %s -h\n", program_name);
-       do_exit(ERROR);
+    if (!force && !list
+        && (presume_input_tty
+            || isatty(fileno((FILE *)(decompress ? stdin : stdout))))) {
+        /* Do not send compressed data to the terminal or read it from
+         * the terminal. We get here when user invoked the program
+         * without parameters, so be helpful. According to the GNU standards:
+         *
+         *   If there is one behavior you think is most useful when the output
+         *   is to a terminal, and another that you think is most useful when
+         *   the output is a file or a pipe, then it is usually best to make
+         *   the default behavior the one that is useful with output to a
+         *   terminal, and have an option for the other behavior.
+         *
+         * Here we use the --force option to get the other behavior.
+         */
+        if (! quiet)
+          fprintf (stderr,
+                   ("%s: compressed data not %s a terminal."
+                    " Use -f to force %scompression.\n"
+                    "For help, type: %s -h\n"),
+                   program_name,
+                   decompress ? "read from" : "written to",
+                   decompress ? "de" : "",
+                   program_name);
+        do_exit(ERROR);
     }
 
     if (decompress || !ascii) {
     }
 
     if (decompress || !ascii) {
-       SET_BINARY_MODE(fileno(stdin));
+        SET_BINARY_MODE(fileno(stdin));
     }
     if (!test && !list && (!decompress || !ascii)) {
     }
     if (!test && !list && (!decompress || !ascii)) {
-       SET_BINARY_MODE(fileno(stdout));
+        SET_BINARY_MODE(fileno(stdout));
     }
     strcpy(ifname, "stdin");
     strcpy(ofname, "stdout");
     }
     strcpy(ifname, "stdin");
     strcpy(ofname, "stdout");
@@ -620,23 +650,29 @@ local void treat_stdin()
     /* Get the file's time stamp and size.  */
     if (fstat (fileno (stdin), &istat) != 0)
       {
     /* Get the file's time stamp and size.  */
     if (fstat (fileno (stdin), &istat) != 0)
       {
-       progerror ("standard input");
-       do_exit (ERROR);
+        progerror ("standard input");
+        do_exit (ERROR);
       }
     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
     time_stamp.tv_nsec = -1;
     if (!no_time || list)
       }
     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
     time_stamp.tv_nsec = -1;
     if (!no_time || list)
-      time_stamp = get_stat_mtime (&istat);
+      {
+        if (S_ISREG (istat.st_mode))
+          time_stamp = get_stat_mtime (&istat);
+        else
+          gettime (&time_stamp);
+      }
 
     clear_bufs(); /* clear input and output buffers */
     to_stdout = 1;
     part_nb = 0;
 
     clear_bufs(); /* clear input and output buffers */
     to_stdout = 1;
     part_nb = 0;
+    ifd = fileno(stdin);
 
     if (decompress) {
 
     if (decompress) {
-       method = get_method(ifd);
-       if (method < 0) {
-           do_exit(exit_code); /* error message already emitted */
-       }
+        method = get_method(ifd);
+        if (method < 0) {
+            do_exit(exit_code); /* error message already emitted */
+        }
     }
     if (list) {
         do_list(ifd, method);
     }
     if (list) {
         do_list(ifd, method);
@@ -646,29 +682,29 @@ local void treat_stdin()
     /* Actually do the compression/decompression. Loop over zipped members.
      */
     for (;;) {
     /* Actually do the compression/decompression. Loop over zipped members.
      */
     for (;;) {
-       if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
+        if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
 
 
-       if (input_eof ())
-         break;
+        if (input_eof ())
+          break;
 
 
-       method = get_method(ifd);
-       if (method < 0) return; /* error message already emitted */
-       bytes_out = 0;            /* required for length check */
+        method = get_method(ifd);
+        if (method < 0) return; /* error message already emitted */
+        bytes_out = 0;            /* required for length check */
     }
 
     if (verbose) {
     }
 
     if (verbose) {
-       if (test) {
-           fprintf(stderr, " OK\n");
+        if (test) {
+            fprintf(stderr, " OK\n");
 
 
-       } else if (!decompress) {
-           display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
-           fprintf(stderr, "\n");
+        } else if (!decompress) {
+            display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
+            fprintf(stderr, "\n");
 #ifdef DISPLAY_STDIN_RATIO
 #ifdef DISPLAY_STDIN_RATIO
-       } else {
-           display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
-           fprintf(stderr, "\n");
+        } else {
+            display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
+            fprintf(stderr, "\n");
 #endif
 #endif
-       }
+        }
     }
 }
 
     }
 }
 
@@ -680,10 +716,10 @@ local void treat_file(iname)
 {
     /* Accept "-" as synonym for stdin */
     if (strequ(iname, "-")) {
 {
     /* Accept "-" as synonym for stdin */
     if (strequ(iname, "-")) {
-       int cflag = to_stdout;
-       treat_stdin();
-       to_stdout = cflag;
-       return;
+        int cflag = to_stdout;
+        treat_stdin();
+        to_stdout = cflag;
+        return;
     }
 
     /* Check if the input file is present, set ifname and istat: */
     }
 
     /* Check if the input file is present, set ifname and istat: */
@@ -694,63 +730,63 @@ local void treat_file(iname)
     /* If the input name is that of a directory, recurse or ignore: */
     if (S_ISDIR(istat.st_mode)) {
 #if ! NO_DIR
     /* If the input name is that of a directory, recurse or ignore: */
     if (S_ISDIR(istat.st_mode)) {
 #if ! NO_DIR
-       if (recursive) {
-           treat_dir (ifd, iname);
-           /* Warning: ifname is now garbage */
-           return;
-       }
+        if (recursive) {
+            treat_dir (ifd, iname);
+            /* Warning: ifname is now garbage */
+            return;
+        }
 #endif
 #endif
-       close (ifd);
-       WARN ((stderr, "%s: %s is a directory -- ignored\n",
-              program_name, ifname));
-       return;
+        close (ifd);
+        WARN ((stderr, "%s: %s is a directory -- ignored\n",
+               program_name, ifname));
+        return;
     }
 
     if (! to_stdout)
       {
     }
 
     if (! to_stdout)
       {
-       if (! S_ISREG (istat.st_mode))
-         {
-           WARN ((stderr,
-                  "%s: %s is not a directory or a regular file - ignored\n",
-                  program_name, ifname));
-           close (ifd);
-           return;
-         }
-       if (istat.st_mode & S_ISUID)
-         {
-           WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
-                  program_name, ifname));
-           close (ifd);
-           return;
-         }
-       if (istat.st_mode & S_ISGID)
-         {
-           WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
-                  program_name, ifname));
-           close (ifd);
-           return;
-         }
-
-       if (! force)
-         {
-           if (istat.st_mode & S_ISVTX)
-             {
-               WARN ((stderr,
-                      "%s: %s has the sticky bit set - file ignored\n",
-                      program_name, ifname));
-               close (ifd);
-               return;
-             }
-           if (2 <= istat.st_nlink)
-             {
-               WARN ((stderr, "%s: %s has %lu other link%c -- unchanged\n",
-                      program_name, ifname,
-                      (unsigned long int) istat.st_nlink - 1,
-                      istat.st_nlink == 2 ? ' ' : 's'));
-               close (ifd);
-               return;
-             }
-         }
+        if (! S_ISREG (istat.st_mode))
+          {
+            WARN ((stderr,
+                   "%s: %s is not a directory or a regular file - ignored\n",
+                   program_name, ifname));
+            close (ifd);
+            return;
+          }
+        if (istat.st_mode & S_ISUID)
+          {
+            WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
+                   program_name, ifname));
+            close (ifd);
+            return;
+          }
+        if (istat.st_mode & S_ISGID)
+          {
+            WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
+                   program_name, ifname));
+            close (ifd);
+            return;
+          }
+
+        if (! force)
+          {
+            if (istat.st_mode & S_ISVTX)
+              {
+                WARN ((stderr,
+                       "%s: %s has the sticky bit set - file ignored\n",
+                       program_name, ifname));
+                close (ifd);
+                return;
+              }
+            if (2 <= istat.st_nlink)
+              {
+                WARN ((stderr, "%s: %s has %lu other link%c -- unchanged\n",
+                       program_name, ifname,
+                       (unsigned long int) istat.st_nlink - 1,
+                       istat.st_nlink == 2 ? ' ' : 's'));
+                close (ifd);
+                return;
+              }
+          }
       }
 
     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
       }
 
     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
@@ -762,27 +798,27 @@ local void treat_file(iname)
      * without a valid gzip suffix (check done in make_ofname).
      */
     if (to_stdout && !list && !test) {
      * without a valid gzip suffix (check done in make_ofname).
      */
     if (to_stdout && !list && !test) {
-       strcpy(ofname, "stdout");
+        strcpy(ofname, "stdout");
 
     } else if (make_ofname() != OK) {
 
     } else if (make_ofname() != OK) {
-       close (ifd);
-       return;
+        close (ifd);
+        return;
     }
 
     clear_bufs(); /* clear input and output buffers */
     part_nb = 0;
 
     if (decompress) {
     }
 
     clear_bufs(); /* clear input and output buffers */
     part_nb = 0;
 
     if (decompress) {
-       method = get_method(ifd); /* updates ofname if original given */
-       if (method < 0) {
-           close(ifd);
-           return;               /* error message already emitted */
-       }
+        method = get_method(ifd); /* updates ofname if original given */
+        if (method < 0) {
+            close(ifd);
+            return;               /* error message already emitted */
+        }
     }
     if (list) {
         do_list(ifd, method);
         if (close (ifd) != 0)
     }
     if (list) {
         do_list(ifd, method);
         if (close (ifd) != 0)
-         read_error ();
+          read_error ();
         return;
     }
 
         return;
     }
 
@@ -791,37 +827,37 @@ local void treat_file(iname)
      * a new ofname and save the original name in the compressed file.
      */
     if (to_stdout) {
      * a new ofname and save the original name in the compressed file.
      */
     if (to_stdout) {
-       ofd = fileno(stdout);
-       /* Keep remove_ofname_fd negative.  */
+        ofd = fileno(stdout);
+        /* Keep remove_ofname_fd negative.  */
     } else {
     } else {
-       if (create_outfile() != OK) return;
+        if (create_outfile() != OK) return;
 
 
-       if (!decompress && save_orig_name && !verbose && !quiet) {
-           fprintf(stderr, "%s: %s compressed to %s\n",
-                   program_name, ifname, ofname);
-       }
+        if (!decompress && save_orig_name && !verbose && !quiet) {
+            fprintf(stderr, "%s: %s compressed to %s\n",
+                    program_name, ifname, ofname);
+        }
     }
     /* Keep the name even if not truncated except with --no-name: */
     if (!save_orig_name) save_orig_name = !no_name;
 
     if (verbose) {
     }
     /* Keep the name even if not truncated except with --no-name: */
     if (!save_orig_name) save_orig_name = !no_name;
 
     if (verbose) {
-       fprintf(stderr, "%s:\t", ifname);
+        fprintf(stderr, "%s:\t", ifname);
     }
 
     /* Actually do the compression/decompression. Loop over zipped members.
      */
     for (;;) {
     }
 
     /* Actually do the compression/decompression. Loop over zipped members.
      */
     for (;;) {
-       if ((*work)(ifd, ofd) != OK) {
-           method = -1; /* force cleanup */
-           break;
-       }
+        if ((*work)(ifd, ofd) != OK) {
+            method = -1; /* force cleanup */
+            break;
+        }
 
 
-       if (input_eof ())
-         break;
+        if (input_eof ())
+          break;
 
 
-       method = get_method(ifd);
-       if (method < 0) break;    /* error message already emitted */
-       bytes_out = 0;            /* required for length check */
+        method = get_method(ifd);
+        if (method < 0) break;    /* error message already emitted */
+        bytes_out = 0;            /* required for length check */
     }
 
     if (close (ifd) != 0)
     }
 
     if (close (ifd) != 0)
@@ -829,48 +865,52 @@ local void treat_file(iname)
 
     if (!to_stdout)
       {
 
     if (!to_stdout)
       {
-       sigset_t oldset;
-       int unlink_errno;
-
-       copy_stat (&istat);
-       if (close (ofd) != 0)
-         write_error ();
-
-       sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
-       remove_ofname_fd = -1;
-       unlink_errno = xunlink (ifname) == 0 ? 0 : errno;
-       sigprocmask (SIG_SETMASK, &oldset, NULL);
-
-       if (unlink_errno)
-         {
-           WARN ((stderr, "%s: ", program_name));
-           if (!quiet)
-             {
-               errno = unlink_errno;
-               perror (ifname);
-             }
-         }
+
+        copy_stat (&istat);
+        if (close (ofd) != 0)
+          write_error ();
+
+        if (!keep)
+          {
+            sigset_t oldset;
+            int unlink_errno;
+
+            sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
+            remove_ofname_fd = -1;
+            unlink_errno = xunlink (ifname) == 0 ? 0 : errno;
+            sigprocmask (SIG_SETMASK, &oldset, NULL);
+
+            if (unlink_errno)
+              {
+                WARN ((stderr, "%s: ", program_name));
+                if (!quiet)
+                  {
+                    errno = unlink_errno;
+                    perror (ifname);
+                  }
+              }
+          }
       }
 
     if (method == -1) {
       }
 
     if (method == -1) {
-       if (!to_stdout)
-         remove_output_file ();
-       return;
+        if (!to_stdout)
+          remove_output_file ();
+        return;
     }
 
     /* Display statistics */
     if(verbose) {
     }
 
     /* Display statistics */
     if(verbose) {
-       if (test) {
-           fprintf(stderr, " OK");
-       } else if (decompress) {
-           display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
-       } else {
-           display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
-       }
-       if (!test && !to_stdout) {
-           fprintf(stderr, " -- replaced with %s", ofname);
-       }
-       fprintf(stderr, "\n");
+        if (test) {
+            fprintf(stderr, " OK");
+        } else if (decompress) {
+            display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
+        } else {
+            display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
+        }
+        if (!test && !to_stdout) {
+            fprintf(stderr, " -- replaced with %s", ofname);
+        }
+        fprintf(stderr, "\n");
     }
 }
 
     }
 }
 
@@ -887,7 +927,7 @@ local int create_outfile()
 {
   int name_shortened = 0;
   int flags = (O_WRONLY | O_CREAT | O_EXCL
 {
   int name_shortened = 0;
   int flags = (O_WRONLY | O_CREAT | O_EXCL
-              | (ascii && decompress ? 0 : O_BINARY));
+               | (ascii && decompress ? 0 : O_BINARY));
 
   for (;;)
     {
 
   for (;;)
     {
@@ -900,37 +940,37 @@ local int create_outfile()
       sigprocmask (SIG_SETMASK, &oldset, NULL);
 
       if (0 <= ofd)
       sigprocmask (SIG_SETMASK, &oldset, NULL);
 
       if (0 <= ofd)
-       break;
+        break;
 
       switch (open_errno)
 
       switch (open_errno)
-       {
+        {
 #ifdef ENAMETOOLONG
 #ifdef ENAMETOOLONG
-       case ENAMETOOLONG:
-         shorten_name (ofname);
-         name_shortened = 1;
-         break;
+        case ENAMETOOLONG:
+          shorten_name (ofname);
+          name_shortened = 1;
+          break;
 #endif
 
 #endif
 
-       case EEXIST:
-         if (check_ofname () != OK)
-           {
-             close (ifd);
-             return ERROR;
-           }
-         break;
-
-       default:
-         progerror (ofname);
-         close (ifd);
-         return ERROR;
-       }
+        case EEXIST:
+          if (check_ofname () != OK)
+            {
+              close (ifd);
+              return ERROR;
+            }
+          break;
+
+        default:
+          progerror (ofname);
+          close (ifd);
+          return ERROR;
+        }
     }
 
   if (name_shortened && decompress)
     {
       /* name might be too long if an original name was saved */
       WARN ((stderr, "%s: %s: warning, name truncated\n",
     }
 
   if (name_shortened && decompress)
     {
       /* name might be too long if an original name was saved */
       WARN ((stderr, "%s: %s: warning, name truncated\n",
-            program_name, ofname));
+             program_name, ofname));
     }
 
   return OK;
     }
 
   return OK;
@@ -953,13 +993,13 @@ local char *get_suffix(name)
 {
     int nlen, slen;
     char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
 {
     int nlen, slen;
     char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
-    static char *known_suffixes[] =
+    static char const *known_suffixes[] =
        {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
 #ifdef MAX_EXT_CHARS
           "z",
 #endif
           NULL};
        {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
 #ifdef MAX_EXT_CHARS
           "z",
 #endif
           NULL};
-    char **suf = known_suffixes;
+    char const **suf = known_suffixes;
 
     *suf = z_suffix;
     if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
 
     *suf = z_suffix;
     if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
@@ -967,8 +1007,8 @@ local char *get_suffix(name)
 #ifdef SUFFIX_SEP
     /* strip a version number from the file name */
     {
 #ifdef SUFFIX_SEP
     /* strip a version number from the file name */
     {
-       char *v = strrchr(name, SUFFIX_SEP);
-       if (v != NULL) *v = '\0';
+        char *v = strrchr(name, SUFFIX_SEP);
+        if (v != NULL) *v = '\0';
     }
 #endif
     nlen = strlen(name);
     }
 #endif
     nlen = strlen(name);
@@ -1003,19 +1043,19 @@ open_and_stat (char *name, int flags, mode_t mode, struct stat *st)
   if (!to_stdout && !force)
     {
       if (HAVE_WORKING_O_NOFOLLOW)
   if (!to_stdout && !force)
     {
       if (HAVE_WORKING_O_NOFOLLOW)
-       flags |= O_NOFOLLOW;
+        flags |= O_NOFOLLOW;
       else
       else
-       {
+        {
 #if HAVE_LSTAT || defined lstat
 #if HAVE_LSTAT || defined lstat
-         if (lstat (name, st) != 0)
-           return -1;
-         else if (S_ISLNK (st->st_mode))
-           {
-             errno = ELOOP;
-             return -1;
-           }
+          if (lstat (name, st) != 0)
+            return -1;
+          else if (S_ISLNK (st->st_mode))
+            {
+              errno = ELOOP;
+              return -1;
+            }
 #endif
 #endif
-       }
+        }
     }
 
   fd = OPEN (name, flags, mode);
     }
 
   fd = OPEN (name, flags, mode);
@@ -1044,20 +1084,20 @@ open_input_file (iname, sbuf)
 {
     int ilen;  /* strlen(ifname) */
     int z_suffix_errno = 0;
 {
     int ilen;  /* strlen(ifname) */
     int z_suffix_errno = 0;
-    static char *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
-    char **suf = suffixes;
-    char *s;
+    static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
+    char const **suf = suffixes;
+    char const *s;
 #ifdef NO_MULTIPLE_DOTS
     char *dot; /* pointer to ifname extension, or NULL */
 #endif
     int fd;
     int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
 #ifdef NO_MULTIPLE_DOTS
     char *dot; /* pointer to ifname extension, or NULL */
 #endif
     int fd;
     int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
-                     | (ascii && !decompress ? 0 : O_BINARY));
+                      | (ascii && !decompress ? 0 : O_BINARY));
 
     *suf = z_suffix;
 
     if (sizeof ifname - 1 <= strlen (iname))
 
     *suf = z_suffix;
 
     if (sizeof ifname - 1 <= strlen (iname))
-       goto name_too_long;
+        goto name_too_long;
 
     strcpy(ifname, iname);
 
 
     strcpy(ifname, iname);
 
@@ -1067,16 +1107,16 @@ open_input_file (iname, sbuf)
       return fd;
 
     if (!decompress || errno != ENOENT) {
       return fd;
 
     if (!decompress || errno != ENOENT) {
-       progerror(ifname);
-       return -1;
+        progerror(ifname);
+        return -1;
     }
     /* file.ext doesn't exist, try adding a suffix (after removing any
      * version number for VMS).
      */
     s = get_suffix(ifname);
     if (s != NULL) {
     }
     /* file.ext doesn't exist, try adding a suffix (after removing any
      * version number for VMS).
      */
     s = get_suffix(ifname);
     if (s != NULL) {
-       progerror(ifname); /* ifname already has z suffix and does not exist */
-       return -1;
+        progerror(ifname); /* ifname already has z suffix and does not exist */
+        return -1;
     }
 #ifdef NO_MULTIPLE_DOTS
     dot = strrchr(ifname, '.');
     }
 #ifdef NO_MULTIPLE_DOTS
     dot = strrchr(ifname, '.');
@@ -1090,29 +1130,29 @@ open_input_file (iname, sbuf)
 
     /* Search for all suffixes */
     do {
 
     /* Search for all suffixes */
     do {
-        char *s0 = s = *suf;
+        char const *s0 = s = *suf;
         strcpy (ifname, iname);
 #ifdef NO_MULTIPLE_DOTS
         if (*s == '.') s++;
         if (*dot == '\0') strcpy (dot, ".");
 #endif
 #ifdef MAX_EXT_CHARS
         strcpy (ifname, iname);
 #ifdef NO_MULTIPLE_DOTS
         if (*s == '.') s++;
         if (*dot == '\0') strcpy (dot, ".");
 #endif
 #ifdef MAX_EXT_CHARS
-       if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
-         dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
+        if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
+          dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
 #endif
 #endif
-       if (sizeof ifname <= ilen + strlen (s))
-         goto name_too_long;
+        if (sizeof ifname <= ilen + strlen (s))
+          goto name_too_long;
         strcat(ifname, s);
         strcat(ifname, s);
-       fd = open_and_stat (ifname, open_flags, RW_USER, sbuf);
-       if (0 <= fd)
-         return fd;
-       if (errno != ENOENT)
-         {
-           progerror (ifname);
-           return -1;
-         }
-       if (strequ (s0, z_suffix))
-         z_suffix_errno = errno;
+        fd = open_and_stat (ifname, open_flags, RW_USER, sbuf);
+        if (0 <= fd)
+          return fd;
+        if (errno != ENOENT)
+          {
+            progerror (ifname);
+            return -1;
+          }
+        if (strequ (s0, z_suffix))
+          z_suffix_errno = errno;
     } while (*++suf != NULL);
 
     /* No suffix found, complain using z_suffix: */
     } while (*++suf != NULL);
 
     /* No suffix found, complain using z_suffix: */
@@ -1148,52 +1188,52 @@ local int make_ofname()
     suff = get_suffix(ofname);
 
     if (decompress) {
     suff = get_suffix(ofname);
 
     if (decompress) {
-       if (suff == NULL) {
-           /* With -t or -l, try all files (even without .gz suffix)
-            * except with -r (behave as with just -dr).
+        if (suff == NULL) {
+            /* With -t or -l, try all files (even without .gz suffix)
+             * except with -r (behave as with just -dr).
              */
             if (!recursive && (list || test)) return OK;
 
              */
             if (!recursive && (list || test)) return OK;
 
-           /* Avoid annoying messages with -r */
-           if (verbose || (!recursive && !quiet)) {
-               WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
-                     program_name, ifname));
-           }
-           return WARNING;
-       }
-       /* Make a special case for .tgz and .taz: */
-       strlwr(suff);
-       if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
-           strcpy(suff, ".tar");
-       } else {
-           *suff = '\0'; /* strip the z suffix */
-       }
+            /* Avoid annoying messages with -r */
+            if (verbose || (!recursive && !quiet)) {
+                WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
+                      program_name, ifname));
+            }
+            return WARNING;
+        }
+        /* Make a special case for .tgz and .taz: */
+        strlwr(suff);
+        if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
+            strcpy(suff, ".tar");
+        } else {
+            *suff = '\0'; /* strip the z suffix */
+        }
         /* ofname might be changed later if infile contains an original name */
 
         /* ofname might be changed later if infile contains an original name */
 
-    } else if (suff != NULL) {
-       /* Avoid annoying messages with -r (see treat_dir()) */
-       if (verbose || (!recursive && !quiet)) {
-           /* Don't use WARN, as it affects exit status.  */
-           fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
-                    program_name, ifname, suff);
-       }
-       return WARNING;
+    } else if (suff && ! force) {
+        /* Avoid annoying messages with -r (see treat_dir()) */
+        if (verbose || (!recursive && !quiet)) {
+            /* Don't use WARN, as it affects exit status.  */
+            fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
+                     program_name, ifname, suff);
+        }
+        return WARNING;
     } else {
         save_orig_name = 0;
 
 #ifdef NO_MULTIPLE_DOTS
     } else {
         save_orig_name = 0;
 
 #ifdef NO_MULTIPLE_DOTS
-       suff = strrchr(ofname, '.');
-       if (suff == NULL) {
-           if (sizeof ofname <= strlen (ofname) + 1)
-               goto name_too_long;
+        suff = strrchr(ofname, '.');
+        if (suff == NULL) {
+            if (sizeof ofname <= strlen (ofname) + 1)
+                goto name_too_long;
             strcat(ofname, ".");
 #  ifdef MAX_EXT_CHARS
             strcat(ofname, ".");
 #  ifdef MAX_EXT_CHARS
-           if (strequ(z_suffix, "z")) {
-               if (sizeof ofname <= strlen (ofname) + 2)
-                   goto name_too_long;
-               strcat(ofname, "gz"); /* enough room */
-               return OK;
-           }
+            if (strequ(z_suffix, "z")) {
+                if (sizeof ofname <= strlen (ofname) + 2)
+                    goto name_too_long;
+                strcat(ofname, "gz"); /* enough room */
+                return OK;
+            }
         /* On the Atari and some versions of MSDOS,
          * ENAMETOOLONG does not work correctly.  So we
          * must truncate here.
         /* On the Atari and some versions of MSDOS,
          * ENAMETOOLONG does not work correctly.  So we
          * must truncate here.
@@ -1204,9 +1244,9 @@ local int make_ofname()
 #  endif
         }
 #endif /* NO_MULTIPLE_DOTS */
 #  endif
         }
 #endif /* NO_MULTIPLE_DOTS */
-       if (sizeof ofname <= strlen (ofname) + z_len)
-           goto name_too_long;
-       strcat(ofname, z_suffix);
+        if (sizeof ofname <= strlen (ofname) + z_len)
+            goto name_too_long;
+        strcat(ofname, z_suffix);
 
     } /* decompress ? */
     return OK;
 
     } /* decompress ? */
     return OK;
@@ -1216,6 +1256,25 @@ local int make_ofname()
     return WARNING;
 }
 
     return WARNING;
 }
 
+/* Discard NBYTES input bytes from the input, or up through the next
+   zero byte if NBYTES == (size_t) -1.  If FLAGS say that the header
+   CRC should be computed, update the CRC accordingly.  */
+static void
+discard_input_bytes (nbytes, flags)
+    size_t nbytes;
+    unsigned int flags;
+{
+  while (nbytes != 0)
+    {
+      uch c = get_byte ();
+      if (flags & HEADER_CRC)
+        updcrc (&c, 1);
+      if (nbytes != (size_t) -1)
+        nbytes--;
+      else if (! c)
+        break;
+    }
+}
 
 /* ========================================================================
  * Check the magic number of the input file and update ofname if an
 
 /* ========================================================================
  * Check the magic number of the input file and update ofname if an
@@ -1232,7 +1291,8 @@ local int get_method(in)
     int in;        /* input file descriptor */
 {
     uch flags;     /* compression flags */
     int in;        /* input file descriptor */
 {
     uch flags;     /* compression flags */
-    char magic[2]; /* magic header */
+    uch magic[10]; /* magic header */
+    int imagic0;   /* first magic byte or EOF */
     int imagic1;   /* like magic[1], but can represent EOF */
     ulg stamp;     /* time stamp */
 
     int imagic1;   /* like magic[1], but can represent EOF */
     ulg stamp;     /* time stamp */
 
@@ -1240,14 +1300,21 @@ local int get_method(in)
      * premature end of file: use try_byte instead of get_byte.
      */
     if (force && to_stdout) {
      * premature end of file: use try_byte instead of get_byte.
      */
     if (force && to_stdout) {
-       magic[0] = (char)try_byte();
-       imagic1 = try_byte ();
-       magic[1] = (char) imagic1;
-       /* If try_byte returned EOF, magic[1] == (char) EOF.  */
+        imagic0 = try_byte();
+        magic[0] = imagic0;
+        imagic1 = try_byte ();
+        magic[1] = imagic1;
+        /* If try_byte returned EOF, magic[1] == (char) EOF.  */
     } else {
     } else {
-       magic[0] = (char)get_byte();
-       magic[1] = (char)get_byte();
-       imagic1 = 0; /* avoid lint warning */
+        magic[0] = get_byte ();
+        imagic0 = 0;
+        if (magic[0]) {
+            magic[1] = get_byte ();
+            imagic1 = 0; /* avoid lint warning */
+        } else {
+            imagic1 = try_byte ();
+            magic[1] = imagic1;
+        }
     }
     method = -1;                 /* unknown yet */
     part_nb++;                   /* number of parts in gzip file */
     }
     method = -1;                 /* unknown yet */
     part_nb++;                   /* number of parts in gzip file */
@@ -1258,160 +1325,183 @@ local int get_method(in)
     if (memcmp(magic, GZIP_MAGIC, 2) == 0
         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
 
     if (memcmp(magic, GZIP_MAGIC, 2) == 0
         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
 
-       method = (int)get_byte();
-       if (method != DEFLATED) {
-           fprintf(stderr,
-                   "%s: %s: unknown method %d -- not supported\n",
-                   program_name, ifname, method);
-           exit_code = ERROR;
-           return -1;
-       }
-       work = unzip;
-       flags  = (uch)get_byte();
-
-       if ((flags & ENCRYPTED) != 0) {
-           fprintf(stderr,
-                   "%s: %s is encrypted -- not supported\n",
-                   program_name, ifname);
-           exit_code = ERROR;
-           return -1;
-       }
-       if ((flags & CONTINUATION) != 0) {
-           fprintf(stderr,
-                   "%s: %s is a a multi-part gzip file -- not supported\n",
-                   program_name, ifname);
-           exit_code = ERROR;
-           if (force <= 1) return -1;
-       }
-       if ((flags & RESERVED) != 0) {
-           fprintf(stderr,
-                   "%s: %s has flags 0x%x -- not supported\n",
-                   program_name, ifname, flags);
-           exit_code = ERROR;
-           if (force <= 1) return -1;
-       }
-       stamp  = (ulg)get_byte();
-       stamp |= ((ulg)get_byte()) << 8;
-       stamp |= ((ulg)get_byte()) << 16;
-       stamp |= ((ulg)get_byte()) << 24;
-       if (stamp != 0 && !no_time)
-         {
-           time_stamp.tv_sec = stamp;
-           time_stamp.tv_nsec = 0;
-         }
-
-       (void)get_byte();  /* Ignore extra flags for the moment */
-       (void)get_byte();  /* Ignore OS type for the moment */
-
-       if ((flags & CONTINUATION) != 0) {
-           unsigned part = (unsigned)get_byte();
-           part |= ((unsigned)get_byte())<<8;
-           if (verbose) {
-               fprintf(stderr,"%s: %s: part number %u\n",
-                       program_name, ifname, part);
-           }
-       }
-       if ((flags & EXTRA_FIELD) != 0) {
-           unsigned len = (unsigned)get_byte();
-           len |= ((unsigned)get_byte())<<8;
-           if (verbose) {
-               fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
-                       program_name, ifname, len);
-           }
-           while (len--) (void)get_byte();
-       }
-
-       /* Get original file name if it was truncated */
-       if ((flags & ORIG_NAME) != 0) {
-           if (no_name || (to_stdout && !list) || part_nb > 1) {
-               /* Discard the old name */
-               char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
-               do {c=get_byte();} while (c != 0);
-           } else {
-               /* Copy the base name. Keep a directory prefix intact. */
+        method = (int)get_byte();
+        if (method != DEFLATED) {
+            fprintf(stderr,
+                    "%s: %s: unknown method %d -- not supported\n",
+                    program_name, ifname, method);
+            exit_code = ERROR;
+            return -1;
+        }
+        work = unzip;
+        flags  = (uch)get_byte();
+
+        if ((flags & ENCRYPTED) != 0) {
+            fprintf(stderr,
+                    "%s: %s is encrypted -- not supported\n",
+                    program_name, ifname);
+            exit_code = ERROR;
+            return -1;
+        }
+        if ((flags & RESERVED) != 0) {
+            fprintf(stderr,
+                    "%s: %s has flags 0x%x -- not supported\n",
+                    program_name, ifname, flags);
+            exit_code = ERROR;
+            if (force <= 1) return -1;
+        }
+        stamp  = (ulg)get_byte();
+        stamp |= ((ulg)get_byte()) << 8;
+        stamp |= ((ulg)get_byte()) << 16;
+        stamp |= ((ulg)get_byte()) << 24;
+        if (stamp != 0 && !no_time)
+          {
+            time_stamp.tv_sec = stamp;
+            time_stamp.tv_nsec = 0;
+          }
+
+        magic[8] = get_byte ();  /* Ignore extra flags.  */
+        magic[9] = get_byte ();  /* Ignore OS type.  */
+
+        if (flags & HEADER_CRC)
+          {
+            magic[2] = DEFLATED;
+            magic[3] = flags;
+            magic[4] = stamp & 0xff;
+            magic[5] = (stamp >> 8) & 0xff;
+            magic[6] = (stamp >> 16) & 0xff;
+            magic[7] = stamp >> 24;
+            updcrc (NULL, 0);
+            updcrc (magic, 10);
+          }
+
+        if ((flags & EXTRA_FIELD) != 0) {
+            uch lenbuf[2];
+            unsigned int len = lenbuf[0] = get_byte ();
+            len |= (lenbuf[1] = get_byte ()) << 8;
+            if (verbose) {
+                fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
+                        program_name, ifname, len);
+            }
+            if (flags & HEADER_CRC)
+              updcrc (lenbuf, 2);
+            discard_input_bytes (len, flags);
+        }
+
+        /* Get original file name if it was truncated */
+        if ((flags & ORIG_NAME) != 0) {
+            if (no_name || (to_stdout && !list) || part_nb > 1) {
+                /* Discard the old name */
+                discard_input_bytes (-1, flags);
+            } else {
+                /* Copy the base name. Keep a directory prefix intact. */
                 char *p = gzip_base_name (ofname);
                 char *base = p;
                 char *p = gzip_base_name (ofname);
                 char *base = p;
-               for (;;) {
-                   *p = (char)get_char();
-                   if (*p++ == '\0') break;
-                   if (p >= ofname+sizeof(ofname)) {
-                       gzip_error ("corrupted input -- file name too large");
-                   }
-               }
-               p = gzip_base_name (base);
-               memmove (base, p, strlen (p) + 1);
+                for (;;) {
+                    *p = (char) get_byte ();
+                    if (*p++ == '\0') break;
+                    if (p >= ofname+sizeof(ofname)) {
+                        gzip_error ("corrupted input -- file name too large");
+                    }
+                }
+                if (flags & HEADER_CRC)
+                  updcrc ((uch *) base, p - base);
+                p = gzip_base_name (base);
+                memmove (base, p, strlen (p) + 1);
                 /* If necessary, adapt the name to local OS conventions: */
                 if (!list) {
                    MAKE_LEGAL_NAME(base);
                 /* If necessary, adapt the name to local OS conventions: */
                 if (!list) {
                    MAKE_LEGAL_NAME(base);
-                  if (base) list=0; /* avoid warning about unused variable */
+                   if (base) list=0; /* avoid warning about unused variable */
                 }
                 }
-           } /* no_name || to_stdout */
-       } /* ORIG_NAME */
+            } /* no_name || to_stdout */
+        } /* ORIG_NAME */
+
+        /* Discard file comment if any */
+        if ((flags & COMMENT) != 0) {
+            discard_input_bytes (-1, flags);
+        }
 
 
-       /* Discard file comment if any */
-       if ((flags & COMMENT) != 0) {
-           while (get_char() != 0) /* null */ ;
-       }
-       if (part_nb == 1) {
-           header_bytes = inptr + 2*sizeof(long); /* include crc and size */
-       }
+        if (flags & HEADER_CRC)
+          {
+            unsigned int crc16 = updcrc (magic, 0) & 0xffff;
+            unsigned int header16 = get_byte ();
+            header16 |= ((unsigned int) get_byte ()) << 8;
+            if (header16 != crc16)
+              {
+                fprintf (stderr,
+                         "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
+                         program_name, ifname, header16, crc16);
+                exit_code = ERROR;
+                if (force <= 1)
+                  return -1;
+              }
+          }
+
+        if (part_nb == 1) {
+            header_bytes = inptr + 2*4; /* include crc and size */
+        }
 
     } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
 
     } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
-           && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
-       /* To simplify the code, we support a zip file when alone only.
+            && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
+        /* To simplify the code, we support a zip file when alone only.
          * We are thus guaranteed that the entire local header fits in inbuf.
          */
         inptr = 0;
          * We are thus guaranteed that the entire local header fits in inbuf.
          */
         inptr = 0;
-       work = unzip;
-       if (check_zipfile(in) != OK) return -1;
-       /* check_zipfile may get ofname from the local header */
-       last_member = 1;
+        work = unzip;
+        if (check_zipfile(in) != OK) return -1;
+        /* check_zipfile may get ofname from the local header */
+        last_member = 1;
 
     } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
 
     } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
-       work = unpack;
-       method = PACKED;
+        work = unpack;
+        method = PACKED;
 
     } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
 
     } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
-       work = unlzw;
-       method = COMPRESSED;
-       last_member = 1;
+        work = unlzw;
+        method = COMPRESSED;
+        last_member = 1;
 
     } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
 
     } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
-       work = unlzh;
-       method = LZHED;
-       last_member = 1;
+        work = unlzh;
+        method = LZHED;
+        last_member = 1;
 
     } else if (force && to_stdout && !list) { /* pass input unchanged */
 
     } else if (force && to_stdout && !list) { /* pass input unchanged */
-       method = STORED;
-       work = copy;
-        inptr = 0;
-       last_member = 1;
+        method = STORED;
+        work = copy;
+        if (imagic1 != EOF)
+            inptr--;
+        last_member = 1;
+        if (imagic0 != EOF) {
+            write_buf(fileno(stdout), magic, 1);
+            bytes_out++;
+        }
     }
     if (method >= 0) return method;
 
     if (part_nb == 1) {
     }
     if (method >= 0) return method;
 
     if (part_nb == 1) {
-       fprintf (stderr, "\n%s: %s: not in gzip format\n",
-                program_name, ifname);
-       exit_code = ERROR;
-       return -1;
+        fprintf (stderr, "\n%s: %s: not in gzip format\n",
+                 program_name, ifname);
+        exit_code = ERROR;
+        return -1;
     } else {
     } else {
-       if (magic[0] == 0)
-         {
-           int inbyte;
-           for (inbyte = imagic1;  inbyte == 0;  inbyte = try_byte ())
-             continue;
-           if (inbyte == EOF)
-             {
-               if (verbose)
-                 WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
-                        program_name, ifname));
-               return -3;
-             }
-         }
-
-       WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
-             program_name, ifname));
-       return -2;
+        if (magic[0] == 0)
+          {
+            int inbyte;
+            for (inbyte = imagic1;  inbyte == 0;  inbyte = try_byte ())
+              continue;
+            if (inbyte == EOF)
+              {
+                if (verbose)
+                  WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
+                         program_name, ifname));
+                return -3;
+              }
+          }
+
+        WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
+              program_name, ifname));
+        return -2;
     }
 }
 
     }
 }
 
@@ -1426,7 +1516,7 @@ local void do_list(ifd, method)
 {
     ulg crc;  /* original crc */
     static int first_time = 1;
 {
     ulg crc;  /* original crc */
     static int first_time = 1;
-    static char* methods[MAX_METHODS] = {
+    static char const *const methods[MAX_METHODS] = {
         "store",  /* 0 */
         "compr",  /* 1 */
         "pack ",  /* 2 */
         "store",  /* 0 */
         "compr",  /* 1 */
         "pack ",  /* 2 */
@@ -1437,43 +1527,42 @@ local void do_list(ifd, method)
     off_t o;
 
     for (o = OFF_T_MAX;  9 < o;  o /= 10) {
     off_t o;
 
     for (o = OFF_T_MAX;  9 < o;  o /= 10) {
-       positive_off_t_width++;
+        positive_off_t_width++;
     }
 
     if (first_time && method >= 0) {
     }
 
     if (first_time && method >= 0) {
-       first_time = 0;
-       if (verbose)  {
-           printf("method  crc     date  time  ");
-       }
-       if (!quiet) {
-           printf("%*.*s %*.*s  ratio uncompressed_name\n",
-                  positive_off_t_width, positive_off_t_width, "compressed",
-                  positive_off_t_width, positive_off_t_width, "uncompressed");
-       }
+        first_time = 0;
+        if (verbose)  {
+            printf("method  crc     date  time  ");
+        }
+        if (!quiet) {
+            printf("%*.*s %*.*s  ratio uncompressed_name\n",
+                   positive_off_t_width, positive_off_t_width, "compressed",
+                   positive_off_t_width, positive_off_t_width, "uncompressed");
+        }
     } else if (method < 0) {
     } else if (method < 0) {
-       if (total_in <= 0 || total_out <= 0) return;
-       if (verbose) {
-           printf("                            ");
-       }
-       if (verbose || !quiet) {
-           fprint_off(stdout, total_in, positive_off_t_width);
-           printf(" ");
-           fprint_off(stdout, total_out, positive_off_t_width);
-           printf(" ");
-       }
-       display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
-       /* header_bytes is not meaningful but used to ensure the same
-        * ratio if there is a single file.
-        */
-       printf(" (totals)\n");
-       return;
+        if (total_in <= 0 || total_out <= 0) return;
+        if (verbose) {
+            printf("                            ");
+        }
+        if (verbose || !quiet) {
+            fprint_off(stdout, total_in, positive_off_t_width);
+            printf(" ");
+            fprint_off(stdout, total_out, positive_off_t_width);
+            printf(" ");
+        }
+        display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
+        /* header_bytes is not meaningful but used to ensure the same
+         * ratio if there is a single file.
+         */
+        printf(" (totals)\n");
+        return;
     }
     crc = (ulg)~0; /* unknown */
     bytes_out = -1L;
     bytes_in = ifile_size;
 
     }
     crc = (ulg)~0; /* unknown */
     bytes_out = -1L;
     bytes_in = ifile_size;
 
-#if RECORD_IO == 0
-    if (method == DEFLATED && !last_member) {
+    if (!RECORD_IO && method == DEFLATED && !last_member) {
         /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
          * If the lseek fails, we could use read() to get to the end, but
          * --list is used to get quick results.
         /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
          * If the lseek fails, we could use read() to get to the end, but
          * --list is used to get quick results.
@@ -1488,37 +1577,37 @@ local void do_list(ifd, method)
                 read_error();
             }
             crc       = LG(buf);
                 read_error();
             }
             crc       = LG(buf);
-           bytes_out = LG(buf+4);
-       }
+            bytes_out = LG(buf+4);
+        }
     }
     }
-#endif /* RECORD_IO */
+
     if (verbose)
       {
     if (verbose)
       {
-       struct tm *tm = localtime (&time_stamp.tv_sec);
-       printf ("%5s %08lx ", methods[method], crc);
-       if (tm)
-         printf ("%s%3d %02d:%02d ",
-                 ("Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"
-                  + 4 * tm->tm_mon),
-                 tm->tm_mday, tm->tm_hour, tm->tm_min);
-       else
-         printf ("??? ?? ??:?? ");
+        struct tm *tm = localtime (&time_stamp.tv_sec);
+        printf ("%5s %08lx ", methods[method], crc);
+        if (tm)
+          printf ("%s%3d %02d:%02d ",
+                  ("Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"
+                   + 4 * tm->tm_mon),
+                  tm->tm_mday, tm->tm_hour, tm->tm_min);
+        else
+          printf ("??? ?? ??:?? ");
       }
     fprint_off(stdout, bytes_in, positive_off_t_width);
     printf(" ");
     fprint_off(stdout, bytes_out, positive_off_t_width);
     printf(" ");
     if (bytes_in  == -1L) {
       }
     fprint_off(stdout, bytes_in, positive_off_t_width);
     printf(" ");
     fprint_off(stdout, bytes_out, positive_off_t_width);
     printf(" ");
     if (bytes_in  == -1L) {
-       total_in = -1L;
-       bytes_in = bytes_out = header_bytes = 0;
+        total_in = -1L;
+        bytes_in = bytes_out = header_bytes = 0;
     } else if (total_in >= 0) {
     } else if (total_in >= 0) {
-       total_in  += bytes_in;
+        total_in  += bytes_in;
     }
     if (bytes_out == -1L) {
     }
     if (bytes_out == -1L) {
-       total_out = -1L;
-       bytes_in = bytes_out = header_bytes = 0;
+        total_out = -1L;
+        bytes_in = bytes_out = header_bytes = 0;
     } else if (total_out >= 0) {
     } else if (total_out >= 0) {
-       total_out += bytes_out;
+        total_out += bytes_out;
     }
     display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
     printf(" %s\n", ofname);
     }
     display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
     printf(" %s\n", ofname);
@@ -1544,10 +1633,10 @@ local void shorten_name(name)
 
     len = strlen(name);
     if (decompress) {
 
     len = strlen(name);
     if (decompress) {
-       if (len <= 1)
-         gzip_error ("name too short");
-       name[len-1] = '\0';
-       return;
+        if (len <= 1)
+          gzip_error ("name too short");
+        name[len-1] = '\0';
+        return;
     }
     p = get_suffix(name);
     if (! p)
     }
     p = get_suffix(name);
     if (! p)
@@ -1557,33 +1646,33 @@ local void shorten_name(name)
 
     /* compress 1234567890.tar to 1234567890.tgz */
     if (len > 4 && strequ(p-4, ".tar")) {
 
     /* compress 1234567890.tar to 1234567890.tgz */
     if (len > 4 && strequ(p-4, ".tar")) {
-       strcpy(p-4, ".tgz");
-       return;
+        strcpy(p-4, ".tgz");
+        return;
     }
     /* Try keeping short extensions intact:
      * 1234.678.012.gz -> 123.678.012.gz
      */
     do {
     }
     /* Try keeping short extensions intact:
      * 1234.678.012.gz -> 123.678.012.gz
      */
     do {
-       p = strrchr(name, PATH_SEP);
-       p = p ? p+1 : name;
-       while (*p) {
-           plen = strcspn(p, PART_SEP);
-           p += plen;
-           if (plen > min_part) trunc = p-1;
-           if (*p) p++;
-       }
+        p = strrchr(name, PATH_SEP);
+        p = p ? p+1 : name;
+        while (*p) {
+            plen = strcspn(p, PART_SEP);
+            p += plen;
+            if (plen > min_part) trunc = p-1;
+            if (*p) p++;
+        }
     } while (trunc == NULL && --min_part != 0);
 
     if (trunc != NULL) {
     } while (trunc == NULL && --min_part != 0);
 
     if (trunc != NULL) {
-       do {
-           trunc[0] = trunc[1];
-       } while (*trunc++);
-       trunc--;
+        do {
+            trunc[0] = trunc[1];
+        } while (*trunc++);
+        trunc--;
     } else {
     } else {
-       trunc = strrchr(name, PART_SEP[0]);
-       if (!trunc)
-         gzip_error ("internal error in shorten_name");
-       if (trunc[1] == '\0') trunc--; /* force truncation */
+        trunc = strrchr(name, PART_SEP[0]);
+        if (!trunc)
+          gzip_error ("internal error in shorten_name");
+        if (trunc[1] == '\0') trunc--; /* force truncation */
     }
     strcpy(trunc, z_suffix);
 }
     }
     strcpy(trunc, z_suffix);
 }
@@ -1596,22 +1685,22 @@ local int check_ofname()
 {
     /* Ask permission to overwrite the existing file */
     if (!force) {
 {
     /* Ask permission to overwrite the existing file */
     if (!force) {
-       int ok = 0;
-       fprintf (stderr, "%s: %s already exists;", program_name, ofname);
-       if (foreground && isatty(fileno(stdin))) {
-           fprintf(stderr, " do you wish to overwrite (y or n)? ");
-           fflush(stderr);
-           ok = yesno();
-       }
-       if (!ok) {
-           fprintf(stderr, "\tnot overwritten\n");
-           if (exit_code == OK) exit_code = WARNING;
-           return ERROR;
-       }
+        int ok = 0;
+        fprintf (stderr, "%s: %s already exists;", program_name, ofname);
+        if (foreground && (presume_input_tty || isatty(fileno(stdin)))) {
+            fprintf(stderr, " do you wish to overwrite (y or n)? ");
+            fflush(stderr);
+            ok = yesno();
+        }
+        if (!ok) {
+            fprintf(stderr, "\tnot overwritten\n");
+            if (exit_code == OK) exit_code = WARNING;
+            return ERROR;
+        }
     }
     if (xunlink (ofname)) {
     }
     if (xunlink (ofname)) {
-       progerror(ofname);
-       return ERROR;
+        progerror(ofname);
+        return ERROR;
     }
     return OK;
 }
     }
     return OK;
 }
@@ -1633,32 +1722,33 @@ local void copy_stat(ifstat)
     timespec[1] = get_stat_mtime (ifstat);
 
     if (decompress && 0 <= time_stamp.tv_nsec
     timespec[1] = get_stat_mtime (ifstat);
 
     if (decompress && 0 <= time_stamp.tv_nsec
-       && ! (timespec[1].tv_sec == time_stamp.tv_sec
-             && timespec[1].tv_nsec == time_stamp.tv_nsec))
+        && ! (timespec[1].tv_sec == time_stamp.tv_sec
+              && timespec[1].tv_nsec == time_stamp.tv_nsec))
       {
       {
-       timespec[1] = time_stamp;
-       if (verbose > 1) {
-           fprintf(stderr, "%s: time stamp restored\n", ofname);
-       }
+        timespec[1] = time_stamp;
+        if (verbose > 1) {
+            fprintf(stderr, "%s: time stamp restored\n", ofname);
+        }
       }
 
       }
 
-    if (futimens (ofd, ofname, timespec) != 0)
+    if (fdutimens (ofd, ofname, timespec) != 0)
       {
       {
-       int e = errno;
-       WARN ((stderr, "%s: ", program_name));
-       if (!quiet)
-         {
-           errno = e;
-           perror (ofname);
-         }
+        int e = errno;
+        WARN ((stderr, "%s: ", program_name));
+        if (!quiet)
+          {
+            errno = e;
+            perror (ofname);
+          }
       }
 #endif
 
 #ifndef NO_CHOWN
       }
 #endif
 
 #ifndef NO_CHOWN
+    /* Copy ownership */
 # if HAVE_FCHOWN
 # if HAVE_FCHOWN
-    fchown (ofd, ifstat->st_uid, ifstat->st_gid);  /* Copy ownership */
+    ignore_value (fchown (ofd, ifstat->st_uid, ifstat->st_gid));
 # elif HAVE_CHOWN
 # elif HAVE_CHOWN
-    chown(ofname, ifstat->st_uid, ifstat->st_gid);  /* Copy ownership */
+    ignore_value (chown (ofname, ifstat->st_uid, ifstat->st_gid));
 # endif
 #endif
 
 # endif
 #endif
 
@@ -1669,89 +1759,72 @@ local void copy_stat(ifstat)
     r = chmod (ofname, mode);
 #endif
     if (r != 0) {
     r = chmod (ofname, mode);
 #endif
     if (r != 0) {
-       int e = errno;
-       WARN ((stderr, "%s: ", program_name));
-       if (!quiet) {
-           errno = e;
-           perror(ofname);
-       }
+        int e = errno;
+        WARN ((stderr, "%s: ", program_name));
+        if (!quiet) {
+            errno = e;
+            perror(ofname);
+        }
     }
 }
 
 #if ! NO_DIR
 
 /* ========================================================================
     }
 }
 
 #if ! NO_DIR
 
 /* ========================================================================
- * Recurse through the given directory. This code is taken from ncompress.
+ * Recurse through the given directory.
  */
 local void treat_dir (fd, dir)
     int fd;
     char *dir;
 {
  */
 local void treat_dir (fd, dir)
     int fd;
     char *dir;
 {
-    struct dirent *dp;
     DIR      *dirp;
     char     nbuf[MAX_PATH_LEN];
     DIR      *dirp;
     char     nbuf[MAX_PATH_LEN];
-    int      len;
+    char *entries;
+    char const *entry;
+    size_t entrylen;
 
 
-#if HAVE_FDOPENDIR
     dirp = fdopendir (fd);
     dirp = fdopendir (fd);
-#else
-    close (fd);
-    dirp = opendir(dir);
-#endif
 
     if (dirp == NULL) {
 
     if (dirp == NULL) {
-       progerror(dir);
-#if HAVE_FDOPENDIR
-       close (fd);
-#endif
-       return ;
+        progerror(dir);
+        close (fd);
+        return ;
     }
     }
-    /*
-     ** WARNING: the following algorithm could occasionally cause
-     ** compress to produce error warnings of the form "<filename>.gz
-     ** already has .gz suffix - ignored". This occurs when the
-     ** .gz output file is inserted into the directory below
-     ** readdir's current pointer.
-     ** These warnings are harmless but annoying, so they are suppressed
-     ** with option -r (except when -v is on). An alternative
-     ** to allowing this would be to store the entire directory
-     ** list in memory, then compress the entries in the stored
-     ** list. Given the depth-first recursive algorithm used here,
-     ** this could use up a tremendous amount of memory. I don't
-     ** think it's worth it. -- Dave Mack
-     ** (An other alternative might be two passes to avoid depth-first.)
-     */
 
 
-    while ((errno = 0, dp = readdir(dirp)) != NULL) {
+    entries = streamsavedir (dirp);
+    if (! entries)
+      progerror (dir);
+    if (closedir (dirp) != 0)
+      progerror (dir);
+    if (! entries)
+      return;
 
 
-       if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
-           continue;
-       }
-       len = strlen(dir);
-       if (len + _D_EXACT_NAMLEN (dp) + 1 < MAX_PATH_LEN - 1) {
-           strcpy(nbuf,dir);
-           if (len != 0 /* dir = "" means current dir on Amiga */
+    for (entry = entries; *entry; entry += entrylen + 1) {
+        size_t len = strlen (dir);
+        entrylen = strlen (entry);
+        if (strequ (entry, ".") || strequ (entry, ".."))
+          continue;
+        if (len + entrylen < MAX_PATH_LEN - 2) {
+            strcpy(nbuf,dir);
+            if (len != 0 /* dir = "" means current dir on Amiga */
 #ifdef PATH_SEP2
 #ifdef PATH_SEP2
-               && dir[len-1] != PATH_SEP2
+                && dir[len-1] != PATH_SEP2
 #endif
 #ifdef PATH_SEP3
 #endif
 #ifdef PATH_SEP3
-               && dir[len-1] != PATH_SEP3
+                && dir[len-1] != PATH_SEP3
 #endif
 #endif
-           ) {
-               nbuf[len++] = PATH_SEP;
-           }
-           strcpy(nbuf+len, dp->d_name);
-           treat_file(nbuf);
-       } else {
-           fprintf(stderr,"%s: %s/%s: pathname too long\n",
-                   program_name, dir, dp->d_name);
-           exit_code = ERROR;
-       }
+            ) {
+                nbuf[len++] = PATH_SEP;
+            }
+            strcpy (nbuf + len, entry);
+            treat_file(nbuf);
+        } else {
+            fprintf(stderr,"%s: %s/%s: pathname too long\n",
+                    program_name, dir, entry);
+            exit_code = ERROR;
+        }
     }
     }
-    if (errno != 0)
-       progerror(dir);
-    if (CLOSEDIR(dirp) != 0)
-       progerror(dir);
+    free (entries);
 }
 #endif /* ! NO_DIR */
 
 }
 #endif /* ! NO_DIR */
 
@@ -1760,30 +1833,7 @@ local void treat_dir (fd, dir)
 static void
 install_signal_handlers ()
 {
 static void
 install_signal_handlers ()
 {
-  static int sig[] =
-    {
-      /* SIGINT must be first, as 'foreground' depends on it.  */
-      SIGINT
-
-#ifdef SIGHUP
-      , SIGHUP
-#endif
-#ifdef SIGPIPE
-      , SIGPIPE
-#else
-# define SIGPIPE 0
-#endif
-#ifdef SIGTERM
-      , SIGTERM
-#endif
-#ifdef SIGXCPU
-      , SIGXCPU
-#endif
-#ifdef SIGXFSZ
-      , SIGXFSZ
-#endif
-    };
-  int nsigs = sizeof sig / sizeof sig[0];
+  int nsigs = sizeof handled_sig / sizeof handled_sig[0];
   int i;
 
 #if SA_NOCLDSTOP
   int i;
 
 #if SA_NOCLDSTOP
@@ -1792,9 +1842,9 @@ install_signal_handlers ()
   sigemptyset (&caught_signals);
   for (i = 0; i < nsigs; i++)
     {
   sigemptyset (&caught_signals);
   for (i = 0; i < nsigs; i++)
     {
-      sigaction (sig[i], NULL, &act);
+      sigaction (handled_sig[i], NULL, &act);
       if (act.sa_handler != SIG_IGN)
       if (act.sa_handler != SIG_IGN)
-       sigaddset (&caught_signals, sig[i]);
+        sigaddset (&caught_signals, handled_sig[i]);
     }
 
   act.sa_handler = abort_gzip_signal;
     }
 
   act.sa_handler = abort_gzip_signal;
@@ -1802,20 +1852,20 @@ install_signal_handlers ()
   act.sa_flags = 0;
 
   for (i = 0; i < nsigs; i++)
   act.sa_flags = 0;
 
   for (i = 0; i < nsigs; i++)
-    if (sigismember (&caught_signals, sig[i]))
+    if (sigismember (&caught_signals, handled_sig[i]))
       {
       {
-       if (i == 0)
-         foreground = 1;
-       sigaction (sig[i], &act, NULL);
+        if (i == 0)
+          foreground = 1;
+        sigaction (handled_sig[i], &act, NULL);
       }
 #else
   for (i = 0; i < nsigs; i++)
       }
 #else
   for (i = 0; i < nsigs; i++)
-    if (signal (sig[i], SIG_IGN) != SIG_IGN)
+    if (signal (handled_sig[i], SIG_IGN) != SIG_IGN)
       {
       {
-       if (i == 0)
-         foreground = 1;
-       signal (sig[i], abort_gzip_signal);
-       siginterrupt (sig[i], 1);
+        if (i == 0)
+          foreground = 1;
+        signal (handled_sig[i], abort_gzip_signal);
+        siginterrupt (handled_sig[i], 1);
       }
 #endif
 }
       }
 #endif
 }
@@ -1830,8 +1880,10 @@ local void do_exit(exitcode)
 
     if (in_exit) exit(exitcode);
     in_exit = 1;
 
     if (in_exit) exit(exitcode);
     in_exit = 1;
-    if (env != NULL)  free(env),  env  = NULL;
-    if (args != NULL) free((char*)args), args = NULL;
+    free(env);
+    env  = NULL;
+    free(args);
+    args = NULL;
     FREE(inbuf);
     FREE(outbuf);
     FREE(d_buf);
     FREE(inbuf);
     FREE(outbuf);
     FREE(d_buf);