1a77d64afScf46844 /* 23d63ea05Sas145665 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3a77d64afScf46844 * Use is subject to license terms. 4a77d64afScf46844 */ 5a77d64afScf46844 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate /* 117c478bd9Sstevel@tonic-gate * Copyright (c) 1986 Regents of the University of California. 127c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 137c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 147c478bd9Sstevel@tonic-gate */ 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate /* 197c478bd9Sstevel@tonic-gate * Compress - data compression program 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate #define min(a, b) ((a > b) ? b : a) 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * machine variants which require cc -Dmachine: pdp11, z8000, pcxt 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Set USERMEM to the maximum amount of physical user memory available 297c478bd9Sstevel@tonic-gate * in bytes. USERMEM is used to determine the maximum BITS that can be used 307c478bd9Sstevel@tonic-gate * for compression. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * SACREDMEM is the amount of physical memory saved for others; compress 337c478bd9Sstevel@tonic-gate * will hog the rest. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate #ifndef SACREDMEM 367c478bd9Sstevel@tonic-gate #define SACREDMEM 0 377c478bd9Sstevel@tonic-gate #endif 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #ifndef USERMEM 407c478bd9Sstevel@tonic-gate #define USERMEM 450000 /* default user memory */ 417c478bd9Sstevel@tonic-gate #endif 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #ifdef USERMEM 447c478bd9Sstevel@tonic-gate #if USERMEM >= (433484+SACREDMEM) 457c478bd9Sstevel@tonic-gate #define PBITS 16 467c478bd9Sstevel@tonic-gate #else 477c478bd9Sstevel@tonic-gate #if USERMEM >= (229600+SACREDMEM) 487c478bd9Sstevel@tonic-gate #define PBITS 15 497c478bd9Sstevel@tonic-gate #else 507c478bd9Sstevel@tonic-gate #if USERMEM >= (127536+SACREDMEM) 517c478bd9Sstevel@tonic-gate #define PBITS 14 527c478bd9Sstevel@tonic-gate #else 537c478bd9Sstevel@tonic-gate #if USERMEM >= (73464+SACREDMEM) 547c478bd9Sstevel@tonic-gate #define PBITS 13 557c478bd9Sstevel@tonic-gate #else 567c478bd9Sstevel@tonic-gate #define PBITS 12 577c478bd9Sstevel@tonic-gate #endif 587c478bd9Sstevel@tonic-gate #endif 597c478bd9Sstevel@tonic-gate #endif 607c478bd9Sstevel@tonic-gate #endif 617c478bd9Sstevel@tonic-gate #undef USERMEM 627c478bd9Sstevel@tonic-gate #endif /* USERMEM */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #ifdef PBITS /* Preferred BITS for this memory size */ 657c478bd9Sstevel@tonic-gate #ifndef BITS 667c478bd9Sstevel@tonic-gate #define BITS PBITS 677c478bd9Sstevel@tonic-gate #endif /* BITS */ 687c478bd9Sstevel@tonic-gate #endif /* PBITS */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #if BITS == 16 717c478bd9Sstevel@tonic-gate #define HSIZE 69001 /* 95% occupancy */ 727c478bd9Sstevel@tonic-gate #endif 737c478bd9Sstevel@tonic-gate #if BITS == 15 747c478bd9Sstevel@tonic-gate #define HSIZE 35023 /* 94% occupancy */ 757c478bd9Sstevel@tonic-gate #endif 767c478bd9Sstevel@tonic-gate #if BITS == 14 777c478bd9Sstevel@tonic-gate #define HSIZE 18013 /* 91% occupancy */ 787c478bd9Sstevel@tonic-gate #endif 797c478bd9Sstevel@tonic-gate #if BITS == 13 807c478bd9Sstevel@tonic-gate #define HSIZE 9001 /* 91% occupancy */ 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate #if BITS <= 12 837c478bd9Sstevel@tonic-gate #define HSIZE 5003 /* 80% occupancy */ 847c478bd9Sstevel@tonic-gate #endif 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #define OUTSTACKSIZE (2<<BITS) 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * a code_int must be able to hold 2**BITS values of type int, and also -1 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate #if BITS > 15 927c478bd9Sstevel@tonic-gate typedef long int code_int; 937c478bd9Sstevel@tonic-gate #else 947c478bd9Sstevel@tonic-gate typedef int code_int; 957c478bd9Sstevel@tonic-gate #endif 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate typedef long int count_int; 987c478bd9Sstevel@tonic-gate typedef long long count_long; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate typedef unsigned char char_type; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static char_type magic_header[] = { "\037\235" }; /* 1F 9D */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Defines for third byte of header */ 1057c478bd9Sstevel@tonic-gate #define BIT_MASK 0x1f 1067c478bd9Sstevel@tonic-gate #define BLOCK_MASK 0x80 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is 1097c478bd9Sstevel@tonic-gate * a fourth header byte(for expansion). 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate #define INIT_BITS 9 /* initial number of bits/code */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * compress.c - File compression ala IEEE Computer, June 1984. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate static char rcs_ident[] = 1177c478bd9Sstevel@tonic-gate "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $"; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate #include <ctype.h> 1207c478bd9Sstevel@tonic-gate #include <signal.h> 1217c478bd9Sstevel@tonic-gate #include <sys/param.h> 1227c478bd9Sstevel@tonic-gate #include <locale.h> 1237c478bd9Sstevel@tonic-gate #include <langinfo.h> 1247c478bd9Sstevel@tonic-gate #include <sys/acl.h> 1257c478bd9Sstevel@tonic-gate #include <utime.h> 1267c478bd9Sstevel@tonic-gate #include <libgen.h> 1277c478bd9Sstevel@tonic-gate #include <setjmp.h> 128fa9e4066Sahrens #include <aclutils.h> 129*da6c28aaSamw #include <libcmdutils.h> 1303d63ea05Sas145665 #include "getresponse.h" 1317c478bd9Sstevel@tonic-gate 132*da6c28aaSamw 1337c478bd9Sstevel@tonic-gate static int n_bits; /* number of bits/code */ 1347c478bd9Sstevel@tonic-gate static int maxbits = BITS; /* user settable max # bits/code */ 1357c478bd9Sstevel@tonic-gate static code_int maxcode; /* maximum code, given n_bits */ 1367c478bd9Sstevel@tonic-gate /* should NEVER generate this code */ 1377c478bd9Sstevel@tonic-gate static code_int maxmaxcode = 1 << BITS; 1387c478bd9Sstevel@tonic-gate #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate static count_int htab [OUTSTACKSIZE]; 1417c478bd9Sstevel@tonic-gate static unsigned short codetab [OUTSTACKSIZE]; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate #define htabof(i) htab[i] 1447c478bd9Sstevel@tonic-gate #define codetabof(i) codetab[i] 1457c478bd9Sstevel@tonic-gate static code_int hsize = HSIZE; /* for dynamic table sizing */ 1467c478bd9Sstevel@tonic-gate static off_t fsize; /* file size of input file */ 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * To save much memory, we overlay the table used by compress() with those 1507c478bd9Sstevel@tonic-gate * used by decompress(). The tab_prefix table is the same size and type 1517c478bd9Sstevel@tonic-gate * as the codetab. The tab_suffix table needs 2**BITS characters. We 1527c478bd9Sstevel@tonic-gate * get this from the beginning of htab. The output stack uses the rest 1537c478bd9Sstevel@tonic-gate * of htab, and contains characters. There is plenty of room for any 1547c478bd9Sstevel@tonic-gate * possible stack (stack used to be 8000 characters). 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate #define tab_prefixof(i) codetabof(i) 1587c478bd9Sstevel@tonic-gate #define tab_suffixof(i) ((char_type *)(htab))[i] 1597c478bd9Sstevel@tonic-gate #define de_stack ((char_type *)&tab_suffixof(1<<BITS)) 1607c478bd9Sstevel@tonic-gate #define stack_max ((char_type *)&tab_suffixof(OUTSTACKSIZE)) 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static code_int free_ent = 0; /* first unused entry */ 1637c478bd9Sstevel@tonic-gate static int newline_needed = 0; 1647c478bd9Sstevel@tonic-gate static int didnt_shrink = 0; 1657c478bd9Sstevel@tonic-gate static int perm_stat = 0; /* permanent status */ 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate static code_int getcode(); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* Use a 3-byte magic number header, unless old file */ 1707c478bd9Sstevel@tonic-gate static int nomagic = 0; 1717c478bd9Sstevel@tonic-gate /* Write output on stdout, suppress messages */ 1727c478bd9Sstevel@tonic-gate static int zcat_flg = 0; /* use stdout on all files */ 1737c478bd9Sstevel@tonic-gate static int zcat_cmd = 0; /* zcat cmd */ 1747c478bd9Sstevel@tonic-gate static int use_stdout = 0; /* set for each file processed */ 1757c478bd9Sstevel@tonic-gate /* Don't unlink output file on interrupt */ 1767c478bd9Sstevel@tonic-gate static int precious = 1; 1777c478bd9Sstevel@tonic-gate static int quiet = 1; /* don't tell me about compression */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * block compression parameters -- after all codes are used up, 1817c478bd9Sstevel@tonic-gate * and compression rate changes, start over. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate static int block_compress = BLOCK_MASK; 1847c478bd9Sstevel@tonic-gate static int clear_flg = 0; 1857c478bd9Sstevel@tonic-gate static long int ratio = 0; 1867c478bd9Sstevel@tonic-gate #define CHECK_GAP 10000 /* ratio check interval */ 1877c478bd9Sstevel@tonic-gate static count_long checkpoint = CHECK_GAP; 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * the next two codes should not be changed lightly, as they must not 1907c478bd9Sstevel@tonic-gate * lie within the contiguous general code space. 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate #define FIRST 257 /* first free entry */ 1937c478bd9Sstevel@tonic-gate #define CLEAR 256 /* table clear output code */ 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate static int force = 0; 1967c478bd9Sstevel@tonic-gate static char ofname [MAXPATHLEN]; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate static int Vflg = 0; 1997c478bd9Sstevel@tonic-gate static int vflg = 0; 2007c478bd9Sstevel@tonic-gate static int qflg = 0; 2017c478bd9Sstevel@tonic-gate static int bflg = 0; 2027c478bd9Sstevel@tonic-gate static int Fflg = 0; 2037c478bd9Sstevel@tonic-gate static int dflg = 0; 2047c478bd9Sstevel@tonic-gate static int cflg = 0; 2057c478bd9Sstevel@tonic-gate static int Cflg = 0; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate #ifdef DEBUG 2087c478bd9Sstevel@tonic-gate int verbose = 0; 2097c478bd9Sstevel@tonic-gate int debug = 0; 2107c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static void (*oldint)(); 2137c478bd9Sstevel@tonic-gate static int bgnd_flag; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate static int do_decomp = 0; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static char *progname; 2187c478bd9Sstevel@tonic-gate static char *optstr; 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Fix lint errors 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static char *local_basename(char *); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate static int addDotZ(char *, size_t); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate static void Usage(void); 2287c478bd9Sstevel@tonic-gate static void cl_block(count_long); 2297c478bd9Sstevel@tonic-gate static void cl_hash(count_int); 2307c478bd9Sstevel@tonic-gate static void compress(void); 2317c478bd9Sstevel@tonic-gate static void copystat(char *, struct stat *, char *); 2327c478bd9Sstevel@tonic-gate static void decompress(void); 2337c478bd9Sstevel@tonic-gate static void ioerror(void); 2347c478bd9Sstevel@tonic-gate static void onintr(); 2357c478bd9Sstevel@tonic-gate static void oops(); 2367c478bd9Sstevel@tonic-gate static void output(code_int); 2377c478bd9Sstevel@tonic-gate static void prratio(FILE *, count_long, count_long); 2387c478bd9Sstevel@tonic-gate static void version(void); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate #ifdef DEBUG 2417c478bd9Sstevel@tonic-gate static int in_stack(int, int); 2427c478bd9Sstevel@tonic-gate static void dump_tab(void); 2437c478bd9Sstevel@tonic-gate static void printcodes(void); 2447c478bd9Sstevel@tonic-gate #endif 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* For error-handling */ 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate static jmp_buf env; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* For input and ouput */ 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate static FILE *inp; /* the current input file */ 2537c478bd9Sstevel@tonic-gate static FILE *infile; /* disk-based input stream */ 2547c478bd9Sstevel@tonic-gate static FILE *outp; /* current output file */ 2557c478bd9Sstevel@tonic-gate static FILE *outfile; /* disk-based output stream */ 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* For output() */ 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate static char buf[BITS]; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate static char_type lmask[9] = 2627c478bd9Sstevel@tonic-gate {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; 2637c478bd9Sstevel@tonic-gate static char_type rmask[9] = 2647c478bd9Sstevel@tonic-gate {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate /* For compress () */ 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate static int offset; 2697c478bd9Sstevel@tonic-gate static count_long bytes_out; /* length of compressed output */ 2707c478bd9Sstevel@tonic-gate /* # of codes output (for debugging) */ 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* For dump_tab() */ 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate #define STACK_SIZE 15000 2757c478bd9Sstevel@tonic-gate #ifdef DEBUG 2767c478bd9Sstevel@tonic-gate code_int sorttab[1<<BITS]; /* sorted pointers into htab */ 2777c478bd9Sstevel@tonic-gate #endif 2787c478bd9Sstevel@tonic-gate 279*da6c28aaSamw /* Extended system attribute support */ 280*da6c28aaSamw 281*da6c28aaSamw static int saflg = 0; 282*da6c28aaSamw 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * ************************************************************* 2857c478bd9Sstevel@tonic-gate * TAG( main ) 2867c478bd9Sstevel@tonic-gate * 2877c478bd9Sstevel@tonic-gate * Algorithm from "A Technique for High Performance Data Compression", 2887c478bd9Sstevel@tonic-gate * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. 2897c478bd9Sstevel@tonic-gate * 290*da6c28aaSamw * Usage: compress [-dfvc/] [-b bits] [file ...] 2917c478bd9Sstevel@tonic-gate * Inputs: 2927c478bd9Sstevel@tonic-gate * -d: If given, decompression is done instead. 2937c478bd9Sstevel@tonic-gate * 2947c478bd9Sstevel@tonic-gate * -c: Write output on stdout, don't remove original. 2957c478bd9Sstevel@tonic-gate * 2967c478bd9Sstevel@tonic-gate * -b: Parameter limits the max number of bits/code. 2977c478bd9Sstevel@tonic-gate * 2987c478bd9Sstevel@tonic-gate * -f: Forces output file to be generated, even if one already 2997c478bd9Sstevel@tonic-gate * exists, and even if no space is saved by compressing. 3007c478bd9Sstevel@tonic-gate * If -f is not used, the user will be prompted if stdin is 3017c478bd9Sstevel@tonic-gate * a tty, otherwise, the output file will not be overwritten. 3027c478bd9Sstevel@tonic-gate * 303*da6c28aaSamw * -/ Copies extended attributes and extended system attributes. 304*da6c28aaSamw * 3057c478bd9Sstevel@tonic-gate * -v: Write compression statistics 3067c478bd9Sstevel@tonic-gate * 3077c478bd9Sstevel@tonic-gate * file ...: Files to be compressed. If none specified, stdin 3087c478bd9Sstevel@tonic-gate * is used. 3097c478bd9Sstevel@tonic-gate * Outputs: 3107c478bd9Sstevel@tonic-gate * file.Z: Compressed form of file with same mode, owner, and utimes 3117c478bd9Sstevel@tonic-gate * or stdout (if stdin used as input) 3127c478bd9Sstevel@tonic-gate * 3137c478bd9Sstevel@tonic-gate * Assumptions: 3147c478bd9Sstevel@tonic-gate * When filenames are given, replaces with the compressed version 3157c478bd9Sstevel@tonic-gate * (.Z suffix) only if the file decreases in size. 3167c478bd9Sstevel@tonic-gate * Algorithm: 3177c478bd9Sstevel@tonic-gate * Modified Lempel-Ziv method (LZW). Basically finds common 3187c478bd9Sstevel@tonic-gate * substrings and replaces them with a variable size code. This is 3197c478bd9Sstevel@tonic-gate * deterministic, and can be done on the fly. Thus, the decompression 3207c478bd9Sstevel@tonic-gate * procedure needs no input table, but tracks the way the table was built. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate int 3247c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate int overwrite = 0; /* Do not overwrite unless given -f flag */ 3277c478bd9Sstevel@tonic-gate char tempname[MAXPATHLEN]; 3287c478bd9Sstevel@tonic-gate char line[LINE_MAX]; 3297c478bd9Sstevel@tonic-gate char **filelist, **fileptr; 3307c478bd9Sstevel@tonic-gate char *cp; 3317c478bd9Sstevel@tonic-gate struct stat statbuf; 3327c478bd9Sstevel@tonic-gate struct stat ostatbuf; 3337c478bd9Sstevel@tonic-gate int ch; /* XCU4 */ 3343d63ea05Sas145665 char *p; 3357c478bd9Sstevel@tonic-gate extern int optind, optopt; 3367c478bd9Sstevel@tonic-gate extern char *optarg; 3377c478bd9Sstevel@tonic-gate int dash_count = 0; /* times "-" is on cmdline */ 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* XCU4 changes */ 3407c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3417c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 3427c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 3437c478bd9Sstevel@tonic-gate #endif 3447c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3457c478bd9Sstevel@tonic-gate 3463d63ea05Sas145665 if (init_yes() < 0) { 3473d63ea05Sas145665 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES), 3483d63ea05Sas145665 strerror(errno)); 3493d63ea05Sas145665 exit(1); 3503d63ea05Sas145665 } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* This bg check only works for sh. */ 3537c478bd9Sstevel@tonic-gate if ((oldint = signal(SIGINT, SIG_IGN)) != SIG_IGN) { 3547c478bd9Sstevel@tonic-gate (void) signal(SIGINT, onintr); 3557c478bd9Sstevel@tonic-gate (void) signal(SIGSEGV, oops); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate bgnd_flag = oldint != SIG_DFL; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* Allocate room for argv + "-" (if stdin needs to be added) */ 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate filelist = fileptr = (char **)(malloc((argc + 1) * sizeof (*argv))); 3627c478bd9Sstevel@tonic-gate *filelist = NULL; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if ((cp = rindex(argv[0], '/')) != 0) { 3657c478bd9Sstevel@tonic-gate cp++; 3667c478bd9Sstevel@tonic-gate } else { 3677c478bd9Sstevel@tonic-gate cp = argv[0]; 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate if (strcmp(cp, "uncompress") == 0) { 3717c478bd9Sstevel@tonic-gate do_decomp = 1; 3727c478bd9Sstevel@tonic-gate } else if (strcmp(cp, "zcat") == 0) { 3737c478bd9Sstevel@tonic-gate do_decomp = 1; 3747c478bd9Sstevel@tonic-gate zcat_cmd = zcat_flg = 1; 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate progname = local_basename(argv[0]); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * Argument Processing 3817c478bd9Sstevel@tonic-gate * All flags are optional. 3827c478bd9Sstevel@tonic-gate * -D = > debug 3837c478bd9Sstevel@tonic-gate * -V = > print Version; debug verbose 3847c478bd9Sstevel@tonic-gate * -d = > do_decomp 3857c478bd9Sstevel@tonic-gate * -v = > unquiet 3867c478bd9Sstevel@tonic-gate * -f = > force overwrite of output file 3877c478bd9Sstevel@tonic-gate * -n = > no header: useful to uncompress old files 3887c478bd9Sstevel@tonic-gate * -b maxbits => maxbits. If -b is specified, 3897c478bd9Sstevel@tonic-gate * then maxbits MUST be given also. 3907c478bd9Sstevel@tonic-gate * -c = > cat all output to stdout 3917c478bd9Sstevel@tonic-gate * -C = > generate output compatible with compress 2.0. 3927c478bd9Sstevel@tonic-gate * if a string is left, must be an input filename. 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate #ifdef DEBUG 395*da6c28aaSamw optstr = "b:cCdDfFnqvV/"; 3967c478bd9Sstevel@tonic-gate #else 397*da6c28aaSamw optstr = "b:cCdfFnqvV/"; 3987c478bd9Sstevel@tonic-gate #endif 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate while ((ch = getopt(argc, argv, optstr)) != EOF) { 4017c478bd9Sstevel@tonic-gate /* Process all flags in this arg */ 4027c478bd9Sstevel@tonic-gate switch (ch) { 4037c478bd9Sstevel@tonic-gate #ifdef DEBUG 4047c478bd9Sstevel@tonic-gate case 'D': 4057c478bd9Sstevel@tonic-gate debug = 1; 4067c478bd9Sstevel@tonic-gate break; 4077c478bd9Sstevel@tonic-gate case 'V': 4087c478bd9Sstevel@tonic-gate verbose = 1; 4097c478bd9Sstevel@tonic-gate version(); 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate #else 4127c478bd9Sstevel@tonic-gate case 'V': 4137c478bd9Sstevel@tonic-gate version(); 4147c478bd9Sstevel@tonic-gate Vflg++; 4157c478bd9Sstevel@tonic-gate break; 4167c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 4177c478bd9Sstevel@tonic-gate case 'v': 4187c478bd9Sstevel@tonic-gate quiet = 0; 4197c478bd9Sstevel@tonic-gate vflg++; 4207c478bd9Sstevel@tonic-gate break; 4217c478bd9Sstevel@tonic-gate case 'd': 4227c478bd9Sstevel@tonic-gate do_decomp = 1; 4237c478bd9Sstevel@tonic-gate dflg++; 4247c478bd9Sstevel@tonic-gate break; 4257c478bd9Sstevel@tonic-gate case 'f': 4267c478bd9Sstevel@tonic-gate case 'F': 4277c478bd9Sstevel@tonic-gate Fflg++; 4287c478bd9Sstevel@tonic-gate overwrite = 1; 4297c478bd9Sstevel@tonic-gate force = 1; 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate case 'n': 4327c478bd9Sstevel@tonic-gate nomagic = 1; 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate case 'C': 4357c478bd9Sstevel@tonic-gate Cflg++; 4367c478bd9Sstevel@tonic-gate block_compress = 0; 4377c478bd9Sstevel@tonic-gate break; 4387c478bd9Sstevel@tonic-gate case 'b': 4397c478bd9Sstevel@tonic-gate bflg++; 4407c478bd9Sstevel@tonic-gate p = optarg; 4417c478bd9Sstevel@tonic-gate if (!p) { 4427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4437c478bd9Sstevel@tonic-gate "Missing maxbits\n")); 4447c478bd9Sstevel@tonic-gate Usage(); 4457c478bd9Sstevel@tonic-gate exit(1); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate maxbits = strtoul(optarg, &p, 10); 4487c478bd9Sstevel@tonic-gate if (*p) { 4497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4507c478bd9Sstevel@tonic-gate "Missing maxbits\n")); 4517c478bd9Sstevel@tonic-gate Usage(); 4527c478bd9Sstevel@tonic-gate exit(1); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate break; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate case 'c': 4577c478bd9Sstevel@tonic-gate cflg++; 4587c478bd9Sstevel@tonic-gate zcat_flg = 1; 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate case 'q': 4617c478bd9Sstevel@tonic-gate qflg++; 4627c478bd9Sstevel@tonic-gate quiet = 1; 4637c478bd9Sstevel@tonic-gate break; 464*da6c28aaSamw case '/': 465*da6c28aaSamw saflg++; 466*da6c28aaSamw break; 4677c478bd9Sstevel@tonic-gate default: 4687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4697c478bd9Sstevel@tonic-gate "Unknown flag: '%c'\n"), optopt); 4707c478bd9Sstevel@tonic-gate Usage(); 4717c478bd9Sstevel@tonic-gate exit(1); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate } /* while */ 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate /* 4767c478bd9Sstevel@tonic-gate * Validate zcat syntax 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (zcat_cmd && (Fflg | Cflg | cflg | 4807c478bd9Sstevel@tonic-gate bflg | qflg | dflg | nomagic)) { 4817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4827c478bd9Sstevel@tonic-gate "Invalid Option\n")); 4837c478bd9Sstevel@tonic-gate Usage(); 4847c478bd9Sstevel@tonic-gate exit(1); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * Process the file list 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) { 4927c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "-") == 0) { 4937c478bd9Sstevel@tonic-gate dash_count++; 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate *fileptr++ = argv[optind]; /* Build input file list */ 4977c478bd9Sstevel@tonic-gate *fileptr = NULL; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (dash_count > 1) { 5017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5027c478bd9Sstevel@tonic-gate gettext("%s may only appear once in the file" 5037c478bd9Sstevel@tonic-gate " list\n"), "\"-\""); 5047c478bd9Sstevel@tonic-gate exit(1); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate if (fileptr - filelist == 0) { 5087c478bd9Sstevel@tonic-gate *fileptr++ = "-"; 5097c478bd9Sstevel@tonic-gate *fileptr = NULL; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (fileptr - filelist > 1 && cflg && !do_decomp) { 5137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5147c478bd9Sstevel@tonic-gate gettext("compress: only one file may be compressed" 5157c478bd9Sstevel@tonic-gate " to stdout\n")); 5167c478bd9Sstevel@tonic-gate exit(1); 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (maxbits < INIT_BITS) 5207c478bd9Sstevel@tonic-gate maxbits = INIT_BITS; 5217c478bd9Sstevel@tonic-gate if (maxbits > BITS) 5227c478bd9Sstevel@tonic-gate maxbits = BITS; 5237c478bd9Sstevel@tonic-gate maxmaxcode = 1 << maxbits; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* Need to open something to close with freopen later */ 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate if ((infile = fopen("/dev/null", "r")) == NULL) { 5287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error opening /dev/null for " 5297c478bd9Sstevel@tonic-gate "input\n")); 5307c478bd9Sstevel@tonic-gate exit(1); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate if ((outfile = fopen("/dev/null", "w")) == NULL) { 5347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error opening /dev/null for " 5357c478bd9Sstevel@tonic-gate "output\n")); 5367c478bd9Sstevel@tonic-gate exit(1); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate for (fileptr = filelist; *fileptr; fileptr++) { 5407c478bd9Sstevel@tonic-gate int jmpval = 0; 5417c478bd9Sstevel@tonic-gate didnt_shrink = 0; 5427c478bd9Sstevel@tonic-gate newline_needed = 0; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate if (do_decomp) { 5457c478bd9Sstevel@tonic-gate /* DECOMPRESSION */ 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if (strcmp(*fileptr, "-") == 0) { 5487c478bd9Sstevel@tonic-gate /* process stdin */ 5497c478bd9Sstevel@tonic-gate inp = stdin; 5507c478bd9Sstevel@tonic-gate outp = stdout; 5517c478bd9Sstevel@tonic-gate use_stdout = 1; 5527c478bd9Sstevel@tonic-gate *fileptr = "stdin"; /* for error messages */ 5537c478bd9Sstevel@tonic-gate } else { 5547c478bd9Sstevel@tonic-gate /* process the named file */ 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate inp = infile; 5577c478bd9Sstevel@tonic-gate outp = outfile; 5587c478bd9Sstevel@tonic-gate use_stdout = 0; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (zcat_flg) { 5617c478bd9Sstevel@tonic-gate use_stdout = 1; 5627c478bd9Sstevel@tonic-gate outp = stdout; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* Check for .Z suffix */ 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate if (strcmp(*fileptr + 5687c478bd9Sstevel@tonic-gate strlen(*fileptr) - 2, ".Z") != 0) { 5697c478bd9Sstevel@tonic-gate /* No .Z: tack one on */ 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if (strlcpy(tempname, *fileptr, 5727c478bd9Sstevel@tonic-gate sizeof (tempname)) >= 5737c478bd9Sstevel@tonic-gate sizeof (tempname)) { 5747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5757c478bd9Sstevel@tonic-gate gettext("%s: filename " 5767c478bd9Sstevel@tonic-gate "too long\n"), 5777c478bd9Sstevel@tonic-gate *fileptr); 5787c478bd9Sstevel@tonic-gate perm_stat = 1; 5797c478bd9Sstevel@tonic-gate continue; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate if (addDotZ(tempname, 5837c478bd9Sstevel@tonic-gate sizeof (tempname)) < 0) { 5847c478bd9Sstevel@tonic-gate perm_stat = 1; 5857c478bd9Sstevel@tonic-gate continue; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate *fileptr = tempname; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* Open input file */ 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate if (stat(*fileptr, &statbuf) < 0) { 5947c478bd9Sstevel@tonic-gate perror(*fileptr); 5957c478bd9Sstevel@tonic-gate perm_stat = 1; 5967c478bd9Sstevel@tonic-gate continue; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if ((freopen(*fileptr, "r", inp)) == NULL) { 6007c478bd9Sstevel@tonic-gate perror(*fileptr); 6017c478bd9Sstevel@tonic-gate perm_stat = 1; 6027c478bd9Sstevel@tonic-gate continue; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* Check the magic number */ 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate if (nomagic == 0) { 6097c478bd9Sstevel@tonic-gate if ((getc(inp) != 6107c478bd9Sstevel@tonic-gate (magic_header[0] & 0xFF)) || 6117c478bd9Sstevel@tonic-gate (getc(inp) != 6127c478bd9Sstevel@tonic-gate (magic_header[1] & 0xFF))) { 6137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6147c478bd9Sstevel@tonic-gate "%s: not in compressed " 6157c478bd9Sstevel@tonic-gate "format\n"), 6167c478bd9Sstevel@tonic-gate *fileptr); 6177c478bd9Sstevel@tonic-gate perm_stat = 1; 6187c478bd9Sstevel@tonic-gate continue; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* set -b from file */ 6227c478bd9Sstevel@tonic-gate if ((maxbits = getc(inp)) == EOF && 6237c478bd9Sstevel@tonic-gate ferror(inp)) { 6247c478bd9Sstevel@tonic-gate perror(*fileptr); 6257c478bd9Sstevel@tonic-gate perm_stat = 1; 6267c478bd9Sstevel@tonic-gate continue; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate block_compress = maxbits & BLOCK_MASK; 6307c478bd9Sstevel@tonic-gate maxbits &= BIT_MASK; 6317c478bd9Sstevel@tonic-gate maxmaxcode = 1 << maxbits; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (maxbits > BITS) { 6347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6357c478bd9Sstevel@tonic-gate gettext("%s: compressed " 6367c478bd9Sstevel@tonic-gate "with %d bits, " 6377c478bd9Sstevel@tonic-gate "can only handle" 6387c478bd9Sstevel@tonic-gate " %d bits\n"), 6397c478bd9Sstevel@tonic-gate *fileptr, maxbits, BITS); 6407c478bd9Sstevel@tonic-gate perm_stat = 1; 6417c478bd9Sstevel@tonic-gate continue; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate if (!use_stdout) { 6467c478bd9Sstevel@tonic-gate /* Generate output filename */ 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if (strlcpy(ofname, *fileptr, 6497c478bd9Sstevel@tonic-gate sizeof (ofname)) >= 6507c478bd9Sstevel@tonic-gate sizeof (ofname)) { 6517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6527c478bd9Sstevel@tonic-gate gettext("%s: filename " 6537c478bd9Sstevel@tonic-gate "too long\n"), 6547c478bd9Sstevel@tonic-gate *fileptr); 6557c478bd9Sstevel@tonic-gate perm_stat = 1; 6567c478bd9Sstevel@tonic-gate continue; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate /* Strip off .Z */ 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate ofname[strlen(*fileptr) - 2] = '\0'; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate } else { 6647c478bd9Sstevel@tonic-gate /* COMPRESSION */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (strcmp(*fileptr, "-") == 0) { 6677c478bd9Sstevel@tonic-gate /* process stdin */ 6687c478bd9Sstevel@tonic-gate inp = stdin; 6697c478bd9Sstevel@tonic-gate outp = stdout; 6707c478bd9Sstevel@tonic-gate use_stdout = 1; 6717c478bd9Sstevel@tonic-gate *fileptr = "stdin"; /* for error messages */ 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* Use the largest possible hash table */ 6747c478bd9Sstevel@tonic-gate hsize = HSIZE; 6757c478bd9Sstevel@tonic-gate } else { 6767c478bd9Sstevel@tonic-gate /* process the named file */ 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate inp = infile; 6797c478bd9Sstevel@tonic-gate outp = outfile; 6807c478bd9Sstevel@tonic-gate use_stdout = 0; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (zcat_flg) { 6837c478bd9Sstevel@tonic-gate use_stdout = 1; 6847c478bd9Sstevel@tonic-gate outp = stdout; 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (strcmp(*fileptr + 6887c478bd9Sstevel@tonic-gate strlen(*fileptr) - 2, ".Z") == 0) { 6897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6907c478bd9Sstevel@tonic-gate "%s: already has .Z " 6917c478bd9Sstevel@tonic-gate "suffix -- no change\n"), 6927c478bd9Sstevel@tonic-gate *fileptr); 6937c478bd9Sstevel@tonic-gate perm_stat = 1; 6947c478bd9Sstevel@tonic-gate continue; 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate /* Open input file */ 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if (stat(*fileptr, &statbuf) < 0) { 6997c478bd9Sstevel@tonic-gate perror(*fileptr); 7007c478bd9Sstevel@tonic-gate perm_stat = 1; 7017c478bd9Sstevel@tonic-gate continue; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if ((freopen(*fileptr, "r", inp)) == NULL) { 7057c478bd9Sstevel@tonic-gate perror(*fileptr); 7067c478bd9Sstevel@tonic-gate perm_stat = 1; 7077c478bd9Sstevel@tonic-gate continue; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate fsize = (off_t)statbuf.st_size; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* 7137c478bd9Sstevel@tonic-gate * tune hash table size for small 7147c478bd9Sstevel@tonic-gate * files -- ad hoc, 7157c478bd9Sstevel@tonic-gate * but the sizes match earlier #defines, which 7167c478bd9Sstevel@tonic-gate * serve as upper bounds on the number of 7177c478bd9Sstevel@tonic-gate * output codes. 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate hsize = HSIZE; 7207c478bd9Sstevel@tonic-gate if (fsize < (1 << 12)) 7217c478bd9Sstevel@tonic-gate hsize = min(5003, HSIZE); 7227c478bd9Sstevel@tonic-gate else if (fsize < (1 << 13)) 7237c478bd9Sstevel@tonic-gate hsize = min(9001, HSIZE); 7247c478bd9Sstevel@tonic-gate else if (fsize < (1 << 14)) 7257c478bd9Sstevel@tonic-gate hsize = min(18013, HSIZE); 7267c478bd9Sstevel@tonic-gate else if (fsize < (1 << 15)) 7277c478bd9Sstevel@tonic-gate hsize = min(35023, HSIZE); 7287c478bd9Sstevel@tonic-gate else if (fsize < 47000) 7297c478bd9Sstevel@tonic-gate hsize = min(50021, HSIZE); 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate if (!use_stdout) { 7327c478bd9Sstevel@tonic-gate /* Generate output filename */ 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate if (strlcpy(ofname, *fileptr, 7357c478bd9Sstevel@tonic-gate sizeof (ofname)) >= 7367c478bd9Sstevel@tonic-gate sizeof (ofname)) { 7377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7387c478bd9Sstevel@tonic-gate gettext("%s: filename " 7397c478bd9Sstevel@tonic-gate "too long\n"), 7407c478bd9Sstevel@tonic-gate *fileptr); 7417c478bd9Sstevel@tonic-gate perm_stat = 1; 7427c478bd9Sstevel@tonic-gate continue; 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate if (addDotZ(ofname, 7467c478bd9Sstevel@tonic-gate sizeof (ofname)) < 0) { 7477c478bd9Sstevel@tonic-gate perm_stat = 1; 7487c478bd9Sstevel@tonic-gate continue; 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate } /* if (do_decomp) */ 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate /* Check for overwrite of existing file */ 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate if (!overwrite && !use_stdout) { 7577c478bd9Sstevel@tonic-gate if (stat(ofname, &ostatbuf) == 0) { 7587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7597c478bd9Sstevel@tonic-gate "%s already exists;"), ofname); 7607c478bd9Sstevel@tonic-gate if (bgnd_flag == 0 && isatty(2)) { 7617c478bd9Sstevel@tonic-gate int cin; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7647c478bd9Sstevel@tonic-gate " do you wish to overwr" 7657c478bd9Sstevel@tonic-gate "ite %s (%s or %s)? "), 7667c478bd9Sstevel@tonic-gate ofname, yesstr, nostr); 7677c478bd9Sstevel@tonic-gate (void) fflush(stderr); 7683d63ea05Sas145665 for (cin = 0; cin < LINE_MAX; cin++) 7697c478bd9Sstevel@tonic-gate line[cin] = 0; 7707c478bd9Sstevel@tonic-gate (void) read(2, line, LINE_MAX); 7717c478bd9Sstevel@tonic-gate 7723d63ea05Sas145665 if (yes_check(line) == 0) { 7737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7747c478bd9Sstevel@tonic-gate gettext( 7757c478bd9Sstevel@tonic-gate "\tnot overwri" 7767c478bd9Sstevel@tonic-gate "tten\n")); 7777c478bd9Sstevel@tonic-gate continue; 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate } else { 7807c478bd9Sstevel@tonic-gate /* 7817c478bd9Sstevel@tonic-gate * XPG4: Assertion 1009 7827c478bd9Sstevel@tonic-gate * Standard input is not 7837c478bd9Sstevel@tonic-gate * terminal, and no '-f', 7847c478bd9Sstevel@tonic-gate * and file exists. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7887c478bd9Sstevel@tonic-gate "%s: File exists, -f not" 7897c478bd9Sstevel@tonic-gate " specified, and ru" 7907c478bd9Sstevel@tonic-gate "nning in the backgro" 7917c478bd9Sstevel@tonic-gate "und.\n"), *fileptr); 7927c478bd9Sstevel@tonic-gate perm_stat = 1; 7937c478bd9Sstevel@tonic-gate continue; 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate if (!use_stdout) { 798*da6c28aaSamw if ((pathconf(ofname, _PC_XATTR_EXISTS) == 1) || 799*da6c28aaSamw (saflg && sysattr_support(ofname, 800*da6c28aaSamw _PC_SATTR_EXISTS) == 1)) { 8017c478bd9Sstevel@tonic-gate (void) unlink(ofname); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate /* Open output file */ 8047c478bd9Sstevel@tonic-gate if (freopen(ofname, "w", outp) == NULL) { 8057c478bd9Sstevel@tonic-gate perror(ofname); 8067c478bd9Sstevel@tonic-gate perm_stat = 1; 8077c478bd9Sstevel@tonic-gate continue; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate precious = 0; 8107c478bd9Sstevel@tonic-gate if (!quiet) { 8117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 8127c478bd9Sstevel@tonic-gate *fileptr); 8137c478bd9Sstevel@tonic-gate newline_needed = 1; 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate } else if (!quiet && !do_decomp) { 8167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 8177c478bd9Sstevel@tonic-gate *fileptr); 8187c478bd9Sstevel@tonic-gate newline_needed = 1; 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* Actually do the compression/decompression */ 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate if ((jmpval = setjmp(env)) == 0) { 8247c478bd9Sstevel@tonic-gate /* We'll see how things go */ 8257c478bd9Sstevel@tonic-gate #ifndef DEBUG 8267c478bd9Sstevel@tonic-gate if (do_decomp == 0) { 8277c478bd9Sstevel@tonic-gate compress(); 8287c478bd9Sstevel@tonic-gate } else { 8297c478bd9Sstevel@tonic-gate decompress(); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate #else 8327c478bd9Sstevel@tonic-gate if (do_decomp == 0) { 8337c478bd9Sstevel@tonic-gate compress(); 8347c478bd9Sstevel@tonic-gate } else if (debug == 0) { 8357c478bd9Sstevel@tonic-gate decompress(); 8367c478bd9Sstevel@tonic-gate } else { 8377c478bd9Sstevel@tonic-gate printcodes(); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate if (verbose) { 8417c478bd9Sstevel@tonic-gate dump_tab(); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate #endif 8447c478bd9Sstevel@tonic-gate } else { 8457c478bd9Sstevel@tonic-gate /* 8467c478bd9Sstevel@tonic-gate * Things went badly - clean up and go on. 8477c478bd9Sstevel@tonic-gate * jmpval's values break down as follows: 8487c478bd9Sstevel@tonic-gate * 1 == message determined by ferror() values. 8497c478bd9Sstevel@tonic-gate * 2 == input problem message needed. 8507c478bd9Sstevel@tonic-gate * 3 == output problem message needed. 8517c478bd9Sstevel@tonic-gate */ 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate if (ferror(inp) || jmpval == 2) { 8547c478bd9Sstevel@tonic-gate if (do_decomp) { 8557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 8567c478bd9Sstevel@tonic-gate "uncompress: %s: corrupt" 8577c478bd9Sstevel@tonic-gate " input\n"), *fileptr); 8587c478bd9Sstevel@tonic-gate } else { 8597c478bd9Sstevel@tonic-gate perror(*fileptr); 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate if (ferror(outp) || jmpval == 3) { 8647c478bd9Sstevel@tonic-gate /* handle output errors */ 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate if (use_stdout) { 8677c478bd9Sstevel@tonic-gate perror(""); 8687c478bd9Sstevel@tonic-gate } else { 8697c478bd9Sstevel@tonic-gate perror(ofname); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate if (ofname[0] != '\0') { 8747c478bd9Sstevel@tonic-gate if (unlink(ofname) < 0) { 8757c478bd9Sstevel@tonic-gate perror(ofname); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate ofname[0] = '\0'; 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate perm_stat = 1; 8827c478bd9Sstevel@tonic-gate continue; 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate /* Things went well */ 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate if (!use_stdout) { 8887c478bd9Sstevel@tonic-gate /* Copy stats */ 8897c478bd9Sstevel@tonic-gate copystat(*fileptr, &statbuf, ofname); 8907c478bd9Sstevel@tonic-gate precious = 1; 8917c478bd9Sstevel@tonic-gate if (newline_needed) { 8927c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * Print the info. for unchanged file 8967c478bd9Sstevel@tonic-gate * when no -v 8977c478bd9Sstevel@tonic-gate */ 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate if (didnt_shrink) { 9007c478bd9Sstevel@tonic-gate if (!force && perm_stat == 0) { 9017c478bd9Sstevel@tonic-gate if (quiet) { 9027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 9037c478bd9Sstevel@tonic-gate "%s: -- file " 9047c478bd9Sstevel@tonic-gate "unchanged\n"), 9057c478bd9Sstevel@tonic-gate *fileptr); 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate perm_stat = 2; 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate } else { 9127c478bd9Sstevel@tonic-gate if (didnt_shrink && !force && perm_stat == 0) { 9137c478bd9Sstevel@tonic-gate perm_stat = 2; 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate if (newline_needed) { 9177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate } /* for */ 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate return (perm_stat); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate static void 9267c478bd9Sstevel@tonic-gate cinterr(int hshift) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate /* we have exceeded the hash table */ 9297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9307c478bd9Sstevel@tonic-gate "internal error: hashtable exceeded - hsize = %ld\n", hsize); 9317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "hshift = %d, %d\n", hshift, (1 << hshift) -1); 9327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "maxbits = %d\n", maxbits); 9337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "n_bits = %d\n", n_bits); 9347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "maxcode = %ld\n", maxcode); 9357c478bd9Sstevel@tonic-gate longjmp(env, 1); 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate static code_int 9397c478bd9Sstevel@tonic-gate adjusti(code_int i, code_int hsize_reg) 9407c478bd9Sstevel@tonic-gate { 9417c478bd9Sstevel@tonic-gate while (i < 0) { 9427c478bd9Sstevel@tonic-gate i += hsize_reg; 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate while (i >= hsize_reg) { 9467c478bd9Sstevel@tonic-gate i -= hsize_reg; 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate return (i); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* 9527c478bd9Sstevel@tonic-gate * compress inp to outp 9537c478bd9Sstevel@tonic-gate * 9547c478bd9Sstevel@tonic-gate * Algorithm: use open addressing double hashing(no chaining) on the 9557c478bd9Sstevel@tonic-gate * prefix code / next character combination. We do a variant of Knuth's 9567c478bd9Sstevel@tonic-gate * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime 9577c478bd9Sstevel@tonic-gate * secondary probe. Here, the modular division first probe is gives way 9587c478bd9Sstevel@tonic-gate * to a faster exclusive-or manipulation. Also do block compression with 9597c478bd9Sstevel@tonic-gate * an adaptive reset, whereby the code table is cleared when the compression 9607c478bd9Sstevel@tonic-gate * ratio decreases, but after the table fills. The variable-length output 9617c478bd9Sstevel@tonic-gate * codes are re-sized at this point, and a special CLEAR code is generated 9627c478bd9Sstevel@tonic-gate * for the decompressor. Late addition: construct the table according to 9637c478bd9Sstevel@tonic-gate * file size for noticeable speed improvement on small files. Please direct 9647c478bd9Sstevel@tonic-gate * questions about this implementation to ames!jaw. 9657c478bd9Sstevel@tonic-gate */ 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate static void 9687c478bd9Sstevel@tonic-gate compress() 9697c478bd9Sstevel@tonic-gate { 9707c478bd9Sstevel@tonic-gate long fcode; 9717c478bd9Sstevel@tonic-gate code_int i = 0; 9727c478bd9Sstevel@tonic-gate int c; 9737c478bd9Sstevel@tonic-gate code_int ent; 9747c478bd9Sstevel@tonic-gate int disp; 9757c478bd9Sstevel@tonic-gate code_int hsize_reg; 9767c478bd9Sstevel@tonic-gate int hshift; 9777c478bd9Sstevel@tonic-gate int probecnt; 9787c478bd9Sstevel@tonic-gate count_long in_count; 9797c478bd9Sstevel@tonic-gate uint32_t inchi, inclo; 9807c478bd9Sstevel@tonic-gate int maxbits_reg; 9817c478bd9Sstevel@tonic-gate FILE *fin = inp; 9827c478bd9Sstevel@tonic-gate #ifdef DEBUG 9837c478bd9Sstevel@tonic-gate count_long out_count = 0; 9847c478bd9Sstevel@tonic-gate #endif 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate if (nomagic == 0) { 9877c478bd9Sstevel@tonic-gate if ((putc(magic_header[0], outp) == EOF || 9887c478bd9Sstevel@tonic-gate putc(magic_header[1], outp) == EOF || 9897c478bd9Sstevel@tonic-gate putc((char)(maxbits | block_compress), 9907c478bd9Sstevel@tonic-gate outp) == EOF) && 9917c478bd9Sstevel@tonic-gate ferror(outp)) { 9927c478bd9Sstevel@tonic-gate ioerror(); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate offset = 0; 9977c478bd9Sstevel@tonic-gate bytes_out = 3; /* includes 3-byte header mojo */ 9987c478bd9Sstevel@tonic-gate clear_flg = 0; 9997c478bd9Sstevel@tonic-gate ratio = 0; 10007c478bd9Sstevel@tonic-gate in_count = 1; 10017c478bd9Sstevel@tonic-gate inchi = 0; 10027c478bd9Sstevel@tonic-gate inclo = 1; 10037c478bd9Sstevel@tonic-gate checkpoint = CHECK_GAP; 10047c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 10057c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate if ((ent = getc(fin)) == EOF && ferror(fin)) { 10087c478bd9Sstevel@tonic-gate ioerror(); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate hshift = 0; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L) 10147c478bd9Sstevel@tonic-gate hshift++; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate hshift = 8 - hshift; /* set hash code range bound */ 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate hsize_reg = hsize; 10197c478bd9Sstevel@tonic-gate maxbits_reg = maxbits; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate cl_hash((count_int) hsize_reg); /* clear hash table */ 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate while ((c = getc(fin)) != EOF) { 10247c478bd9Sstevel@tonic-gate if (++inclo == 0) 10257c478bd9Sstevel@tonic-gate inchi++; 10267c478bd9Sstevel@tonic-gate fcode = (long)(((long)c << maxbits_reg) + ent); 10277c478bd9Sstevel@tonic-gate i = ((c << hshift) ^ ent); /* xor hashing */ 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if ((unsigned int)i >= hsize_reg) 10307c478bd9Sstevel@tonic-gate i = adjusti(i, hsize_reg); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate if (htabof(i) == fcode) { 10337c478bd9Sstevel@tonic-gate ent = codetabof(i); 10347c478bd9Sstevel@tonic-gate continue; 10357c478bd9Sstevel@tonic-gate } else if ((long)htabof(i) < 0) { 10367c478bd9Sstevel@tonic-gate /* empty slot */ 10377c478bd9Sstevel@tonic-gate goto nomatch; 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* secondary hash (after G. Knott) */ 10417c478bd9Sstevel@tonic-gate disp = hsize_reg - i; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate if (i == 0) { 10447c478bd9Sstevel@tonic-gate disp = 1; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate probecnt = 0; 10487c478bd9Sstevel@tonic-gate probe: 10497c478bd9Sstevel@tonic-gate if (++probecnt > hsize_reg) 10507c478bd9Sstevel@tonic-gate cinterr(hshift); 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if ((i -= disp) < 0) { 10537c478bd9Sstevel@tonic-gate while (i < 0) 10547c478bd9Sstevel@tonic-gate i += hsize_reg; 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate if (htabof(i) == fcode) { 10587c478bd9Sstevel@tonic-gate ent = codetabof(i); 10597c478bd9Sstevel@tonic-gate continue; 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate if ((long)htabof(i) > 0) { 10637c478bd9Sstevel@tonic-gate goto probe; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate nomatch: 10667c478bd9Sstevel@tonic-gate output((code_int) ent); 10677c478bd9Sstevel@tonic-gate #ifdef DEBUG 10687c478bd9Sstevel@tonic-gate out_count++; 10697c478bd9Sstevel@tonic-gate #endif 10707c478bd9Sstevel@tonic-gate ent = c; 10717c478bd9Sstevel@tonic-gate if (free_ent < maxmaxcode) { 10727c478bd9Sstevel@tonic-gate codetabof(i) = free_ent++; 10737c478bd9Sstevel@tonic-gate /* code -> hashtable */ 10747c478bd9Sstevel@tonic-gate htabof(i) = fcode; 10757c478bd9Sstevel@tonic-gate } else { 10767c478bd9Sstevel@tonic-gate in_count = ((long long)inchi<<32|inclo); 10777c478bd9Sstevel@tonic-gate if ((count_long)in_count >= 10787c478bd9Sstevel@tonic-gate (count_long)checkpoint && block_compress) { 10797c478bd9Sstevel@tonic-gate cl_block(in_count); 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate in_count = ((long long)inchi<<32|inclo); 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate if (ferror(fin) != 0) { 10877c478bd9Sstevel@tonic-gate ioerror(); 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate /* 10917c478bd9Sstevel@tonic-gate * Put out the final code. 10927c478bd9Sstevel@tonic-gate */ 10937c478bd9Sstevel@tonic-gate output((code_int)ent); 10947c478bd9Sstevel@tonic-gate #ifdef DEBUG 10957c478bd9Sstevel@tonic-gate out_count++; 10967c478bd9Sstevel@tonic-gate #endif 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate output((code_int)-1); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * Print out stats on stderr 11027c478bd9Sstevel@tonic-gate */ 11037c478bd9Sstevel@tonic-gate if (!quiet) { 11047c478bd9Sstevel@tonic-gate #ifdef DEBUG 11057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11067c478bd9Sstevel@tonic-gate "%lld chars in, %lld codes (%lld bytes) out, " 11077c478bd9Sstevel@tonic-gate "compression factor: ", 11087c478bd9Sstevel@tonic-gate (count_long)in_count, (count_long)out_count, 11097c478bd9Sstevel@tonic-gate (count_long) bytes_out); 11107c478bd9Sstevel@tonic-gate prratio(stderr, (count_long)in_count, 11117c478bd9Sstevel@tonic-gate (count_long)bytes_out); 11127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 11137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tCompression as in compact: "); 11147c478bd9Sstevel@tonic-gate prratio(stderr, 11157c478bd9Sstevel@tonic-gate (count_long)in_count-(count_long)bytes_out, 11167c478bd9Sstevel@tonic-gate (count_long)in_count); 11177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 11187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11197c478bd9Sstevel@tonic-gate "\tLargest code (of last block) was %d" 11207c478bd9Sstevel@tonic-gate " (%d bits)\n", 11217c478bd9Sstevel@tonic-gate free_ent - 1, n_bits); 11227c478bd9Sstevel@tonic-gate #else /* !DEBUG */ 11237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Compression: ")); 11247c478bd9Sstevel@tonic-gate prratio(stderr, 11257c478bd9Sstevel@tonic-gate (count_long)in_count-(count_long)bytes_out, 11267c478bd9Sstevel@tonic-gate (count_long)in_count); 11277c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate /* report if no savings */ 11307c478bd9Sstevel@tonic-gate if ((count_long)bytes_out > (count_long)in_count) { 11317c478bd9Sstevel@tonic-gate didnt_shrink = 1; 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate /* 11367c478bd9Sstevel@tonic-gate * ************************************************************** 11377c478bd9Sstevel@tonic-gate * TAG(output) 11387c478bd9Sstevel@tonic-gate * 11397c478bd9Sstevel@tonic-gate * Output the given code. 11407c478bd9Sstevel@tonic-gate * Inputs: 11417c478bd9Sstevel@tonic-gate * code: A n_bits-bit integer. If == -1, then EOF. This assumes 11427c478bd9Sstevel@tonic-gate * that n_bits = < (long)wordsize - 1. 11437c478bd9Sstevel@tonic-gate * Outputs: 11447c478bd9Sstevel@tonic-gate * Outputs code to the file. 11457c478bd9Sstevel@tonic-gate * Assumptions: 11467c478bd9Sstevel@tonic-gate * Chars are 8 bits long. 11477c478bd9Sstevel@tonic-gate * Algorithm: 11487c478bd9Sstevel@tonic-gate * Maintain a BITS character long buffer(so that 8 codes will 11497c478bd9Sstevel@tonic-gate * fit in it exactly). Use the VAX insv instruction to insert each 11507c478bd9Sstevel@tonic-gate * code in turn. When the buffer fills up empty it and start over. 11517c478bd9Sstevel@tonic-gate */ 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate static void 11547c478bd9Sstevel@tonic-gate output(code_int code) 11557c478bd9Sstevel@tonic-gate { 11567c478bd9Sstevel@tonic-gate #ifdef DEBUG 11577c478bd9Sstevel@tonic-gate static int col = 0; 11587c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate int r_off = offset, bits = n_bits; 11617c478bd9Sstevel@tonic-gate char *bp = buf; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate #ifdef DEBUG 11647c478bd9Sstevel@tonic-gate if (verbose) 11657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d%c", code, 11667c478bd9Sstevel@tonic-gate (col += 6) >= 74 ? (col = 0, '\n') : ' '); 11677c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11687c478bd9Sstevel@tonic-gate if (code >= 0) { 11697c478bd9Sstevel@tonic-gate /* 11707c478bd9Sstevel@tonic-gate * byte/bit numbering on the VAX is simulated 11717c478bd9Sstevel@tonic-gate * by the following code 11727c478bd9Sstevel@tonic-gate */ 11737c478bd9Sstevel@tonic-gate /* 11747c478bd9Sstevel@tonic-gate * Get to the first byte. 11757c478bd9Sstevel@tonic-gate */ 11767c478bd9Sstevel@tonic-gate bp += (r_off >> 3); 11777c478bd9Sstevel@tonic-gate r_off &= 7; 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * Since code is always >= 8 bits, only need to mask the first 11807c478bd9Sstevel@tonic-gate * hunk on the left. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; 11837c478bd9Sstevel@tonic-gate bp++; 11847c478bd9Sstevel@tonic-gate bits -= (8 - r_off); 11857c478bd9Sstevel@tonic-gate code >>= 8 - r_off; 11867c478bd9Sstevel@tonic-gate /* 11877c478bd9Sstevel@tonic-gate * Get any 8 bit parts in the middle (<=1 for up to 16 11887c478bd9Sstevel@tonic-gate * bits). 11897c478bd9Sstevel@tonic-gate */ 11907c478bd9Sstevel@tonic-gate if (bits >= 8) { 11917c478bd9Sstevel@tonic-gate *bp++ = code; 11927c478bd9Sstevel@tonic-gate code >>= 8; 11937c478bd9Sstevel@tonic-gate bits -= 8; 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate /* Last bits. */ 11967c478bd9Sstevel@tonic-gate if (bits) 11977c478bd9Sstevel@tonic-gate *bp = code; 11987c478bd9Sstevel@tonic-gate offset += n_bits; 11997c478bd9Sstevel@tonic-gate if (offset == (n_bits << 3)) { 12007c478bd9Sstevel@tonic-gate bp = buf; 12017c478bd9Sstevel@tonic-gate bits = n_bits; 12027c478bd9Sstevel@tonic-gate bytes_out += bits; 12037c478bd9Sstevel@tonic-gate do { 12047c478bd9Sstevel@tonic-gate if (putc(*bp, outp) == EOF && 12057c478bd9Sstevel@tonic-gate ferror(outp)) { 12067c478bd9Sstevel@tonic-gate ioerror(); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate bp++; 12097c478bd9Sstevel@tonic-gate } while (--bits); 12107c478bd9Sstevel@tonic-gate offset = 0; 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* 12147c478bd9Sstevel@tonic-gate * If the next entry is going to be too big for the code size, 12157c478bd9Sstevel@tonic-gate * then increase it, if possible. 12167c478bd9Sstevel@tonic-gate */ 12177c478bd9Sstevel@tonic-gate if (free_ent > maxcode || (clear_flg > 0)) { 12187c478bd9Sstevel@tonic-gate /* 12197c478bd9Sstevel@tonic-gate * Write the whole buffer, because the input 12207c478bd9Sstevel@tonic-gate * side won't discover the size increase until 12217c478bd9Sstevel@tonic-gate * after it has read it. 12227c478bd9Sstevel@tonic-gate */ 12237c478bd9Sstevel@tonic-gate if (offset > 0) { 12247c478bd9Sstevel@tonic-gate if (fwrite(buf, 1, n_bits, outp) != n_bits) { 12257c478bd9Sstevel@tonic-gate longjmp(env, 3); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate bytes_out += n_bits; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate offset = 0; 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate if (clear_flg) { 12327c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 12337c478bd9Sstevel@tonic-gate clear_flg = 0; 12347c478bd9Sstevel@tonic-gate } else { 12357c478bd9Sstevel@tonic-gate n_bits++; 12367c478bd9Sstevel@tonic-gate if (n_bits == maxbits) 12377c478bd9Sstevel@tonic-gate maxcode = maxmaxcode; 12387c478bd9Sstevel@tonic-gate else 12397c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate #ifdef DEBUG 12427c478bd9Sstevel@tonic-gate if (debug) { 12437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12447c478bd9Sstevel@tonic-gate "\nChange to %d bits\n", n_bits); 12457c478bd9Sstevel@tonic-gate col = 0; 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate } else { 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * At EOF, write the rest of the buffer. 12527c478bd9Sstevel@tonic-gate */ 12537c478bd9Sstevel@tonic-gate if (offset > 0) { 12547c478bd9Sstevel@tonic-gate if (fwrite(buf, 1, (offset + 7) / 8, outp) == 0 && 12557c478bd9Sstevel@tonic-gate ferror(outp)) { 12567c478bd9Sstevel@tonic-gate ioerror(); 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate bytes_out += (offset + 7) / 8; 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate offset = 0; 12617c478bd9Sstevel@tonic-gate (void) fflush(outp); 12627c478bd9Sstevel@tonic-gate #ifdef DEBUG 12637c478bd9Sstevel@tonic-gate if (verbose) 12647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 12657c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12667c478bd9Sstevel@tonic-gate if (ferror(outp)) 12677c478bd9Sstevel@tonic-gate ioerror(); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * Decompress inp to outp. This routine adapts to the codes in the 12737c478bd9Sstevel@tonic-gate * file building the "string" table on-the-fly; requiring no table to 12747c478bd9Sstevel@tonic-gate * be stored in the compressed file. The tables used herein are shared 12757c478bd9Sstevel@tonic-gate * with those of the compress() routine. See the definitions above. 12767c478bd9Sstevel@tonic-gate */ 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate static void 12797c478bd9Sstevel@tonic-gate decompress() 12807c478bd9Sstevel@tonic-gate { 12817c478bd9Sstevel@tonic-gate char_type *stackp, *stack_lim; 12827c478bd9Sstevel@tonic-gate int finchar; 12837c478bd9Sstevel@tonic-gate code_int code, oldcode, incode; 12847c478bd9Sstevel@tonic-gate FILE *fout = outp; 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* 12877c478bd9Sstevel@tonic-gate * As above, initialize the first 256 entries in the table. 12887c478bd9Sstevel@tonic-gate */ 12897c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 12907c478bd9Sstevel@tonic-gate for (code = 255; code >= 0; code--) { 12917c478bd9Sstevel@tonic-gate tab_prefixof(code) = 0; 12927c478bd9Sstevel@tonic-gate tab_suffixof(code) = (char_type)code; 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate finchar = oldcode = getcode(); 12977c478bd9Sstevel@tonic-gate if (oldcode == -1) /* EOF already? */ 12987c478bd9Sstevel@tonic-gate return; /* Get out of here */ 12997c478bd9Sstevel@tonic-gate /* first code must be 8 bits = char */ 13007c478bd9Sstevel@tonic-gate if (putc((char)finchar, outp) == EOF && ferror(outp)) { 13017c478bd9Sstevel@tonic-gate /* Crash if can't write */ 13027c478bd9Sstevel@tonic-gate ioerror(); 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate stackp = de_stack; 13057c478bd9Sstevel@tonic-gate stack_lim = stack_max; 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate while ((code = getcode()) > -1) { 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate if ((code == CLEAR) && block_compress) { 13107c478bd9Sstevel@tonic-gate for (code = 255; code >= 0; code--) 13117c478bd9Sstevel@tonic-gate tab_prefixof(code) = 0; 13127c478bd9Sstevel@tonic-gate clear_flg = 1; 13137c478bd9Sstevel@tonic-gate free_ent = FIRST - 1; 13147c478bd9Sstevel@tonic-gate if ((code = getcode()) == -1) /* O, untimely death! */ 13157c478bd9Sstevel@tonic-gate break; 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate incode = code; 13187c478bd9Sstevel@tonic-gate /* 13197c478bd9Sstevel@tonic-gate * Special case for KwKwK string. 13207c478bd9Sstevel@tonic-gate */ 13217c478bd9Sstevel@tonic-gate if (code >= free_ent) { 13227c478bd9Sstevel@tonic-gate if (stackp < stack_lim) { 13237c478bd9Sstevel@tonic-gate *stackp++ = (char_type) finchar; 13247c478bd9Sstevel@tonic-gate code = oldcode; 13257c478bd9Sstevel@tonic-gate } else { 13267c478bd9Sstevel@tonic-gate /* badness */ 13277c478bd9Sstevel@tonic-gate longjmp(env, 2); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate /* 13327c478bd9Sstevel@tonic-gate * Generate output characters in reverse order 13337c478bd9Sstevel@tonic-gate */ 13347c478bd9Sstevel@tonic-gate while (code >= 256) { 13357c478bd9Sstevel@tonic-gate if (stackp < stack_lim) { 13367c478bd9Sstevel@tonic-gate *stackp++ = tab_suffixof(code); 13377c478bd9Sstevel@tonic-gate code = tab_prefixof(code); 13387c478bd9Sstevel@tonic-gate } else { 13397c478bd9Sstevel@tonic-gate /* badness */ 13407c478bd9Sstevel@tonic-gate longjmp(env, 2); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate *stackp++ = finchar = tab_suffixof(code); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate /* 13467c478bd9Sstevel@tonic-gate * And put them out in forward order 13477c478bd9Sstevel@tonic-gate */ 13487c478bd9Sstevel@tonic-gate do { 13497c478bd9Sstevel@tonic-gate stackp--; 13507c478bd9Sstevel@tonic-gate (void) putc(*stackp, fout); 13517c478bd9Sstevel@tonic-gate } while (stackp > de_stack); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (ferror(fout)) 13547c478bd9Sstevel@tonic-gate ioerror(); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* 13577c478bd9Sstevel@tonic-gate * Generate the new entry. 13587c478bd9Sstevel@tonic-gate */ 13597c478bd9Sstevel@tonic-gate if ((code = free_ent) < maxmaxcode) { 13607c478bd9Sstevel@tonic-gate tab_prefixof(code) = (unsigned short) oldcode; 13617c478bd9Sstevel@tonic-gate tab_suffixof(code) = (char_type) finchar; 13627c478bd9Sstevel@tonic-gate free_ent = code+1; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate /* 13657c478bd9Sstevel@tonic-gate * Remember previous code. 13667c478bd9Sstevel@tonic-gate */ 13677c478bd9Sstevel@tonic-gate oldcode = incode; 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate (void) fflush(outp); 13707c478bd9Sstevel@tonic-gate if (ferror(outp)) 13717c478bd9Sstevel@tonic-gate ioerror(); 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * ************************************************************** 13767c478bd9Sstevel@tonic-gate * TAG( getcode ) 13777c478bd9Sstevel@tonic-gate * 13787c478bd9Sstevel@tonic-gate * Read one code from the standard input. If EOF, return -1. 13797c478bd9Sstevel@tonic-gate * Inputs: 13807c478bd9Sstevel@tonic-gate * inp 13817c478bd9Sstevel@tonic-gate * Outputs: 13827c478bd9Sstevel@tonic-gate * code or -1 is returned. 13837c478bd9Sstevel@tonic-gate */ 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate code_int 13867c478bd9Sstevel@tonic-gate getcode() { 13877c478bd9Sstevel@tonic-gate code_int code; 13887c478bd9Sstevel@tonic-gate static int offset = 0, size = 0; 13897c478bd9Sstevel@tonic-gate static char_type buf[BITS]; 13907c478bd9Sstevel@tonic-gate int r_off, bits; 13917c478bd9Sstevel@tonic-gate char_type *bp = buf; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate if (clear_flg > 0 || offset >= size || free_ent > maxcode) { 13947c478bd9Sstevel@tonic-gate /* 13957c478bd9Sstevel@tonic-gate * If the next entry will be too big for the current code 13967c478bd9Sstevel@tonic-gate * size, then we must increase the size. This implies reading 13977c478bd9Sstevel@tonic-gate * a new buffer full, too. 13987c478bd9Sstevel@tonic-gate */ 13997c478bd9Sstevel@tonic-gate if (free_ent > maxcode) { 14007c478bd9Sstevel@tonic-gate n_bits++; 14017c478bd9Sstevel@tonic-gate if (n_bits == maxbits) 14027c478bd9Sstevel@tonic-gate /* won't get any bigger now */ 14037c478bd9Sstevel@tonic-gate maxcode = maxmaxcode; 14047c478bd9Sstevel@tonic-gate else 14057c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate if (clear_flg > 0) { 14087c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 14097c478bd9Sstevel@tonic-gate clear_flg = 0; 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate size = fread(buf, 1, n_bits, inp); 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate if (size <= 0) { 14147c478bd9Sstevel@tonic-gate if (feof(inp)) { 14157c478bd9Sstevel@tonic-gate /* end of file */ 14167c478bd9Sstevel@tonic-gate return (-1); 14177c478bd9Sstevel@tonic-gate } else if (ferror(inp)) { 14187c478bd9Sstevel@tonic-gate ioerror(); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate offset = 0; 14237c478bd9Sstevel@tonic-gate /* Round size down to integral number of codes */ 14247c478bd9Sstevel@tonic-gate size = (size << 3) - (n_bits - 1); 14257c478bd9Sstevel@tonic-gate } 14267c478bd9Sstevel@tonic-gate r_off = offset; 14277c478bd9Sstevel@tonic-gate bits = n_bits; 14287c478bd9Sstevel@tonic-gate /* 14297c478bd9Sstevel@tonic-gate * Get to the first byte. 14307c478bd9Sstevel@tonic-gate */ 14317c478bd9Sstevel@tonic-gate bp += (r_off >> 3); 14327c478bd9Sstevel@tonic-gate r_off &= 7; 14337c478bd9Sstevel@tonic-gate /* Get first part (low order bits) */ 14347c478bd9Sstevel@tonic-gate code = (*bp++ >> r_off); 14357c478bd9Sstevel@tonic-gate bits -= (8 - r_off); 14367c478bd9Sstevel@tonic-gate r_off = 8 - r_off; /* now, offset into code word */ 14377c478bd9Sstevel@tonic-gate /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ 14387c478bd9Sstevel@tonic-gate if (bits >= 8) { 14397c478bd9Sstevel@tonic-gate code |= *bp++ << r_off; 14407c478bd9Sstevel@tonic-gate r_off += 8; 14417c478bd9Sstevel@tonic-gate bits -= 8; 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate /* high order bits. */ 14447c478bd9Sstevel@tonic-gate code |= (*bp & rmask[bits]) << r_off; 14457c478bd9Sstevel@tonic-gate offset += n_bits; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate return (code); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate #ifdef DEBUG 14517c478bd9Sstevel@tonic-gate static void 14527c478bd9Sstevel@tonic-gate printcodes() 14537c478bd9Sstevel@tonic-gate { 14547c478bd9Sstevel@tonic-gate /* 14557c478bd9Sstevel@tonic-gate * Just print out codes from input file. For debugging. 14567c478bd9Sstevel@tonic-gate */ 14577c478bd9Sstevel@tonic-gate code_int code; 14587c478bd9Sstevel@tonic-gate int col = 0, bits; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate bits = n_bits = INIT_BITS; 14617c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 14627c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 14637c478bd9Sstevel@tonic-gate while ((code = getcode()) >= 0) { 14647c478bd9Sstevel@tonic-gate if ((code == CLEAR) && block_compress) { 14657c478bd9Sstevel@tonic-gate free_ent = FIRST - 1; 14667c478bd9Sstevel@tonic-gate clear_flg = 1; 14677c478bd9Sstevel@tonic-gate } else if (free_ent < maxmaxcode) 14687c478bd9Sstevel@tonic-gate free_ent++; 14697c478bd9Sstevel@tonic-gate if (bits != n_bits) { 14707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\nChange to %d bits\n", n_bits); 14717c478bd9Sstevel@tonic-gate bits = n_bits; 14727c478bd9Sstevel@tonic-gate col = 0; 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d%c", 14757c478bd9Sstevel@tonic-gate code, (col += 6) >= 74 ? (col = 0, '\n') : ' '); 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate #ifdef DEBUG 14837c478bd9Sstevel@tonic-gate static void 14847c478bd9Sstevel@tonic-gate dump_tab() /* dump string table */ 14857c478bd9Sstevel@tonic-gate { 14867c478bd9Sstevel@tonic-gate int i, first; 14877c478bd9Sstevel@tonic-gate int ent; 14887c478bd9Sstevel@tonic-gate int stack_top = STACK_SIZE; 14897c478bd9Sstevel@tonic-gate int c; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate if (do_decomp == 0) { /* compressing */ 14927c478bd9Sstevel@tonic-gate int flag = 1; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate for (i = 0; i < hsize; i++) { /* build sort pointers */ 14957c478bd9Sstevel@tonic-gate if ((long)htabof(i) >= 0) { 14967c478bd9Sstevel@tonic-gate sorttab[codetabof(i)] = i; 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate first = block_compress ? FIRST : 256; 15007c478bd9Sstevel@tonic-gate for (i = first; i < free_ent; i++) { 15017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: \"", i); 15027c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\n'; 15037c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '"'; 15047c478bd9Sstevel@tonic-gate stack_top = 15057c478bd9Sstevel@tonic-gate in_stack((htabof(sorttab[i]) >> maxbits) & 0xff, 15067c478bd9Sstevel@tonic-gate stack_top); 15077c478bd9Sstevel@tonic-gate for (ent = htabof(sorttab[i]) & ((1 << maxbits) -1); 15087c478bd9Sstevel@tonic-gate ent > 256; 15097c478bd9Sstevel@tonic-gate ent = htabof(sorttab[ent]) & ((1<<maxbits)-1)) { 15107c478bd9Sstevel@tonic-gate stack_top = in_stack( 15117c478bd9Sstevel@tonic-gate htabof(sorttab[ent]) >> maxbits, 15127c478bd9Sstevel@tonic-gate stack_top); 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate stack_top = in_stack(ent, stack_top); 15157c478bd9Sstevel@tonic-gate (void) fwrite(&de_stack[stack_top], 1, 15167c478bd9Sstevel@tonic-gate STACK_SIZE - stack_top, stderr); 15177c478bd9Sstevel@tonic-gate stack_top = STACK_SIZE; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate } else if (!debug) { /* decompressing */ 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate for (i = 0; i < free_ent; i++) { 15227c478bd9Sstevel@tonic-gate ent = i; 15237c478bd9Sstevel@tonic-gate c = tab_suffixof(ent); 15247c478bd9Sstevel@tonic-gate if (isascii(c) && isprint(c)) 15257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: %5d/'%c' \"", 15267c478bd9Sstevel@tonic-gate ent, tab_prefixof(ent), c); 15277c478bd9Sstevel@tonic-gate else 15287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: %5d/\\%03o \"", 15297c478bd9Sstevel@tonic-gate ent, tab_prefixof(ent), c); 15307c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\n'; 15317c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '"'; 15327c478bd9Sstevel@tonic-gate for (; ent != NULL; 15337c478bd9Sstevel@tonic-gate ent = (ent >= FIRST ? tab_prefixof(ent) : 15347c478bd9Sstevel@tonic-gate NULL)) { 15357c478bd9Sstevel@tonic-gate stack_top = in_stack(tab_suffixof(ent), 15367c478bd9Sstevel@tonic-gate stack_top); 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate (void) fwrite(&de_stack[stack_top], 1, 15397c478bd9Sstevel@tonic-gate STACK_SIZE - stack_top, stderr); 15407c478bd9Sstevel@tonic-gate stack_top = STACK_SIZE; 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15467c478bd9Sstevel@tonic-gate #ifdef DEBUG 15477c478bd9Sstevel@tonic-gate static int 15487c478bd9Sstevel@tonic-gate in_stack(int c, int stack_top) 15497c478bd9Sstevel@tonic-gate { 15507c478bd9Sstevel@tonic-gate if ((isascii(c) && isprint(c) && c != '\\') || c == ' ') { 15517c478bd9Sstevel@tonic-gate de_stack[--stack_top] = c; 15527c478bd9Sstevel@tonic-gate } else { 15537c478bd9Sstevel@tonic-gate switch (c) { 15547c478bd9Sstevel@tonic-gate case '\n': de_stack[--stack_top] = 'n'; break; 15557c478bd9Sstevel@tonic-gate case '\t': de_stack[--stack_top] = 't'; break; 15567c478bd9Sstevel@tonic-gate case '\b': de_stack[--stack_top] = 'b'; break; 15577c478bd9Sstevel@tonic-gate case '\f': de_stack[--stack_top] = 'f'; break; 15587c478bd9Sstevel@tonic-gate case '\r': de_stack[--stack_top] = 'r'; break; 15597c478bd9Sstevel@tonic-gate case '\\': de_stack[--stack_top] = '\\'; break; 15607c478bd9Sstevel@tonic-gate default: 15617c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + c % 8; 15627c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + (c / 8) % 8; 15637c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + c / 64; 15647c478bd9Sstevel@tonic-gate break; 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\\'; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate return (stack_top); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15727c478bd9Sstevel@tonic-gate static void 15737c478bd9Sstevel@tonic-gate ioerror() 15747c478bd9Sstevel@tonic-gate { 15757c478bd9Sstevel@tonic-gate longjmp(env, 1); 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate static void 15797c478bd9Sstevel@tonic-gate copystat(char *ifname, struct stat *ifstat, char *ofname) 15807c478bd9Sstevel@tonic-gate { 15817c478bd9Sstevel@tonic-gate mode_t mode; 15827c478bd9Sstevel@tonic-gate struct utimbuf timep; 1583f0a2d94fSmarks acl_t *aclp = NULL; 1584fa9e4066Sahrens int error; 1585*da6c28aaSamw int sattr_exist = 0; 1586*da6c28aaSamw int xattr_exist = 0; 1587*da6c28aaSamw 1588*da6c28aaSamw if (pathconf(ifname, _PC_XATTR_EXISTS) == 1) 1589*da6c28aaSamw xattr_exist = 1; 1590*da6c28aaSamw if (saflg && sysattr_support(ifname, _PC_SATTR_EXISTS) == 1) 1591*da6c28aaSamw sattr_exist = 1; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate if (fclose(outp)) { 15947c478bd9Sstevel@tonic-gate perror(ofname); 15957c478bd9Sstevel@tonic-gate if (!quiet) { 15967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(" -- file unchanged")); 15977c478bd9Sstevel@tonic-gate newline_needed = 1; 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate perm_stat = 1; 16007c478bd9Sstevel@tonic-gate } else if (ifstat == NULL) { /* Get stat on input file */ 16017c478bd9Sstevel@tonic-gate perror(ifname); 16027c478bd9Sstevel@tonic-gate return; 16037c478bd9Sstevel@tonic-gate } else if ((ifstat->st_mode & 16047c478bd9Sstevel@tonic-gate S_IFMT /* 0170000 */) != S_IFREG /* 0100000 */) { 16057c478bd9Sstevel@tonic-gate if (quiet) { 16067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", ifname); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16097c478bd9Sstevel@tonic-gate " -- not a regular file: unchanged")); 16107c478bd9Sstevel@tonic-gate newline_needed = 1; 16117c478bd9Sstevel@tonic-gate perm_stat = 1; 16127c478bd9Sstevel@tonic-gate } else if (ifstat->st_nlink > 1) { 16137c478bd9Sstevel@tonic-gate if (quiet) { 16147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", ifname); 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16177c478bd9Sstevel@tonic-gate " -- has %d other links: unchanged"), 16187c478bd9Sstevel@tonic-gate (uint_t)ifstat->st_nlink - 1); 16197c478bd9Sstevel@tonic-gate newline_needed = 1; 16207c478bd9Sstevel@tonic-gate perm_stat = 1; 16217c478bd9Sstevel@tonic-gate } else if (didnt_shrink && !force) { 16227c478bd9Sstevel@tonic-gate /* No compression: remove file.Z */ 16237c478bd9Sstevel@tonic-gate if (!quiet) { 16247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16257c478bd9Sstevel@tonic-gate " -- file unchanged")); 16267c478bd9Sstevel@tonic-gate newline_needed = 1; 16277c478bd9Sstevel@tonic-gate } 1628*da6c28aaSamw } else if ((xattr_exist || sattr_exist) && 1629*da6c28aaSamw (mv_xattrs(progname, ifname, ofname, sattr_exist, 0) 1630*da6c28aaSamw != 0)) { 16317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1632*da6c28aaSamw "%s: -- cannot preserve extended attributes or " 1633*da6c28aaSamw "system attributes, file unchanged"), ifname); 16347c478bd9Sstevel@tonic-gate newline_needed = 1; 16357c478bd9Sstevel@tonic-gate /* Move attributes back ... */ 1636*da6c28aaSamw xattr_exist = 0; 1637*da6c28aaSamw sattr_exist = 0; 1638*da6c28aaSamw if (pathconf(ofname, _PC_XATTR_EXISTS) == 1) 1639*da6c28aaSamw xattr_exist = 1; 1640*da6c28aaSamw if (saflg && sysattr_support(ofname, _PC_SATTR_EXISTS) == 1) 1641*da6c28aaSamw sattr_exist = 1; 1642*da6c28aaSamw if (sattr_exist || xattr_exist) 1643*da6c28aaSamw (void) mv_xattrs(progname, ofname, ifname, 1644*da6c28aaSamw sattr_exist, 1); 16457c478bd9Sstevel@tonic-gate perm_stat = 1; 16467c478bd9Sstevel@tonic-gate } else { /* ***** Successful Compression ***** */ 16477c478bd9Sstevel@tonic-gate mode = ifstat->st_mode & 07777; 1648*da6c28aaSamw if (chmod(ofname, mode)) { /* Copy modes */ 1649*da6c28aaSamw if (errno == EPERM) { 1650*da6c28aaSamw (void) fprintf(stderr, 1651*da6c28aaSamw gettext("failed to chmod %s" 1652*da6c28aaSamw "- permisssion denied\n"), ofname); 1653*da6c28aaSamw } 16547c478bd9Sstevel@tonic-gate perror(ofname); 1655*da6c28aaSamw } 1656fa9e4066Sahrens error = acl_get(ifname, ACL_NO_TRIVIAL, &aclp); 1657fa9e4066Sahrens if (error != 0) { 16587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1659fa9e4066Sahrens "%s: failed to retrieve acl : %s\n"), 1660fa9e4066Sahrens ifname, acl_strerror(error)); 16617c478bd9Sstevel@tonic-gate perm_stat = 1; 16627c478bd9Sstevel@tonic-gate } 1663fa9e4066Sahrens if (aclp && (acl_set(ofname, aclp) < 0)) { 1664*da6c28aaSamw (void) fprintf(stderr, 1665*da6c28aaSamw gettext("%s: failed to set acl " 16667c478bd9Sstevel@tonic-gate "entries\n"), ofname); 16677c478bd9Sstevel@tonic-gate perm_stat = 1; 16687c478bd9Sstevel@tonic-gate } 1669f0a2d94fSmarks if (aclp) { 1670fa9e4066Sahrens acl_free(aclp); 1671f0a2d94fSmarks aclp = NULL; 1672f0a2d94fSmarks } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* Copy ownership */ 16757c478bd9Sstevel@tonic-gate (void) chown(ofname, ifstat->st_uid, ifstat->st_gid); 16767c478bd9Sstevel@tonic-gate timep.actime = ifstat->st_atime; 16777c478bd9Sstevel@tonic-gate timep.modtime = ifstat->st_mtime; 16787c478bd9Sstevel@tonic-gate /* Update last accessed and modified times */ 16797c478bd9Sstevel@tonic-gate (void) utime(ofname, &timep); 1680*da6c28aaSamw if (unlink(ifname)) { /* Remove input file */ 1681*da6c28aaSamw if (errno == EPERM) { 1682*da6c28aaSamw (void) fprintf(stderr, 1683*da6c28aaSamw gettext("failed to remove %s" 1684*da6c28aaSamw "- permisssion denied\n"), ifname); 1685*da6c28aaSamw } 16867c478bd9Sstevel@tonic-gate perror(ifname); 1687*da6c28aaSamw } 16887c478bd9Sstevel@tonic-gate if (!quiet) { 16897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16907c478bd9Sstevel@tonic-gate " -- replaced with %s"), ofname); 16917c478bd9Sstevel@tonic-gate newline_needed = 1; 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate return; /* Successful return */ 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate /* Unsuccessful return -- one of the tests failed */ 16977c478bd9Sstevel@tonic-gate if (ofname[0] != '\0') { 16987c478bd9Sstevel@tonic-gate if (unlink(ofname)) { 1699*da6c28aaSamw if (errno == EPERM) { 1700*da6c28aaSamw (void) fprintf(stderr, 1701*da6c28aaSamw gettext("failed to remove %s" 1702*da6c28aaSamw "- permisssion denied\n"), ifname); 1703*da6c28aaSamw } 17047c478bd9Sstevel@tonic-gate perror(ofname); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate ofname[0] = '\0'; 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate } 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate static void 17127c478bd9Sstevel@tonic-gate onintr() 17137c478bd9Sstevel@tonic-gate { 17147c478bd9Sstevel@tonic-gate if (!precious && !use_stdout && ofname[0] != '\0') 17157c478bd9Sstevel@tonic-gate (void) unlink(ofname); 17167c478bd9Sstevel@tonic-gate exit(1); 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate static void 17207c478bd9Sstevel@tonic-gate oops() /* wild pointer -- assume bad input */ 17217c478bd9Sstevel@tonic-gate { 17227c478bd9Sstevel@tonic-gate if (do_decomp) { 17237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("uncompress: corrupt input\n")); 17247c478bd9Sstevel@tonic-gate } 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate if (!use_stdout && ofname[0] != '\0') { 17277c478bd9Sstevel@tonic-gate (void) unlink(ofname); 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate exit(1); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate static void 17347c478bd9Sstevel@tonic-gate cl_block(count_long in_count) /* table clear for block compress */ 17357c478bd9Sstevel@tonic-gate { 17367c478bd9Sstevel@tonic-gate count_long rat; 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate checkpoint = (count_long)in_count + (count_long)CHECK_GAP; 17397c478bd9Sstevel@tonic-gate #ifdef DEBUG 17407c478bd9Sstevel@tonic-gate if (debug) { 17417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "count: %lld, ratio: ", 17427c478bd9Sstevel@tonic-gate (count_long)in_count); 17437c478bd9Sstevel@tonic-gate prratio(stderr, (count_long)in_count, (count_long)bytes_out); 17447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate /* shift will overflow */ 1749a77d64afScf46844 if ((count_long)in_count > 0x007fffffffffffffLL) { 17507c478bd9Sstevel@tonic-gate rat = (count_long)bytes_out >> 8; 17517c478bd9Sstevel@tonic-gate if (rat == 0) { /* Don't divide by zero */ 1752a77d64afScf46844 rat = 0x7fffffffffffffffLL; 17537c478bd9Sstevel@tonic-gate } else { 17547c478bd9Sstevel@tonic-gate rat = (count_long)in_count / (count_long)rat; 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate } else { 17577c478bd9Sstevel@tonic-gate /* 8 fractional bits */ 17587c478bd9Sstevel@tonic-gate rat = ((count_long)in_count << 8) /(count_long)bytes_out; 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate if (rat > ratio) { 17617c478bd9Sstevel@tonic-gate ratio = rat; 17627c478bd9Sstevel@tonic-gate } else { 17637c478bd9Sstevel@tonic-gate ratio = 0; 17647c478bd9Sstevel@tonic-gate #ifdef DEBUG 17657c478bd9Sstevel@tonic-gate if (verbose) 17667c478bd9Sstevel@tonic-gate dump_tab(); /* dump string table */ 17677c478bd9Sstevel@tonic-gate #endif 17687c478bd9Sstevel@tonic-gate cl_hash((count_int) hsize); 17697c478bd9Sstevel@tonic-gate free_ent = FIRST; 17707c478bd9Sstevel@tonic-gate clear_flg = 1; 17717c478bd9Sstevel@tonic-gate output((code_int) CLEAR); 17727c478bd9Sstevel@tonic-gate #ifdef DEBUG 17737c478bd9Sstevel@tonic-gate if (debug) 17747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "clear\n"); 17757c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate static void 17807c478bd9Sstevel@tonic-gate cl_hash(count_int hsize) /* reset code table */ 17817c478bd9Sstevel@tonic-gate { 17827c478bd9Sstevel@tonic-gate count_int *htab_p = htab+hsize; 17837c478bd9Sstevel@tonic-gate long i; 17847c478bd9Sstevel@tonic-gate long m1 = -1; 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate i = hsize - 16; 17877c478bd9Sstevel@tonic-gate do { /* might use Sys V memset(3) here */ 17887c478bd9Sstevel@tonic-gate *(htab_p-16) = m1; 17897c478bd9Sstevel@tonic-gate *(htab_p-15) = m1; 17907c478bd9Sstevel@tonic-gate *(htab_p-14) = m1; 17917c478bd9Sstevel@tonic-gate *(htab_p-13) = m1; 17927c478bd9Sstevel@tonic-gate *(htab_p-12) = m1; 17937c478bd9Sstevel@tonic-gate *(htab_p-11) = m1; 17947c478bd9Sstevel@tonic-gate *(htab_p-10) = m1; 17957c478bd9Sstevel@tonic-gate *(htab_p-9) = m1; 17967c478bd9Sstevel@tonic-gate *(htab_p-8) = m1; 17977c478bd9Sstevel@tonic-gate *(htab_p-7) = m1; 17987c478bd9Sstevel@tonic-gate *(htab_p-6) = m1; 17997c478bd9Sstevel@tonic-gate *(htab_p-5) = m1; 18007c478bd9Sstevel@tonic-gate *(htab_p-4) = m1; 18017c478bd9Sstevel@tonic-gate *(htab_p-3) = m1; 18027c478bd9Sstevel@tonic-gate *(htab_p-2) = m1; 18037c478bd9Sstevel@tonic-gate *(htab_p-1) = m1; 18047c478bd9Sstevel@tonic-gate htab_p -= 16; 18057c478bd9Sstevel@tonic-gate } while ((i -= 16) >= 0); 18067c478bd9Sstevel@tonic-gate for (i += 16; i > 0; i--) 18077c478bd9Sstevel@tonic-gate *--htab_p = m1; 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate static void 18117c478bd9Sstevel@tonic-gate prratio(FILE *stream, count_long num, count_long den) 18127c478bd9Sstevel@tonic-gate { 18137c478bd9Sstevel@tonic-gate int q; /* store percentage */ 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate q = (int)(10000LL * (count_long)num / (count_long)den); 18167c478bd9Sstevel@tonic-gate if (q < 0) { 18177c478bd9Sstevel@tonic-gate (void) putc('-', stream); 18187c478bd9Sstevel@tonic-gate q = -q; 18197c478bd9Sstevel@tonic-gate } 18207c478bd9Sstevel@tonic-gate (void) fprintf(stream, "%d%s%02d%%", q / 100, 18217c478bd9Sstevel@tonic-gate localeconv()->decimal_point, q % 100); 18227c478bd9Sstevel@tonic-gate } 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate static void 18257c478bd9Sstevel@tonic-gate version() 18267c478bd9Sstevel@tonic-gate { 18277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s, Berkeley 5.9 5/11/86\n", rcs_ident); 18287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Options: "); 18297c478bd9Sstevel@tonic-gate #ifdef DEBUG 18307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "DEBUG, "); 18317c478bd9Sstevel@tonic-gate #endif 18327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "BITS = %d\n", BITS); 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate static void 18367c478bd9Sstevel@tonic-gate Usage() 18377c478bd9Sstevel@tonic-gate { 18387c478bd9Sstevel@tonic-gate #ifdef DEBUG 18397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1840*da6c28aaSamw "Usage: compress [-dDVfc/] [-b maxbits] [file ...]\n"); 18417c478bd9Sstevel@tonic-gate #else 18427c478bd9Sstevel@tonic-gate if (strcmp(progname, "compress") == 0) { 18437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18447c478bd9Sstevel@tonic-gate gettext( 1845*da6c28aaSamw "Usage: compress [-fv/] [-b maxbits] [file ...]\n"\ 1846*da6c28aaSamw " compress c [-fv] [-b maxbits] [file]\n")); 18477c478bd9Sstevel@tonic-gate } else if (strcmp(progname, "uncompress") == 0) 18487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1849*da6c28aaSamw "Usage: uncompress [-fv] [-c || -/] [file ...]\n")); 18507c478bd9Sstevel@tonic-gate else if (strcmp(progname, "zcat") == 0) 18517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage: zcat [file ...]\n")); 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate static char * 18577c478bd9Sstevel@tonic-gate local_basename(char *path) 18587c478bd9Sstevel@tonic-gate { 18597c478bd9Sstevel@tonic-gate char *p; 18607c478bd9Sstevel@tonic-gate char *ret = (char *)path; 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate while ((p = (char *)strpbrk(ret, "/")) != NULL) 18637c478bd9Sstevel@tonic-gate ret = p + 1; 18647c478bd9Sstevel@tonic-gate return (ret); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate static int 18687c478bd9Sstevel@tonic-gate addDotZ(char *fn, size_t fnsize) 18697c478bd9Sstevel@tonic-gate { 18707c478bd9Sstevel@tonic-gate char *fn_dup; 18717c478bd9Sstevel@tonic-gate char *dir; 18727c478bd9Sstevel@tonic-gate long int max_name; 18737c478bd9Sstevel@tonic-gate long int max_path; 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate fn_dup = strdup(fn); 18767c478bd9Sstevel@tonic-gate dir = dirname(fn_dup); 18777c478bd9Sstevel@tonic-gate max_name = pathconf(dir, _PC_NAME_MAX); 18787c478bd9Sstevel@tonic-gate max_path = pathconf(dir, _PC_PATH_MAX); 18797c478bd9Sstevel@tonic-gate free(fn_dup); 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate /* Check for component length too long */ 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if ((strlen(local_basename(fn)) + 2) > (size_t)max_name) { 18847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18857c478bd9Sstevel@tonic-gate gettext("%s: filename too long to tack on .Z:" 18867c478bd9Sstevel@tonic-gate " %s\n"), progname, fn); 18877c478bd9Sstevel@tonic-gate return (-1); 18887c478bd9Sstevel@tonic-gate } 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate /* Check for path length too long */ 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate if ((strlen(fn) + 2) > (size_t)max_path - 1) { 18937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18947c478bd9Sstevel@tonic-gate gettext("%s: Pathname too long to tack on .Z:" 18957c478bd9Sstevel@tonic-gate " %s\n"), progname, fn); 18967c478bd9Sstevel@tonic-gate return (-1); 18977c478bd9Sstevel@tonic-gate } 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate if (strlcat(fn, ".Z", fnsize) >= fnsize) { 19007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19017c478bd9Sstevel@tonic-gate gettext("%s: Buffer overflow adding .Z to %s\n"), 19027c478bd9Sstevel@tonic-gate progname, fn); 19037c478bd9Sstevel@tonic-gate return (-1); 19047c478bd9Sstevel@tonic-gate } 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate return (0); 19077c478bd9Sstevel@tonic-gate } 1908