1 /*
   2  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
   7 /*        All Rights Reserved   */
   8 
   9 
  10 /*
  11  * Copyright (c) 1986 Regents of the University of California.
  12  * All rights reserved.  The Berkeley software License Agreement
  13  * specifies the terms and conditions for redistribution.
  14  */
  15 
  16 /*
  17  * Copyright (c) 2018, Joyent, Inc.
  18  */
  19 
  20 /*
  21  * Compress - data compression program
  22  */
  23 #define min(a, b)       ((a > b) ? b : a)
  24 
  25 /*
  26  * machine variants which require cc -Dmachine:  pdp11, z8000, pcxt
  27  */
  28 
  29 /*
  30  * Set USERMEM to the maximum amount of physical user memory available
  31  * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  32  * for compression.
  33  *
  34  * SACREDMEM is the amount of physical memory saved for others; compress
  35  * will hog the rest.
  36  */
  37 #ifndef SACREDMEM
  38 #define SACREDMEM       0
  39 #endif
  40 
  41 #ifndef USERMEM
  42 #define USERMEM         450000  /* default user memory */
  43 #endif
  44 
  45 #ifdef USERMEM
  46 #if USERMEM >= (433484+SACREDMEM)
  47 #define PBITS   16
  48 #else
  49 #if USERMEM >= (229600+SACREDMEM)
  50 #define PBITS   15
  51 #else
  52 #if USERMEM >= (127536+SACREDMEM)
  53 #define PBITS   14
  54 #else
  55 #if USERMEM >= (73464+SACREDMEM)
  56 #define PBITS   13
  57 #else
  58 #define PBITS   12
  59 #endif
  60 #endif
  61 #endif
  62 #endif
  63 #undef USERMEM
  64 #endif /* USERMEM */
  65 
  66 #ifdef PBITS            /* Preferred BITS for this memory size */
  67 #ifndef BITS
  68 #define BITS PBITS
  69 #endif /* BITS */
  70 #endif /* PBITS */
  71 
  72 #if BITS == 16
  73 #define HSIZE   69001           /* 95% occupancy */
  74 #endif
  75 #if BITS == 15
  76 #define HSIZE   35023           /* 94% occupancy */
  77 #endif
  78 #if BITS == 14
  79 #define HSIZE   18013           /* 91% occupancy */
  80 #endif
  81 #if BITS == 13
  82 #define HSIZE   9001            /* 91% occupancy */
  83 #endif
  84 #if BITS <= 12
  85 #define HSIZE   5003            /* 80% occupancy */
  86 #endif
  87 
  88 #define OUTSTACKSIZE    (2<<BITS)
  89 
  90 /*
  91  * a code_int must be able to hold 2**BITS values of type int, and also -1
  92  */
  93 #if BITS > 15
  94 typedef long int        code_int;
  95 #else
  96 typedef int             code_int;
  97 #endif
  98 
  99 typedef long int        count_int;
 100 typedef long long       count_long;
 101 
 102 typedef unsigned char   char_type;
 103 
 104 static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
 105 
 106 /* Defines for third byte of header */
 107 #define BIT_MASK        0x1f
 108 #define BLOCK_MASK      0x80
 109 /*
 110  * Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
 111  * a fourth header byte(for expansion).
 112  */
 113 #define INIT_BITS 9                     /* initial number of bits/code */
 114 
 115 /*
 116  * compress.c - File compression ala IEEE Computer, June 1984.
 117  */
 118 static char rcs_ident[] =
 119         "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
 120 
 121 #include <ctype.h>
 122 #include <signal.h>
 123 #include <sys/param.h>
 124 #include <locale.h>
 125 #include <langinfo.h>
 126 #include <sys/acl.h>
 127 #include <utime.h>
 128 #include <libgen.h>
 129 #include <setjmp.h>
 130 #include <aclutils.h>
 131 #include <libcmdutils.h>
 132 #include "getresponse.h"
 133 
 134 
 135 static int n_bits;                      /* number of bits/code */
 136 static int maxbits = BITS;      /* user settable max # bits/code */
 137 static code_int maxcode;        /* maximum code, given n_bits */
 138                         /* should NEVER generate this code */
 139 static code_int maxmaxcode = 1 << BITS;
 140 #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
 141 
 142 static count_int htab [OUTSTACKSIZE];
 143 static unsigned short codetab [OUTSTACKSIZE];
 144 
 145 #define htabof(i)       htab[i]
 146 #define codetabof(i)    codetab[i]
 147 static code_int hsize = HSIZE; /* for dynamic table sizing */
 148 static off_t    fsize;  /* file size of input file */
 149 
 150 /*
 151  * To save much memory, we overlay the table used by compress() with those
 152  * used by decompress().  The tab_prefix table is the same size and type
 153  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
 154  * get this from the beginning of htab.  The output stack uses the rest
 155  * of htab, and contains characters.  There is plenty of room for any
 156  * possible stack (stack used to be 8000 characters).
 157  */
 158 
 159 #define tab_prefixof(i)         codetabof(i)
 160 #define tab_suffixof(i)         ((char_type *)(htab))[i]
 161 #define de_stack                ((char_type *)&tab_suffixof(1<<BITS))
 162 #define stack_max               ((char_type *)&tab_suffixof(OUTSTACKSIZE))
 163 
 164 static code_int free_ent = 0; /* first unused entry */
 165 static int newline_needed = 0;
 166 static int didnt_shrink = 0;
 167 static int perm_stat = 0;       /* permanent status */
 168 
 169 static code_int getcode();
 170 
 171         /* Use a 3-byte magic number header, unless old file */
 172 static int nomagic = 0;
 173         /* Write output on stdout, suppress messages */
 174 static int zcat_flg = 0;        /* use stdout on all files */
 175 static int zcat_cmd = 0;        /* zcat cmd */
 176 static int use_stdout = 0;      /* set for each file processed */
 177         /* Don't unlink output file on interrupt */
 178 static int precious = 1;
 179 static int quiet = 1;   /* don't tell me about compression */
 180 
 181 /*
 182  * block compression parameters -- after all codes are used up,
 183  * and compression rate changes, start over.
 184  */
 185 static int block_compress = BLOCK_MASK;
 186 static int clear_flg = 0;
 187 static long int ratio = 0;
 188 #define CHECK_GAP 10000 /* ratio check interval */
 189 static count_long checkpoint = CHECK_GAP;
 190 /*
 191  * the next two codes should not be changed lightly, as they must not
 192  * lie within the contiguous general code space.
 193  */
 194 #define FIRST   257     /* first free entry */
 195 #define CLEAR   256     /* table clear output code */
 196 
 197 static int force = 0;
 198 static char ofname [MAXPATHLEN];
 199 
 200 static int Vflg = 0;
 201 static int vflg = 0;
 202 static int qflg = 0;
 203 static int bflg = 0;
 204 static int Fflg = 0;
 205 static int dflg = 0;
 206 static int cflg = 0;
 207 static int Cflg = 0;
 208 
 209 #ifdef DEBUG
 210 int verbose = 0;
 211 int debug = 0;
 212 #endif /* DEBUG */
 213 
 214 static void (*oldint)();
 215 static int bgnd_flag;
 216 
 217 static int do_decomp = 0;
 218 
 219 static char *progname;
 220 static char *optstr;
 221 /*
 222  * Fix lint errors
 223  */
 224 
 225 static char *local_basename(char *);
 226 
 227 static int  addDotZ(char *, size_t);
 228 
 229 static void Usage(void);
 230 static void cl_block(count_long);
 231 static void cl_hash(count_int);
 232 static void compress(void);
 233 static void copystat(char *, struct stat *, char *);
 234 static void decompress(void);
 235 static void ioerror(void);
 236 static void onintr();
 237 static void oops();
 238 static void output(code_int);
 239 static void prratio(FILE *, count_long, count_long);
 240 static void version(void);
 241 
 242 #ifdef DEBUG
 243 static int in_stack(int, int);
 244 static void dump_tab(void);
 245 static void printcodes(void);
 246 #endif
 247 
 248 /* For error-handling */
 249 
 250 static jmp_buf env;
 251 
 252 /* For input and ouput */
 253 
 254 static FILE *inp;               /* the current input file */
 255 static FILE *infile;            /* disk-based input stream */
 256 static FILE *outp;              /* current output file */
 257 static FILE *outfile;           /* disk-based output stream */
 258 
 259 /* For output() */
 260 
 261 static char buf[BITS];
 262 
 263 static char_type lmask[9] =
 264         {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
 265 static char_type rmask[9] =
 266         {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
 267 
 268 /* For compress () */
 269 
 270 static int offset;
 271 static count_long bytes_out;    /* length of compressed output */
 272         /* # of codes output (for debugging) */
 273 
 274 /* For dump_tab() */
 275 
 276 #define STACK_SIZE      15000
 277 #ifdef DEBUG
 278 code_int sorttab[1<<BITS];        /* sorted pointers into htab */
 279 #endif
 280 
 281 /* Extended system attribute support */
 282 
 283 static int saflg = 0;
 284 
 285 /*
 286  * *************************************************************
 287  * TAG( main )
 288  *
 289  * Algorithm from "A Technique for High Performance Data Compression",
 290  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
 291  *
 292  * Usage: compress [-dfvc/] [-b bits] [file ...]
 293  * Inputs:
 294  *      -d:         If given, decompression is done instead.
 295  *
 296  *      -c:         Write output on stdout, don't remove original.
 297  *
 298  *      -b:         Parameter limits the max number of bits/code.
 299  *
 300  *      -f:         Forces output file to be generated, even if one already
 301  *                  exists, and even if no space is saved by compressing.
 302  *                  If -f is not used, the user will be prompted if stdin is
 303  *                  a tty, otherwise, the output file will not be overwritten.
 304  *
 305  *      -/          Copies extended attributes and extended system attributes.
 306  *
 307  *  -v:     Write compression statistics
 308  *
 309  *      file ...:   Files to be compressed.  If none specified, stdin
 310  *                  is used.
 311  * Outputs:
 312  *      file.Z:     Compressed form of file with same mode, owner, and utimes
 313  *      or stdout   (if stdin used as input)
 314  *
 315  * Assumptions:
 316  * When filenames are given, replaces with the compressed version
 317  * (.Z suffix) only if the file decreases in size.
 318  * Algorithm:
 319  * Modified Lempel-Ziv method (LZW).  Basically finds common
 320  * substrings and replaces them with a variable size code.  This is
 321  * deterministic, and can be done on the fly.  Thus, the decompression
 322  * procedure needs no input table, but tracks the way the table was built.
 323  */
 324 
 325 int
 326 main(int argc, char *argv[])
 327 {
 328         int overwrite = 0;      /* Do not overwrite unless given -f flag */
 329         char tempname[MAXPATHLEN];
 330         char line[LINE_MAX];
 331         char **filelist, **fileptr;
 332         char *cp;
 333         struct stat statbuf;
 334         struct stat ostatbuf;
 335         int ch;                         /* XCU4 */
 336         char    *p;
 337         extern int optind, optopt;
 338         extern char *optarg;
 339         int dash_count = 0;             /* times "-" is on cmdline */
 340 
 341         /* XCU4 changes */
 342         (void) setlocale(LC_ALL, "");
 343 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 344 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 345 #endif
 346         (void) textdomain(TEXT_DOMAIN);
 347 
 348         if (init_yes() < 0) {
 349                 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
 350                     strerror(errno));
 351                 exit(1);
 352         }
 353 
 354         /* This bg check only works for sh. */
 355         if ((oldint = signal(SIGINT, SIG_IGN)) != SIG_IGN) {
 356                 (void) signal(SIGINT, onintr);
 357                 (void) signal(SIGSEGV, oops);
 358         }
 359         bgnd_flag = oldint != SIG_DFL;
 360 
 361         /* Allocate room for argv + "-" (if stdin needs to be added) */
 362 
 363         filelist = fileptr = (char **)(malloc((argc + 1) * sizeof (*argv)));
 364         *filelist = NULL;
 365 
 366         if ((cp = rindex(argv[0], '/')) != 0) {
 367                 cp++;
 368         } else {
 369                 cp = argv[0];
 370         }
 371 
 372         if (strcmp(cp, "uncompress") == 0) {
 373                 do_decomp = 1;
 374         } else if (strcmp(cp, "zcat") == 0) {
 375                 do_decomp = 1;
 376                 zcat_cmd = zcat_flg = 1;
 377         }
 378 
 379         progname = local_basename(argv[0]);
 380 
 381         /*
 382          * Argument Processing
 383          * All flags are optional.
 384          * -D = > debug
 385          * -V = > print Version; debug verbose
 386          * -d = > do_decomp
 387          * -v = > unquiet
 388          * -f = > force overwrite of output file
 389          * -n = > no header: useful to uncompress old files
 390          * -b     maxbits => maxbits.  If -b is specified,
 391          *        then maxbits MUST be given also.
 392          * -c = > cat all output to stdout
 393          * -C = > generate output compatible with compress 2.0.
 394          * if a string is left, must be an input filename.
 395          */
 396 #ifdef DEBUG
 397         optstr = "b:cCdDfFnqvV/";
 398 #else
 399         optstr = "b:cCdfFnqvV/";
 400 #endif
 401 
 402         while ((ch = getopt(argc, argv, optstr)) != EOF) {
 403                 /* Process all flags in this arg */
 404                 switch (ch) {
 405 #ifdef DEBUG
 406                         case 'D':
 407                                 debug = 1;
 408                                 break;
 409                         case 'V':
 410                                 verbose = 1;
 411                                 version();
 412                                 break;
 413 #else
 414                         case 'V':
 415                                 version();
 416                                 Vflg++;
 417                                 break;
 418 #endif /* DEBUG */
 419                         case 'v':
 420                                 quiet = 0;
 421                                 vflg++;
 422                                 break;
 423                         case 'd':
 424                                 do_decomp = 1;
 425                                 dflg++;
 426                                 break;
 427                         case 'f':
 428                         case 'F':
 429                                 Fflg++;
 430                                 overwrite = 1;
 431                                 force = 1;
 432                                 break;
 433                         case 'n':
 434                                 nomagic = 1;
 435                                 break;
 436                         case 'C':
 437                                 Cflg++;
 438                                 block_compress = 0;
 439                                 break;
 440                         case 'b':
 441                                 bflg++;
 442                                 p = optarg;
 443                                 if (!p) {
 444                                         (void) fprintf(stderr, gettext(
 445                                             "Missing maxbits\n"));
 446                                         Usage();
 447                                         exit(1);
 448                                 }
 449                                 maxbits = strtoul(optarg, &p, 10);
 450                                 if (*p) {
 451                                         (void) fprintf(stderr, gettext(
 452                                             "Missing maxbits\n"));
 453                                         Usage();
 454                                         exit(1);
 455                                 }
 456                                 break;
 457 
 458                         case 'c':
 459                                 cflg++;
 460                                 zcat_flg = 1;
 461                                 break;
 462                         case 'q':
 463                                 qflg++;
 464                                 quiet = 1;
 465                                 break;
 466                         case '/':
 467                                 saflg++;
 468                                 break;
 469                         default:
 470                                 (void) fprintf(stderr, gettext(
 471                                     "Unknown flag: '%c'\n"), optopt);
 472                                 Usage();
 473                                 exit(1);
 474                 }
 475         } /* while */
 476 
 477         /*
 478          * Validate zcat syntax
 479          */
 480 
 481         if (zcat_cmd && (Fflg | Cflg | cflg |
 482             bflg | qflg | dflg | nomagic)) {
 483                 (void) fprintf(stderr, gettext(
 484                     "Invalid Option\n"));
 485                 Usage();
 486                 exit(1);
 487         }
 488 
 489         /*
 490          * Process the file list
 491          */
 492 
 493         for (; optind < argc; optind++) {
 494                 if (strcmp(argv[optind], "-") == 0) {
 495                         dash_count++;
 496                 }
 497 
 498                 *fileptr++ = argv[optind];      /* Build input file list */
 499                 *fileptr = NULL;
 500         }
 501 
 502         if (dash_count > 1) {
 503                 (void) fprintf(stderr,
 504                     gettext("%s may only appear once in the file"
 505                     " list\n"), "\"-\"");
 506                 exit(1);
 507         }
 508 
 509         if (fileptr - filelist == 0) {
 510                 *fileptr++ = "-";
 511                 *fileptr = NULL;
 512         }
 513 
 514         if (fileptr - filelist > 1 && cflg && !do_decomp) {
 515                 (void) fprintf(stderr,
 516                     gettext("compress: only one file may be compressed"
 517                     " to stdout\n"));
 518                 exit(1);
 519         }
 520 
 521         if (maxbits < INIT_BITS)
 522                 maxbits = INIT_BITS;
 523         if (maxbits > BITS)
 524                 maxbits = BITS;
 525         maxmaxcode = 1 << maxbits;
 526 
 527         /* Need to open something to close with freopen later */
 528 
 529         if ((infile = fopen("/dev/null", "r")) == NULL) {
 530                 (void) fprintf(stderr, gettext("Error opening /dev/null for "
 531                     "input\n"));
 532                 exit(1);
 533         }
 534 
 535         if ((outfile = fopen("/dev/null", "w")) == NULL) {
 536                 (void) fprintf(stderr, gettext("Error opening /dev/null for "
 537                     "output\n"));
 538                 exit(1);
 539         }
 540 
 541         for (fileptr = filelist; *fileptr; fileptr++) {
 542                 int jmpval = 0;
 543                 didnt_shrink = 0;
 544                 newline_needed = 0;
 545 
 546                 if (do_decomp) {
 547                         /* DECOMPRESSION */
 548 
 549                         if (strcmp(*fileptr, "-") == 0) {
 550                                 /* process stdin */
 551                                 inp = stdin;
 552                                 outp = stdout;
 553                                 use_stdout = 1;
 554                                 *fileptr = "stdin"; /* for error messages */
 555                         } else {
 556                                 /* process the named file */
 557 
 558                                 inp = infile;
 559                                 outp = outfile;
 560                                 use_stdout = 0;
 561 
 562                                 if (zcat_flg) {
 563                                         use_stdout = 1;
 564                                         outp = stdout;
 565                                 }
 566 
 567                                 /* Check for .Z suffix */
 568 
 569                                 if (strcmp(*fileptr +
 570                                     strlen(*fileptr) - 2, ".Z") != 0) {
 571                                         /* No .Z: tack one on */
 572 
 573                                         if (strlcpy(tempname, *fileptr,
 574                                             sizeof (tempname)) >=
 575                                             sizeof (tempname)) {
 576                                                 (void) fprintf(stderr,
 577                                                     gettext("%s: filename "
 578                                                     "too long\n"),
 579                                                     *fileptr);
 580                                                 perm_stat = 1;
 581                                                 continue;
 582                                         }
 583 
 584                                         if (addDotZ(tempname,
 585                                             sizeof (tempname)) < 0) {
 586                                                 perm_stat = 1;
 587                                                 continue;
 588                                         }
 589 
 590                                         *fileptr = tempname;
 591                                 }
 592 
 593                                 /* Open input file */
 594 
 595                                 if (stat(*fileptr, &statbuf) < 0) {
 596                                         perror(*fileptr);
 597                                         perm_stat = 1;
 598                                         continue;
 599                                 }
 600 
 601                                 if ((freopen(*fileptr, "r", inp)) == NULL) {
 602                                         perror(*fileptr);
 603                                         perm_stat = 1;
 604                                         continue;
 605                                 }
 606                         }
 607 
 608                         /* Check the magic number */
 609 
 610                         if (nomagic == 0) {
 611                                 if ((getc(inp) !=
 612                                     (magic_header[0] & 0xFF)) ||
 613                                     (getc(inp) !=
 614                                     (magic_header[1] & 0xFF))) {
 615                                         (void) fprintf(stderr, gettext(
 616                                             "%s: not in compressed "
 617                                             "format\n"),
 618                                             *fileptr);
 619                                         perm_stat = 1;
 620                                         continue;
 621                                 }
 622 
 623                                 /* set -b from file */
 624                                 if ((maxbits = getc(inp)) == EOF &&
 625                                     ferror(inp)) {
 626                                         perror(*fileptr);
 627                                         perm_stat = 1;
 628                                         continue;
 629                                 }
 630 
 631                                 block_compress = maxbits & BLOCK_MASK;
 632                                 maxbits &= BIT_MASK;
 633                                 maxmaxcode = 1 << maxbits;
 634 
 635                                 if (maxbits > BITS) {
 636                                         (void) fprintf(stderr,
 637                                             gettext("%s: compressed "
 638                                             "with %d bits, "
 639                                             "can only handle"
 640                                             " %d bits\n"),
 641                                             *fileptr, maxbits, BITS);
 642                                         perm_stat = 1;
 643                                         continue;
 644                                 }
 645                         }
 646 
 647                         if (!use_stdout) {
 648                                 /* Generate output filename */
 649 
 650                                 if (strlcpy(ofname, *fileptr,
 651                                     sizeof (ofname)) >=
 652                                     sizeof (ofname)) {
 653                                         (void) fprintf(stderr,
 654                                             gettext("%s: filename "
 655                                             "too long\n"),
 656                                             *fileptr);
 657                                         perm_stat = 1;
 658                                         continue;
 659                                 }
 660 
 661                                 /* Strip off .Z */
 662 
 663                                 ofname[strlen(*fileptr) - 2] = '\0';
 664                         }
 665                 } else {
 666                         /* COMPRESSION */
 667 
 668                         if (strcmp(*fileptr, "-") == 0) {
 669                                 /* process stdin */
 670                                 inp = stdin;
 671                                 outp = stdout;
 672                                 use_stdout = 1;
 673                                 *fileptr = "stdin"; /* for error messages */
 674 
 675                                 /* Use the largest possible hash table */
 676                                 hsize =  HSIZE;
 677                         } else {
 678                                 /* process the named file */
 679 
 680                                 inp = infile;
 681                                 outp = outfile;
 682                                 use_stdout = 0;
 683 
 684                                 if (zcat_flg) {
 685                                         use_stdout = 1;
 686                                         outp = stdout;
 687                                 }
 688 
 689                                 if (strcmp(*fileptr +
 690                                     strlen(*fileptr) - 2, ".Z") == 0) {
 691                                         (void) fprintf(stderr, gettext(
 692                                             "%s: already has .Z "
 693                                             "suffix -- no change\n"),
 694                                             *fileptr);
 695                                         perm_stat = 1;
 696                                         continue;
 697                                 }
 698                                 /* Open input file */
 699 
 700                                 if (stat(*fileptr, &statbuf) < 0) {
 701                                         perror(*fileptr);
 702                                         perm_stat = 1;
 703                                         continue;
 704                                 }
 705 
 706                                 if ((freopen(*fileptr, "r", inp)) == NULL) {
 707                                         perror(*fileptr);
 708                                         perm_stat = 1;
 709                                         continue;
 710                                 }
 711 
 712                                 fsize = (off_t)statbuf.st_size;
 713 
 714                                 /*
 715                                  * tune hash table size for small
 716                                  * files -- ad hoc,
 717                                  * but the sizes match earlier #defines, which
 718                                  * serve as upper bounds on the number of
 719                                  * output codes.
 720                                  */
 721                                 hsize = HSIZE;
 722                                 if (fsize < (1 << 12))
 723                                         hsize = min(5003, HSIZE);
 724                                 else if (fsize < (1 << 13))
 725                                         hsize = min(9001, HSIZE);
 726                                 else if (fsize < (1 << 14))
 727                                         hsize = min(18013, HSIZE);
 728                                 else if (fsize < (1 << 15))
 729                                         hsize = min(35023, HSIZE);
 730                                 else if (fsize < 47000)
 731                                         hsize = min(50021, HSIZE);
 732 
 733                                 if (!use_stdout) {
 734                                         /* Generate output filename */
 735 
 736                                         if (strlcpy(ofname, *fileptr,
 737                                             sizeof (ofname)) >=
 738                                             sizeof (ofname)) {
 739                                                 (void) fprintf(stderr,
 740                                                     gettext("%s: filename "
 741                                                     "too long\n"),
 742                                                     *fileptr);
 743                                                 perm_stat = 1;
 744                                                 continue;
 745                                         }
 746 
 747                                         if (addDotZ(ofname,
 748                                             sizeof (ofname)) < 0) {
 749                                                 perm_stat = 1;
 750                                                 continue;
 751                                         }
 752                                 }
 753                         }
 754                 }       /* if (do_decomp) */
 755 
 756                 /* Check for overwrite of existing file */
 757 
 758                 if (!overwrite && !use_stdout) {
 759                         if (stat(ofname, &ostatbuf) == 0) {
 760                                 (void) fprintf(stderr, gettext(
 761                                     "%s already exists;"), ofname);
 762                                 if (bgnd_flag == 0 && isatty(2)) {
 763                                         int cin;
 764 
 765                                         (void) fprintf(stderr, gettext(
 766                                             " do you wish to overwr"
 767                                             "ite %s (%s or %s)? "),
 768                                             ofname, yesstr, nostr);
 769                                         (void) fflush(stderr);
 770                                         for (cin = 0; cin < LINE_MAX; cin++)
 771                                                 line[cin] = 0;
 772                                         (void) read(2, line, LINE_MAX);
 773 
 774                                         if (yes_check(line) == 0) {
 775                                                 (void) fprintf(stderr,
 776                                                     gettext(
 777                                                     "\tnot overwri"
 778                                                     "tten\n"));
 779                                                 continue;
 780                                         }
 781                                 } else {
 782                                         /*
 783                                          * XPG4: Assertion 1009
 784                                          * Standard input is not
 785                                          * terminal, and no '-f',
 786                                          * and file exists.
 787                                          */
 788 
 789                                         (void) fprintf(stderr, gettext(
 790                                             "%s: File exists, -f not"
 791                                             " specified, and ru"
 792                                             "nning in the backgro"
 793                                             "und.\n"), *fileptr);
 794                                         perm_stat = 1;
 795                                         continue;
 796                                 }
 797                         }
 798                 }
 799                 if (!use_stdout) {
 800                         if ((pathconf(ofname, _PC_XATTR_EXISTS) == 1) ||
 801                             (saflg && sysattr_support(ofname,
 802                             _PC_SATTR_EXISTS) == 1)) {
 803                                 (void) unlink(ofname);
 804                         }
 805                         /* Open output file */
 806                         if (freopen(ofname, "w", outp) == NULL) {
 807                                 perror(ofname);
 808                                 perm_stat = 1;
 809                                 continue;
 810                         }
 811                         precious = 0;
 812                         if (!quiet) {
 813                                 (void) fprintf(stderr, "%s: ",
 814                                     *fileptr);
 815                                 newline_needed = 1;
 816                         }
 817                 } else if (!quiet && !do_decomp) {
 818                         (void) fprintf(stderr, "%s: ",
 819                             *fileptr);
 820                         newline_needed = 1;
 821                 }
 822 
 823                 /* Actually do the compression/decompression */
 824 
 825                 if ((jmpval = setjmp(env)) == 0) {
 826                         /* We'll see how things go */
 827 #ifndef DEBUG
 828                         if (do_decomp == 0)  {
 829                                 compress();
 830                         } else {
 831                                 decompress();
 832                         }
 833 #else
 834                         if (do_decomp == 0)  {
 835                                 compress();
 836                         } else if (debug == 0)  {
 837                                 decompress();
 838                         } else {
 839                                 printcodes();
 840                         }
 841 
 842                         if (verbose) {
 843                                 dump_tab();
 844                         }
 845 #endif
 846                 } else {
 847                         /*
 848                          * Things went badly - clean up and go on.
 849                          * jmpval's values break down as follows:
 850                          *   1 == message determined by ferror() values.
 851                          *   2 == input problem message needed.
 852                          *   3 == output problem message needed.
 853                          */
 854 
 855                         if (ferror(inp) || jmpval == 2) {
 856                                 if (do_decomp) {
 857                                         (void) fprintf(stderr, gettext(
 858                                             "uncompress: %s: corrupt"
 859                                             " input\n"), *fileptr);
 860                                 } else {
 861                                         perror(*fileptr);
 862                                 }
 863                         }
 864 
 865                         if (ferror(outp) || jmpval == 3) {
 866                                 /* handle output errors */
 867 
 868                                 if (use_stdout) {
 869                                         perror("");
 870                                 } else {
 871                                         perror(ofname);
 872                                 }
 873                         }
 874 
 875                         if (ofname[0] != '\0') {
 876                                 if (unlink(ofname) < 0)  {
 877                                         perror(ofname);
 878                                 }
 879 
 880                                 ofname[0] = '\0';
 881                         }
 882 
 883                         perm_stat = 1;
 884                         continue;
 885                 }
 886 
 887                 /* Things went well */
 888 
 889                 if (!use_stdout) {
 890                                 /* Copy stats */
 891                         copystat(*fileptr, &statbuf, ofname);
 892                         precious = 1;
 893                         if (newline_needed) {
 894                                 (void) putc('\n', stderr);
 895                         }
 896                         /*
 897                          * Print the info. for unchanged file
 898                          * when no -v
 899                          */
 900 
 901                         if (didnt_shrink) {
 902                                 if (!force && perm_stat == 0) {
 903                                         if (quiet) {
 904                                                 (void) fprintf(stderr, gettext(
 905                                                     "%s: -- file "
 906                                                     "unchanged\n"),
 907                                                     *fileptr);
 908                                         }
 909 
 910                                         perm_stat = 2;
 911                                 }
 912                         }
 913                 } else {
 914                         if (didnt_shrink && !force && perm_stat == 0) {
 915                                 perm_stat = 2;
 916                         }
 917 
 918                         if (newline_needed) {
 919                                 (void) fprintf(stderr, "\n");
 920                         }
 921                 }
 922         }       /* for */
 923 
 924         return (perm_stat);
 925 }
 926 
 927 static void
 928 cinterr(int hshift)
 929 {
 930         /* we have exceeded the hash table */
 931         (void) fprintf(stderr,
 932             "internal error: hashtable exceeded - hsize = %ld\n", hsize);
 933         (void) fprintf(stderr, "hshift = %d, %d\n", hshift, (1 << hshift) -1);
 934         (void) fprintf(stderr, "maxbits = %d\n", maxbits);
 935         (void) fprintf(stderr, "n_bits = %d\n", n_bits);
 936         (void) fprintf(stderr, "maxcode = %ld\n", maxcode);
 937         longjmp(env, 1);
 938 }
 939 
 940 static code_int
 941 adjusti(code_int i, code_int hsize_reg)
 942 {
 943         while (i < 0) {
 944                 i += hsize_reg;
 945         }
 946 
 947         while (i >= hsize_reg) {
 948                 i -= hsize_reg;
 949         }
 950         return (i);
 951 }
 952 
 953 /*
 954  * compress inp to outp
 955  *
 956  * Algorithm:  use open addressing double hashing(no chaining) on the
 957  * prefix code / next character combination.  We do a variant of Knuth's
 958  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 959  * secondary probe.  Here, the modular division first probe is gives way
 960  * to a faster exclusive-or manipulation.  Also do block compression with
 961  * an adaptive reset, whereby the code table is cleared when the compression
 962  * ratio decreases, but after the table fills.  The variable-length output
 963  * codes are re-sized at this point, and a special CLEAR code is generated
 964  * for the decompressor.  Late addition:  construct the table according to
 965  * file size for noticeable speed improvement on small files.  Please direct
 966  * questions about this implementation to ames!jaw.
 967  */
 968 
 969 static void
 970 compress()
 971 {
 972         long fcode;
 973         code_int i = 0;
 974         int c;
 975         code_int ent;
 976         int disp;
 977         code_int hsize_reg;
 978         int hshift;
 979         int probecnt;
 980         count_long in_count;
 981         uint32_t inchi, inclo;
 982         int maxbits_reg;
 983         FILE *fin = inp;
 984 #ifdef DEBUG
 985         count_long out_count = 0;
 986 #endif
 987 
 988         if (nomagic == 0) {
 989                 if ((putc(magic_header[0], outp) == EOF ||
 990                     putc(magic_header[1], outp) == EOF ||
 991                     putc((char)(maxbits | block_compress),
 992                     outp) == EOF) &&
 993                     ferror(outp)) {
 994                         ioerror();
 995                 }
 996         }
 997 
 998         offset = 0;
 999         bytes_out = 3;          /* includes 3-byte header mojo */
1000         clear_flg = 0;
1001         ratio = 0;
1002         in_count = 1;
1003         inchi = 0;
1004         inclo = 1;
1005         checkpoint = CHECK_GAP;
1006         maxcode = MAXCODE(n_bits = INIT_BITS);
1007         free_ent = ((block_compress) ? FIRST : 256);
1008 
1009         if ((ent = getc(fin)) == EOF && ferror(fin)) {
1010                 ioerror();
1011         }
1012 
1013         hshift = 0;
1014 
1015         for (fcode = (long)hsize;  fcode < 65536L; fcode *= 2L)
1016                 hshift++;
1017 
1018         hshift = 8 - hshift;            /* set hash code range bound */
1019 
1020         hsize_reg = hsize;
1021         maxbits_reg = maxbits;
1022 
1023         cl_hash((count_int) hsize_reg);         /* clear hash table */
1024 
1025         while ((c = getc(fin)) != EOF) {
1026                 if (++inclo == 0)
1027                         inchi++;
1028                 fcode = (long)(((long)c << maxbits_reg) + ent);
1029                 i = ((c << hshift) ^ ent);        /* xor hashing */
1030 
1031                 if ((unsigned int)i >= hsize_reg)
1032                         i = adjusti(i, hsize_reg);
1033 
1034                 if (htabof(i) == fcode) {
1035                         ent = codetabof(i);
1036                         continue;
1037                 } else if ((long)htabof(i) < 0) {
1038                         /* empty slot */
1039                         goto nomatch;
1040                 }
1041 
1042                 /* secondary hash (after G. Knott) */
1043                 disp = hsize_reg - i;
1044 
1045                 if (i == 0) {
1046                         disp = 1;
1047                 }
1048 
1049                 probecnt = 0;
1050         probe:
1051                 if (++probecnt > hsize_reg)
1052                         cinterr(hshift);
1053 
1054                 if ((i -= disp) < 0) {
1055                         while (i < 0)
1056                                 i += hsize_reg;
1057                 }
1058 
1059                 if (htabof(i) == fcode) {
1060                         ent = codetabof(i);
1061                         continue;
1062                 }
1063 
1064                 if ((long)htabof(i) > 0) {
1065                         goto probe;
1066                 }
1067         nomatch:
1068                 output((code_int) ent);
1069 #ifdef DEBUG
1070                 out_count++;
1071 #endif
1072                 ent = c;
1073                 if (free_ent < maxmaxcode) {
1074                         codetabof(i) = free_ent++;
1075                         /* code -> hashtable */
1076                         htabof(i) = fcode;
1077                 } else {
1078                         in_count = ((long long)inchi<<32|inclo);
1079                         if ((count_long)in_count >=
1080                             (count_long)checkpoint && block_compress) {
1081                                 cl_block(in_count);
1082                         }
1083                 }
1084         }
1085 
1086         in_count = ((long long)inchi<<32|inclo);
1087 
1088         if (ferror(fin) != 0) {
1089                 ioerror();
1090         }
1091 
1092         /*
1093          * Put out the final code.
1094          */
1095         output((code_int)ent);
1096 #ifdef DEBUG
1097         out_count++;
1098 #endif
1099 
1100         output((code_int)-1);
1101 
1102         /*
1103          * Print out stats on stderr
1104          */
1105         if (!quiet) {
1106 #ifdef DEBUG
1107                 (void) fprintf(stderr,
1108                     "%lld chars in, %lld codes (%lld bytes) out, "
1109                     "compression factor: ",
1110                     (count_long)in_count, (count_long)out_count,
1111                     (count_long) bytes_out);
1112                 prratio(stderr, (count_long)in_count,
1113                     (count_long)bytes_out);
1114                 (void) fprintf(stderr, "\n");
1115                 (void) fprintf(stderr, "\tCompression as in compact: ");
1116                 prratio(stderr,
1117                     (count_long)in_count-(count_long)bytes_out,
1118                     (count_long)in_count);
1119                 (void) fprintf(stderr, "\n");
1120                 (void) fprintf(stderr,
1121                     "\tLargest code (of last block) was %d"
1122                     " (%d bits)\n",
1123                     free_ent - 1, n_bits);
1124 #else /* !DEBUG */
1125                 (void) fprintf(stderr, gettext("Compression: "));
1126                 prratio(stderr,
1127                     (count_long)in_count-(count_long)bytes_out,
1128                     (count_long)in_count);
1129 #endif /* DEBUG */
1130         }
1131         /* report if no savings */
1132         if ((count_long)bytes_out > (count_long)in_count) {
1133                 didnt_shrink = 1;
1134         }
1135 }
1136 
1137 /*
1138  * **************************************************************
1139  * TAG(output)
1140  *
1141  * Output the given code.
1142  * Inputs:
1143  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
1144  *              that n_bits = < (long)wordsize - 1.
1145  * Outputs:
1146  *      Outputs code to the file.
1147  * Assumptions:
1148  *      Chars are 8 bits long.
1149  * Algorithm:
1150  *      Maintain a BITS character long buffer(so that 8 codes will
1151  * fit in it exactly).  Use the VAX insv instruction to insert each
1152  * code in turn.  When the buffer fills up empty it and start over.
1153  */
1154 
1155 static void
1156 output(code_int code)
1157 {
1158 #ifdef DEBUG
1159         static int col = 0;
1160 #endif /* DEBUG */
1161 
1162         int r_off = offset, bits = n_bits;
1163         char *bp = buf;
1164 
1165 #ifdef DEBUG
1166         if (verbose)
1167                 (void) fprintf(stderr, "%5d%c", code,
1168                     (col += 6) >= 74 ? (col = 0, '\n') : ' ');
1169 #endif /* DEBUG */
1170         if (code >= 0) {
1171                 /*
1172                  * byte/bit numbering on the VAX is simulated
1173                  * by the following code
1174                  */
1175                 /*
1176                  * Get to the first byte.
1177                  */
1178                 bp += (r_off >> 3);
1179                 r_off &= 7;
1180                 /*
1181                  * Since code is always >= 8 bits, only need to mask the first
1182                  * hunk on the left.
1183                  */
1184                 *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
1185                 bp++;
1186                 bits -= (8 - r_off);
1187                 code >>= 8 - r_off;
1188                 /*
1189                  * Get any 8 bit parts in the middle (<=1 for up to 16
1190                  * bits).
1191                  */
1192                 if (bits >= 8) {
1193                         *bp++ = code;
1194                         code >>= 8;
1195                         bits -= 8;
1196                 }
1197                 /* Last bits. */
1198                 if (bits)
1199                         *bp = code;
1200                 offset += n_bits;
1201                 if (offset == (n_bits << 3)) {
1202                         bp = buf;
1203                         bits = n_bits;
1204                         bytes_out += bits;
1205                         do {
1206                                 if (putc(*bp, outp) == EOF &&
1207                                     ferror(outp)) {
1208                                         ioerror();
1209                                 }
1210                                 bp++;
1211                         } while (--bits);
1212                         offset = 0;
1213                 }
1214 
1215                 /*
1216                  * If the next entry is going to be too big for the code size,
1217                  * then increase it, if possible.
1218                  */
1219                 if (free_ent > maxcode || (clear_flg > 0)) {
1220                         /*
1221                          * Write the whole buffer, because the input
1222                          * side won't discover the size increase until
1223                          * after it has read it.
1224                          */
1225                         if (offset > 0) {
1226                                 if (fwrite(buf, 1, n_bits, outp) != n_bits) {
1227                                         longjmp(env, 3);
1228                                 }
1229                                 bytes_out += n_bits;
1230                         }
1231                         offset = 0;
1232 
1233                         if (clear_flg) {
1234                                 maxcode = MAXCODE(n_bits = INIT_BITS);
1235                                 clear_flg = 0;
1236                         } else {
1237                                 n_bits++;
1238                                 if (n_bits == maxbits)
1239                                         maxcode = maxmaxcode;
1240                                 else
1241                                         maxcode = MAXCODE(n_bits);
1242                         }
1243 #ifdef DEBUG
1244                         if (debug) {
1245                                 (void) fprintf(stderr,
1246                                     "\nChange to %d bits\n", n_bits);
1247                                 col = 0;
1248                         }
1249 #endif /* DEBUG */
1250                 }
1251         } else {
1252                 /*
1253                  * At EOF, write the rest of the buffer.
1254                  */
1255                 if (offset > 0) {
1256                         if (fwrite(buf, 1, (offset + 7) / 8, outp) == 0 &&
1257                             ferror(outp)) {
1258                                 ioerror();
1259                         }
1260                         bytes_out += (offset + 7) / 8;
1261                 }
1262                 offset = 0;
1263                 (void) fflush(outp);
1264 #ifdef DEBUG
1265                 if (verbose)
1266                         (void) fprintf(stderr, "\n");
1267 #endif /* DEBUG */
1268                 if (ferror(outp))
1269                         ioerror();
1270         }
1271 }
1272 
1273 /*
1274  * Decompress inp to outp.  This routine adapts to the codes in the
1275  * file building the "string" table on-the-fly; requiring no table to
1276  * be stored in the compressed file.  The tables used herein are shared
1277  * with those of the compress() routine.  See the definitions above.
1278  */
1279 
1280 static void
1281 decompress()
1282 {
1283         char_type *stackp, *stack_lim;
1284         int finchar;
1285         code_int code, oldcode, incode;
1286         FILE *fout = outp;
1287 
1288         /*
1289          * As above, initialize the first 256 entries in the table.
1290          */
1291         maxcode = MAXCODE(n_bits = INIT_BITS);
1292         for (code = 255; code >= 0; code--) {
1293                 tab_prefixof(code) = 0;
1294                 tab_suffixof(code) = (char_type)code;
1295         }
1296         free_ent = ((block_compress) ? FIRST : 256);
1297 
1298         finchar = oldcode = getcode();
1299         if (oldcode == -1)      /* EOF already? */
1300                 return;                 /* Get out of here */
1301         /* first code must be 8 bits = char */
1302         if (putc((char)finchar, outp) == EOF && ferror(outp)) {
1303                 /* Crash if can't write */
1304                 ioerror();
1305         }
1306         stackp = de_stack;
1307         stack_lim = stack_max;
1308 
1309         while ((code = getcode()) > -1) {
1310 
1311                 if ((code == CLEAR) && block_compress) {
1312                         for (code = 255; code >= 0; code--)
1313                                 tab_prefixof(code) = 0;
1314                         clear_flg = 1;
1315                         free_ent = FIRST - 1;
1316                         if ((code = getcode()) == -1)   /* O, untimely death! */
1317                                 break;
1318                 }
1319                 incode = code;
1320                 /*
1321                  * Special case for KwKwK string.
1322                  */
1323                 if (code >= free_ent) {
1324                         if (stackp < stack_lim) {
1325                                 *stackp++ = (char_type) finchar;
1326                                 code = oldcode;
1327                         } else {
1328                                 /* badness */
1329                                 longjmp(env, 2);
1330                         }
1331                 }
1332 
1333                 /*
1334                  * Generate output characters in reverse order
1335                  */
1336                 while (code >= 256) {
1337                         if (stackp < stack_lim) {
1338                                 *stackp++ = tab_suffixof(code);
1339                                 code = tab_prefixof(code);
1340                         } else {
1341                                 /* badness */
1342                                 longjmp(env, 2);
1343                         }
1344                 }
1345                 *stackp++ = finchar = tab_suffixof(code);
1346 
1347                 /*
1348                  * And put them out in forward order
1349                  */
1350                 do {
1351                         stackp--;
1352                         (void) putc(*stackp, fout);
1353                 } while (stackp > de_stack);
1354 
1355                 if (ferror(fout))
1356                         ioerror();
1357 
1358                 /*
1359                  * Generate the new entry.
1360                  */
1361                 if ((code = free_ent) < maxmaxcode) {
1362                         tab_prefixof(code) = (unsigned short) oldcode;
1363                         tab_suffixof(code) = (char_type) finchar;
1364                         free_ent = code+1;
1365                 }
1366                 /*
1367                  * Remember previous code.
1368                  */
1369                 oldcode = incode;
1370         }
1371         (void) fflush(outp);
1372         if (ferror(outp))
1373                 ioerror();
1374 }
1375 
1376 /*
1377  * **************************************************************
1378  * TAG( getcode )
1379  *
1380  * Read one code from the standard input.  If EOF, return -1.
1381  * Inputs:
1382  *      inp
1383  * Outputs:
1384  *      code or -1 is returned.
1385  */
1386 
1387 code_int
1388 getcode() {
1389         code_int code;
1390         static int offset = 0, size = 0;
1391         static char_type buf[BITS];
1392         int r_off, bits;
1393         char_type *bp = buf;
1394 
1395         if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
1396                 /*
1397                  * If the next entry will be too big for the current code
1398                  * size, then we must increase the size.  This implies reading
1399                  * a new buffer full, too.
1400                  */
1401                 if (free_ent > maxcode) {
1402                         n_bits++;
1403                         if (n_bits == maxbits)
1404                                 /* won't get any bigger now */
1405                                 maxcode = maxmaxcode;
1406                         else
1407                                 maxcode = MAXCODE(n_bits);
1408                 }
1409                 if (clear_flg > 0) {
1410                         maxcode = MAXCODE(n_bits = INIT_BITS);
1411                         clear_flg = 0;
1412                 }
1413                 size = fread(buf, 1, n_bits, inp);
1414 
1415                 if (size <= 0) {
1416                         if (feof(inp)) {
1417                                 /* end of file */
1418                                 return (-1);
1419                         } else if (ferror(inp)) {
1420                                 ioerror();
1421                         }
1422                 }
1423 
1424                 offset = 0;
1425                 /* Round size down to integral number of codes */
1426                 size = (size << 3) - (n_bits - 1);
1427         }
1428         r_off = offset;
1429         bits = n_bits;
1430         /*
1431          * Get to the first byte.
1432          */
1433         bp += (r_off >> 3);
1434         r_off &= 7;
1435         /* Get first part (low order bits) */
1436         code = (*bp++ >> r_off);
1437         bits -= (8 - r_off);
1438         r_off = 8 - r_off;              /* now, offset into code word */
1439         /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
1440         if (bits >= 8) {
1441                 code |= *bp++ << r_off;
1442                 r_off += 8;
1443                 bits -= 8;
1444         }
1445         /* high order bits. */
1446         code |= (*bp & rmask[bits]) << r_off;
1447         offset += n_bits;
1448 
1449         return (code);
1450 }
1451 
1452 #ifdef DEBUG
1453 static void
1454 printcodes()
1455 {
1456         /*
1457          * Just print out codes from input file.  For debugging.
1458          */
1459         code_int code;
1460         int col = 0, bits;
1461 
1462         bits = n_bits = INIT_BITS;
1463         maxcode = MAXCODE(n_bits);
1464         free_ent = ((block_compress) ? FIRST : 256);
1465         while ((code = getcode()) >= 0) {
1466                 if ((code == CLEAR) && block_compress) {
1467                         free_ent = FIRST - 1;
1468                         clear_flg = 1;
1469                 } else if (free_ent < maxmaxcode)
1470                         free_ent++;
1471                 if (bits != n_bits) {
1472                         (void) fprintf(stderr, "\nChange to %d bits\n", n_bits);
1473                         bits = n_bits;
1474                         col = 0;
1475                 }
1476                 (void) fprintf(stderr, "%5d%c",
1477                     code, (col += 6) >= 74 ? (col = 0, '\n') : ' ');
1478         }
1479         (void) putc('\n', stderr);
1480 }
1481 
1482 #endif /* DEBUG */
1483 
1484 #ifdef DEBUG
1485 static void
1486 dump_tab()      /* dump string table */
1487 {
1488         int i, first;
1489         int ent;
1490         int stack_top = STACK_SIZE;
1491         int c;
1492 
1493         if (do_decomp == 0) {   /* compressing */
1494                 int flag = 1;
1495 
1496                 for (i = 0; i < hsize; i++) {        /* build sort pointers */
1497                         if ((long)htabof(i) >= 0) {
1498                                 sorttab[codetabof(i)] = i;
1499                         }
1500                 }
1501                 first = block_compress ? FIRST : 256;
1502                 for (i = first; i < free_ent; i++) {
1503                         (void) fprintf(stderr, "%5d: \"", i);
1504                         de_stack[--stack_top] = '\n';
1505                         de_stack[--stack_top] = '"';
1506                         stack_top =
1507                             in_stack((htabof(sorttab[i]) >> maxbits) & 0xff,
1508                             stack_top);
1509                         for (ent = htabof(sorttab[i]) & ((1 << maxbits) -1);
1510                             ent > 256;
1511                             ent = htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
1512                                 stack_top = in_stack(
1513                                     htabof(sorttab[ent]) >> maxbits,
1514                                     stack_top);
1515                         }
1516                         stack_top = in_stack(ent, stack_top);
1517                         (void) fwrite(&de_stack[stack_top], 1,
1518                             STACK_SIZE - stack_top, stderr);
1519                         stack_top = STACK_SIZE;
1520                 }
1521         } else if (!debug) {    /* decompressing */
1522 
1523                 for (i = 0; i < free_ent; i++) {
1524                         ent = i;
1525                         c = tab_suffixof(ent);
1526                         if (isascii(c) && isprint(c))
1527                                 (void) fprintf(stderr, "%5d: %5d/'%c'  \"",
1528                                     ent, tab_prefixof(ent), c);
1529                         else
1530                                 (void) fprintf(stderr, "%5d: %5d/\\%03o \"",
1531                                     ent, tab_prefixof(ent), c);
1532                         de_stack[--stack_top] = '\n';
1533                         de_stack[--stack_top] = '"';
1534                         for (; ent != NULL;
1535                             ent = (ent >= FIRST ? tab_prefixof(ent) :
1536                             NULL)) {
1537                                 stack_top = in_stack(tab_suffixof(ent),
1538                                     stack_top);
1539                         }
1540                         (void) fwrite(&de_stack[stack_top], 1,
1541                             STACK_SIZE - stack_top, stderr);
1542                         stack_top = STACK_SIZE;
1543                 }
1544         }
1545 }
1546 
1547 #endif /* DEBUG */
1548 #ifdef DEBUG
1549 static int
1550 in_stack(int c, int stack_top)
1551 {
1552         if ((isascii(c) && isprint(c) && c != '\\') || c == ' ') {
1553                 de_stack[--stack_top] = c;
1554         } else {
1555                 switch (c) {
1556                 case '\n': de_stack[--stack_top] = 'n'; break;
1557                 case '\t': de_stack[--stack_top] = 't'; break;
1558                 case '\b': de_stack[--stack_top] = 'b'; break;
1559                 case '\f': de_stack[--stack_top] = 'f'; break;
1560                 case '\r': de_stack[--stack_top] = 'r'; break;
1561                 case '\\': de_stack[--stack_top] = '\\'; break;
1562                 default:
1563                         de_stack[--stack_top] = '0' + c % 8;
1564                         de_stack[--stack_top] = '0' + (c / 8) % 8;
1565                         de_stack[--stack_top] = '0' + c / 64;
1566                         break;
1567                 }
1568                 de_stack[--stack_top] = '\\';
1569         }
1570         return (stack_top);
1571 }
1572 
1573 #endif /* DEBUG */
1574 static void
1575 ioerror()
1576 {
1577         longjmp(env, 1);
1578 }
1579 
1580 static void
1581 copystat(char *ifname, struct stat *ifstat, char *ofname)
1582 {
1583         mode_t mode;
1584         struct utimbuf timep;
1585         acl_t *aclp = NULL;
1586         int error;
1587         int sattr_exist = 0;
1588         int xattr_exist = 0;
1589 
1590         if (pathconf(ifname, _PC_XATTR_EXISTS) == 1)
1591                 xattr_exist = 1;
1592         if (saflg && sysattr_support(ifname, _PC_SATTR_EXISTS) == 1)
1593                 sattr_exist = 1;
1594 
1595         if (fclose(outp)) {
1596                 perror(ofname);
1597                 if (!quiet) {
1598                         (void) fprintf(stderr, gettext(" -- file unchanged"));
1599                         newline_needed = 1;
1600                 }
1601                 perm_stat = 1;
1602         } else if (ifstat == NULL) {    /* Get stat on input file */
1603                 perror(ifname);
1604                 return;
1605         } else if ((ifstat->st_mode &
1606             S_IFMT /* 0170000 */) != S_IFREG /* 0100000 */) {
1607                 if (quiet) {
1608                         (void) fprintf(stderr, "%s: ", ifname);
1609                 }
1610                 (void) fprintf(stderr, gettext(
1611                     " -- not a regular file: unchanged"));
1612                 newline_needed = 1;
1613                 perm_stat = 1;
1614         } else if (ifstat->st_nlink > 1) {
1615                 if (quiet) {
1616                         (void) fprintf(stderr, "%s: ", ifname);
1617                 }
1618                 (void) fprintf(stderr, gettext(
1619                     " -- has %d other links: unchanged"),
1620                     (uint_t)ifstat->st_nlink - 1);
1621                 newline_needed = 1;
1622                 perm_stat = 1;
1623         } else if (didnt_shrink && !force) {
1624                 /* No compression: remove file.Z */
1625                 if (!quiet) {
1626                         (void) fprintf(stderr, gettext(
1627                             " -- file unchanged"));
1628                         newline_needed = 1;
1629                 }
1630         } else  if ((xattr_exist || sattr_exist) &&
1631             (mv_xattrs(progname, ifname, ofname, sattr_exist, 0)
1632             != 0)) {
1633                 (void) fprintf(stderr, gettext(
1634                     "%s: -- cannot preserve extended attributes or "
1635                     "system attributes, file unchanged"), ifname);
1636                 newline_needed = 1;
1637                 /* Move attributes back ... */
1638                 xattr_exist = 0;
1639                 sattr_exist = 0;
1640                 if (pathconf(ofname, _PC_XATTR_EXISTS) == 1)
1641                         xattr_exist = 1;
1642                 if (saflg && sysattr_support(ofname, _PC_SATTR_EXISTS) == 1)
1643                         sattr_exist = 1;
1644                 if (sattr_exist || xattr_exist)
1645                         (void) mv_xattrs(progname, ofname, ifname,
1646                             sattr_exist, 1);
1647                 perm_stat = 1;
1648         } else { /* ***** Successful Compression ***** */
1649                 mode = ifstat->st_mode & 07777;
1650                 if (chmod(ofname, mode)) {       /* Copy modes */
1651                         if (errno == EPERM) {
1652                                 (void) fprintf(stderr,
1653                                     gettext("failed to chmod %s"
1654                                     "- permisssion denied\n"), ofname);
1655                         }
1656                         perror(ofname);
1657                 }
1658                 error = acl_get(ifname, ACL_NO_TRIVIAL, &aclp);
1659                 if (error != 0) {
1660                         (void) fprintf(stderr, gettext(
1661                             "%s: failed to retrieve acl : %s\n"),
1662                             ifname, acl_strerror(error));
1663                         perm_stat = 1;
1664                 }
1665                 if (aclp && (acl_set(ofname, aclp) < 0)) {
1666                         (void) fprintf(stderr,
1667                             gettext("%s: failed to set acl "
1668                             "entries\n"), ofname);
1669                         perm_stat = 1;
1670                 }
1671                 if (aclp) {
1672                         acl_free(aclp);
1673                         aclp = NULL;
1674                 }
1675 
1676                 /* Copy ownership */
1677                 (void) chown(ofname, ifstat->st_uid, ifstat->st_gid);
1678                 timep.actime = ifstat->st_atime;
1679                 timep.modtime = ifstat->st_mtime;
1680                 /* Update last accessed and modified times */
1681                 (void) utime(ofname, &timep);
1682                 if (unlink(ifname)) { /* Remove input file */
1683                         if (errno == EPERM) {
1684                                 (void) fprintf(stderr,
1685                                     gettext("failed to remove %s"
1686                                     "- permisssion denied\n"), ifname);
1687                         }
1688                         perror(ifname);
1689                 }
1690                 if (!quiet) {
1691                         (void) fprintf(stderr, gettext(
1692                             " -- replaced with %s"), ofname);
1693                         newline_needed = 1;
1694                 }
1695                 return;         /* Successful return */
1696         }
1697 
1698         /* Unsuccessful return -- one of the tests failed */
1699         if (ofname[0] != '\0') {
1700                 if (unlink(ofname)) {
1701                         if (errno == EPERM) {
1702                                 (void) fprintf(stderr,
1703                                     gettext("failed to remove %s"
1704                                     "- permisssion denied\n"), ifname);
1705                         }
1706                         perror(ofname);
1707                 }
1708 
1709                 ofname[0] = '\0';
1710         }
1711 }
1712 
1713 static void
1714 onintr()
1715 {
1716         if (!precious && !use_stdout && ofname[0] != '\0')
1717                 (void) unlink(ofname);
1718         exit(1);
1719 }
1720 
1721 static void
1722 oops()  /* wild pointer -- assume bad input */
1723 {
1724         if (do_decomp) {
1725                 (void) fprintf(stderr, gettext("uncompress: corrupt input\n"));
1726         }
1727 
1728         if (!use_stdout && ofname[0] != '\0') {
1729                 (void) unlink(ofname);
1730         }
1731 
1732         exit(1);
1733 }
1734 
1735 static void
1736 cl_block(count_long in_count)   /* table clear for block compress */
1737 {
1738         count_long rat;
1739 
1740         checkpoint = (count_long)in_count + (count_long)CHECK_GAP;
1741 #ifdef DEBUG
1742         if (debug) {
1743                 (void) fprintf(stderr, "count: %lld, ratio: ",
1744                     (count_long)in_count);
1745                 prratio(stderr, (count_long)in_count, (count_long)bytes_out);
1746                 (void) fprintf(stderr, "\n");
1747         }
1748 #endif /* DEBUG */
1749 
1750         /* shift will overflow */
1751         if ((count_long)in_count > 0x007fffffffffffffLL) {
1752                 rat = (count_long)bytes_out >> 8;
1753                 if (rat == 0) {         /* Don't divide by zero */
1754                         rat = 0x7fffffffffffffffLL;
1755                 } else {
1756                         rat = (count_long)in_count / (count_long)rat;
1757                 }
1758         } else {
1759                 /* 8 fractional bits */
1760                 rat = ((count_long)in_count << 8) /(count_long)bytes_out;
1761         }
1762         if (rat > ratio) {
1763                 ratio = rat;
1764         } else {
1765                 ratio = 0;
1766 #ifdef DEBUG
1767                 if (verbose)
1768                         dump_tab();     /* dump string table */
1769 #endif
1770                 cl_hash((count_int) hsize);
1771                 free_ent = FIRST;
1772                 clear_flg = 1;
1773                 output((code_int) CLEAR);
1774 #ifdef DEBUG
1775                 if (debug)
1776                         (void) fprintf(stderr, "clear\n");
1777 #endif /* DEBUG */
1778         }
1779 }
1780 
1781 static void
1782 cl_hash(count_int hsize)                /* reset code table */
1783 {
1784         count_int *htab_p = htab+hsize;
1785         long i;
1786         long m1 = -1;
1787 
1788         i = hsize - 16;
1789         do {                            /* might use Sys V memset(3) here */
1790                 *(htab_p-16) = m1;
1791                 *(htab_p-15) = m1;
1792                 *(htab_p-14) = m1;
1793                 *(htab_p-13) = m1;
1794                 *(htab_p-12) = m1;
1795                 *(htab_p-11) = m1;
1796                 *(htab_p-10) = m1;
1797                 *(htab_p-9) = m1;
1798                 *(htab_p-8) = m1;
1799                 *(htab_p-7) = m1;
1800                 *(htab_p-6) = m1;
1801                 *(htab_p-5) = m1;
1802                 *(htab_p-4) = m1;
1803                 *(htab_p-3) = m1;
1804                 *(htab_p-2) = m1;
1805                 *(htab_p-1) = m1;
1806                 htab_p -= 16;
1807         } while ((i -= 16) >= 0);
1808 
1809         for (i += 16; i > 0; i--)
1810                 *--htab_p = m1;
1811 }
1812 
1813 static void
1814 prratio(FILE *stream, count_long num, count_long den)
1815 {
1816         int q;  /* store percentage */
1817 
1818         q = (int)(10000LL * (count_long)num / (count_long)den);
1819         if (q < 0) {
1820                 (void) putc('-', stream);
1821                 q = -q;
1822         }
1823         (void) fprintf(stream, "%d%s%02d%%", q / 100,
1824             localeconv()->decimal_point, q % 100);
1825 }
1826 
1827 static void
1828 version()
1829 {
1830         (void) fprintf(stderr, "%s, Berkeley 5.9 5/11/86\n", rcs_ident);
1831         (void) fprintf(stderr, "Options: ");
1832 #ifdef DEBUG
1833         (void) fprintf(stderr, "DEBUG, ");
1834 #endif
1835         (void) fprintf(stderr, "BITS = %d\n", BITS);
1836 }
1837 
1838 static void
1839 Usage()
1840 {
1841 #ifdef DEBUG
1842         (void) fprintf(stderr,
1843         "Usage: compress [-dDVfc/] [-b maxbits] [file ...]\n");
1844 #else
1845         if (strcmp(progname, "compress") == 0) {
1846                 (void) fprintf(stderr,
1847                     gettext(
1848                     "Usage: compress [-fv/] [-b maxbits] [file ...]\n"\
1849                     "       compress c [-fv] [-b maxbits] [file]\n"));
1850         } else if (strcmp(progname, "uncompress") == 0)
1851                 (void) fprintf(stderr, gettext(
1852                     "Usage: uncompress [-fv] [-c || -/] [file ...]\n"));
1853         else if (strcmp(progname, "zcat") == 0)
1854                 (void) fprintf(stderr, gettext("Usage: zcat [file ...]\n"));
1855 
1856 #endif /* DEBUG */
1857 }
1858 
1859 static char *
1860 local_basename(char *path)
1861 {
1862         char *p;
1863         char *ret = (char *)path;
1864 
1865         while ((p = (char *)strpbrk(ret, "/")) != NULL)
1866                 ret = p + 1;
1867         return (ret);
1868 }
1869 
1870 static int
1871 addDotZ(char *fn, size_t fnsize)
1872 {
1873         char *fn_dup;
1874         char *dir;
1875         long int max_name;
1876         long int max_path;
1877 
1878         fn_dup = strdup(fn);
1879         dir = dirname(fn_dup);
1880         max_name = pathconf(dir, _PC_NAME_MAX);
1881         max_path = pathconf(dir, _PC_PATH_MAX);
1882         free(fn_dup);
1883 
1884         /* Check for component length too long */
1885 
1886         if ((strlen(local_basename(fn)) + 2) > (size_t)max_name) {
1887                 (void) fprintf(stderr,
1888                     gettext("%s: filename too long to tack on .Z:"
1889                     " %s\n"), progname, fn);
1890                 return (-1);
1891         }
1892 
1893         /* Check for path length too long */
1894 
1895         if ((strlen(fn) + 2) > (size_t)max_path - 1) {
1896                 (void) fprintf(stderr,
1897                     gettext("%s: Pathname too long to tack on .Z:"
1898                     " %s\n"), progname, fn);
1899                 return (-1);
1900         }
1901 
1902         if (strlcat(fn, ".Z", fnsize) >= fnsize) {
1903                 (void) fprintf(stderr,
1904                     gettext("%s: Buffer overflow adding .Z to %s\n"),
1905                     progname, fn);
1906                 return (-1);
1907         }
1908 
1909         return (0);
1910 }