19b50d902SRodney W. Grimes /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni *
49b50d902SRodney W. Grimes * Copyright (c) 1992, 1993
59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved.
69b50d902SRodney W. Grimes *
79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions
99b50d902SRodney W. Grimes * are met:
109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software
179b50d902SRodney W. Grimes * without specific prior written permission.
189b50d902SRodney W. Grimes *
199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299b50d902SRodney W. Grimes * SUCH DAMAGE.
309b50d902SRodney W. Grimes */
319b50d902SRodney W. Grimes
329b50d902SRodney W. Grimes #include <sys/param.h>
339b50d902SRodney W. Grimes #include <sys/stat.h>
34eb2fc780SGarrett Wollman #include <sys/time.h>
359b50d902SRodney W. Grimes
369b50d902SRodney W. Grimes #include <err.h>
379b50d902SRodney W. Grimes #include <errno.h>
38d6b3ef63SJilles Tjoelker #include <fcntl.h>
397ddea7b8SWarner Losh #include <stdarg.h>
409b50d902SRodney W. Grimes #include <stdio.h>
419b50d902SRodney W. Grimes #include <stdlib.h>
429b50d902SRodney W. Grimes #include <string.h>
439b50d902SRodney W. Grimes #include <unistd.h>
449b50d902SRodney W. Grimes
451f36dc1fSBruce Evans #include "zopen.h"
461f36dc1fSBruce Evans
47305700d9SEd Schouten static void compress(const char *, const char *, int);
48305700d9SEd Schouten static void cwarn(const char *, ...) __printflike(1, 2);
49305700d9SEd Schouten static void cwarnx(const char *, ...) __printflike(1, 2);
50305700d9SEd Schouten static void decompress(const char *, const char *, int);
51305700d9SEd Schouten static int permission(const char *);
52305700d9SEd Schouten static void setfile(const char *, struct stat *);
53305700d9SEd Schouten static void usage(int);
549b50d902SRodney W. Grimes
55305700d9SEd Schouten static int eval, force, verbose;
569b50d902SRodney W. Grimes
579b50d902SRodney W. Grimes int
main(int argc,char * argv[])5847e9e6a1SDavid Malone main(int argc, char *argv[])
599b50d902SRodney W. Grimes {
60d52ae819SBruce Evans enum {COMPRESS, DECOMPRESS} style;
619b50d902SRodney W. Grimes size_t len;
629b50d902SRodney W. Grimes int bits, cat, ch;
639b50d902SRodney W. Grimes char *p, newname[MAXPATHLEN];
649b50d902SRodney W. Grimes
65d52ae819SBruce Evans cat = 0;
66b3608ae1SEd Schouten if ((p = strrchr(argv[0], '/')) == NULL)
679b50d902SRodney W. Grimes p = argv[0];
689b50d902SRodney W. Grimes else
699b50d902SRodney W. Grimes ++p;
709b50d902SRodney W. Grimes if (!strcmp(p, "uncompress"))
719b50d902SRodney W. Grimes style = DECOMPRESS;
729b50d902SRodney W. Grimes else if (!strcmp(p, "compress"))
739b50d902SRodney W. Grimes style = COMPRESS;
747c0704e4SMike Smith else if (!strcmp(p, "zcat")) {
757c0704e4SMike Smith cat = 1;
76d52ae819SBruce Evans style = DECOMPRESS;
777c0704e4SMike Smith } else
789b50d902SRodney W. Grimes errx(1, "unknown program name");
799b50d902SRodney W. Grimes
80d52ae819SBruce Evans bits = 0;
811c8af878SWarner Losh while ((ch = getopt(argc, argv, "b:cdfv")) != -1)
829b50d902SRodney W. Grimes switch(ch) {
839b50d902SRodney W. Grimes case 'b':
849b50d902SRodney W. Grimes bits = strtol(optarg, &p, 10);
859b50d902SRodney W. Grimes if (*p)
869b50d902SRodney W. Grimes errx(1, "illegal bit count -- %s", optarg);
879b50d902SRodney W. Grimes break;
889b50d902SRodney W. Grimes case 'c':
899b50d902SRodney W. Grimes cat = 1;
909b50d902SRodney W. Grimes break;
919b50d902SRodney W. Grimes case 'd': /* Backward compatible. */
929b50d902SRodney W. Grimes style = DECOMPRESS;
939b50d902SRodney W. Grimes break;
949b50d902SRodney W. Grimes case 'f':
959b50d902SRodney W. Grimes force = 1;
969b50d902SRodney W. Grimes break;
979b50d902SRodney W. Grimes case 'v':
989b50d902SRodney W. Grimes verbose = 1;
999b50d902SRodney W. Grimes break;
1009b50d902SRodney W. Grimes case '?':
1019b50d902SRodney W. Grimes default:
1029b50d902SRodney W. Grimes usage(style == COMPRESS);
1039b50d902SRodney W. Grimes }
1049b50d902SRodney W. Grimes argc -= optind;
1059b50d902SRodney W. Grimes argv += optind;
1069b50d902SRodney W. Grimes
1079b50d902SRodney W. Grimes if (argc == 0) {
1089b50d902SRodney W. Grimes switch(style) {
1099b50d902SRodney W. Grimes case COMPRESS:
1109b50d902SRodney W. Grimes (void)compress("/dev/stdin", "/dev/stdout", bits);
1119b50d902SRodney W. Grimes break;
1129b50d902SRodney W. Grimes case DECOMPRESS:
1139b50d902SRodney W. Grimes (void)decompress("/dev/stdin", "/dev/stdout", bits);
1149b50d902SRodney W. Grimes break;
1159b50d902SRodney W. Grimes }
1169b50d902SRodney W. Grimes exit (eval);
1179b50d902SRodney W. Grimes }
1189b50d902SRodney W. Grimes
119f084f766SJilles Tjoelker if (cat == 1 && style == COMPRESS && argc > 1)
1209b50d902SRodney W. Grimes errx(1, "the -c option permits only a single file argument");
1219b50d902SRodney W. Grimes
1229b50d902SRodney W. Grimes for (; *argv; ++argv)
1239b50d902SRodney W. Grimes switch(style) {
1249b50d902SRodney W. Grimes case COMPRESS:
125b4771590STim J. Robbins if (strcmp(*argv, "-") == 0) {
126b4771590STim J. Robbins compress("/dev/stdin", "/dev/stdout", bits);
127b4771590STim J. Robbins break;
128b4771590STim J. Robbins } else if (cat) {
1299b50d902SRodney W. Grimes compress(*argv, "/dev/stdout", bits);
1309b50d902SRodney W. Grimes break;
1319b50d902SRodney W. Grimes }
132b3608ae1SEd Schouten if ((p = strrchr(*argv, '.')) != NULL &&
1339b50d902SRodney W. Grimes !strcmp(p, ".Z")) {
1349b50d902SRodney W. Grimes cwarnx("%s: name already has trailing .Z",
1359b50d902SRodney W. Grimes *argv);
1369b50d902SRodney W. Grimes break;
1379b50d902SRodney W. Grimes }
1389b50d902SRodney W. Grimes len = strlen(*argv);
1399b50d902SRodney W. Grimes if (len > sizeof(newname) - 3) {
1409b50d902SRodney W. Grimes cwarnx("%s: name too long", *argv);
1419b50d902SRodney W. Grimes break;
1429b50d902SRodney W. Grimes }
1439b50d902SRodney W. Grimes memmove(newname, *argv, len);
1449b50d902SRodney W. Grimes newname[len] = '.';
1459b50d902SRodney W. Grimes newname[len + 1] = 'Z';
1469b50d902SRodney W. Grimes newname[len + 2] = '\0';
1479b50d902SRodney W. Grimes compress(*argv, newname, bits);
1489b50d902SRodney W. Grimes break;
1499b50d902SRodney W. Grimes case DECOMPRESS:
150b4771590STim J. Robbins if (strcmp(*argv, "-") == 0) {
151b4771590STim J. Robbins decompress("/dev/stdin", "/dev/stdout", bits);
152b4771590STim J. Robbins break;
153b4771590STim J. Robbins }
1549b50d902SRodney W. Grimes len = strlen(*argv);
155b3608ae1SEd Schouten if ((p = strrchr(*argv, '.')) == NULL ||
1569b50d902SRodney W. Grimes strcmp(p, ".Z")) {
1579b50d902SRodney W. Grimes if (len > sizeof(newname) - 3) {
1589b50d902SRodney W. Grimes cwarnx("%s: name too long", *argv);
1599b50d902SRodney W. Grimes break;
1609b50d902SRodney W. Grimes }
1619b50d902SRodney W. Grimes memmove(newname, *argv, len);
1629b50d902SRodney W. Grimes newname[len] = '.';
1639b50d902SRodney W. Grimes newname[len + 1] = 'Z';
1649b50d902SRodney W. Grimes newname[len + 2] = '\0';
1659b50d902SRodney W. Grimes decompress(newname,
1669b50d902SRodney W. Grimes cat ? "/dev/stdout" : *argv, bits);
1679b50d902SRodney W. Grimes } else {
1689b50d902SRodney W. Grimes if (len - 2 > sizeof(newname) - 1) {
1699b50d902SRodney W. Grimes cwarnx("%s: name too long", *argv);
1709b50d902SRodney W. Grimes break;
1719b50d902SRodney W. Grimes }
1729b50d902SRodney W. Grimes memmove(newname, *argv, len - 2);
1739b50d902SRodney W. Grimes newname[len - 2] = '\0';
1749b50d902SRodney W. Grimes decompress(*argv,
1759b50d902SRodney W. Grimes cat ? "/dev/stdout" : newname, bits);
1769b50d902SRodney W. Grimes }
1779b50d902SRodney W. Grimes break;
1789b50d902SRodney W. Grimes }
1799b50d902SRodney W. Grimes exit (eval);
1809b50d902SRodney W. Grimes }
1819b50d902SRodney W. Grimes
182305700d9SEd Schouten static void
compress(const char * in,const char * out,int bits)18347e9e6a1SDavid Malone compress(const char *in, const char *out, int bits)
1849b50d902SRodney W. Grimes {
185cb08795bSMark Murray size_t nr;
1869b50d902SRodney W. Grimes struct stat isb, sb;
1879b50d902SRodney W. Grimes FILE *ifp, *ofp;
1889b50d902SRodney W. Grimes int exists, isreg, oreg;
1899b50d902SRodney W. Grimes u_char buf[1024];
1909b50d902SRodney W. Grimes
1919b50d902SRodney W. Grimes exists = !stat(out, &sb);
1929b50d902SRodney W. Grimes if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
1939b50d902SRodney W. Grimes return;
1949b50d902SRodney W. Grimes isreg = oreg = !exists || S_ISREG(sb.st_mode);
1959b50d902SRodney W. Grimes
1969b50d902SRodney W. Grimes ifp = ofp = NULL;
1979b50d902SRodney W. Grimes if ((ifp = fopen(in, "r")) == NULL) {
1989b50d902SRodney W. Grimes cwarn("%s", in);
1999b50d902SRodney W. Grimes return;
2009b50d902SRodney W. Grimes }
2019b50d902SRodney W. Grimes if (stat(in, &isb)) { /* DON'T FSTAT! */
2029b50d902SRodney W. Grimes cwarn("%s", in);
2039b50d902SRodney W. Grimes goto err;
2049b50d902SRodney W. Grimes }
2059b50d902SRodney W. Grimes if (!S_ISREG(isb.st_mode))
2069b50d902SRodney W. Grimes isreg = 0;
2079b50d902SRodney W. Grimes
2089b50d902SRodney W. Grimes if ((ofp = zopen(out, "w", bits)) == NULL) {
2099b50d902SRodney W. Grimes cwarn("%s", out);
2109b50d902SRodney W. Grimes goto err;
2119b50d902SRodney W. Grimes }
2129b50d902SRodney W. Grimes while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
2139b50d902SRodney W. Grimes if (fwrite(buf, 1, nr, ofp) != nr) {
2149b50d902SRodney W. Grimes cwarn("%s", out);
2159b50d902SRodney W. Grimes goto err;
2169b50d902SRodney W. Grimes }
2179b50d902SRodney W. Grimes
2189b50d902SRodney W. Grimes if (ferror(ifp) || fclose(ifp)) {
2199b50d902SRodney W. Grimes cwarn("%s", in);
2209b50d902SRodney W. Grimes goto err;
2219b50d902SRodney W. Grimes }
2229b50d902SRodney W. Grimes ifp = NULL;
2239b50d902SRodney W. Grimes
2249b50d902SRodney W. Grimes if (fclose(ofp)) {
2259b50d902SRodney W. Grimes cwarn("%s", out);
2269b50d902SRodney W. Grimes goto err;
2279b50d902SRodney W. Grimes }
2289b50d902SRodney W. Grimes ofp = NULL;
2299b50d902SRodney W. Grimes
2309b50d902SRodney W. Grimes if (isreg) {
2319b50d902SRodney W. Grimes if (stat(out, &sb)) {
2329b50d902SRodney W. Grimes cwarn("%s", out);
2339b50d902SRodney W. Grimes goto err;
2349b50d902SRodney W. Grimes }
2359b50d902SRodney W. Grimes
2369b50d902SRodney W. Grimes if (!force && sb.st_size >= isb.st_size) {
2379b50d902SRodney W. Grimes if (verbose)
238783b4710STim J. Robbins (void)fprintf(stderr, "%s: file would grow; left unmodified\n",
239783b4710STim J. Robbins in);
2406c1b63bbSTim J. Robbins eval = 2;
2419b50d902SRodney W. Grimes if (unlink(out))
2429b50d902SRodney W. Grimes cwarn("%s", out);
2439b50d902SRodney W. Grimes goto err;
2449b50d902SRodney W. Grimes }
2459b50d902SRodney W. Grimes
2469b50d902SRodney W. Grimes setfile(out, &isb);
2479b50d902SRodney W. Grimes
2489b50d902SRodney W. Grimes if (unlink(in))
2499b50d902SRodney W. Grimes cwarn("%s", in);
2509b50d902SRodney W. Grimes
2519b50d902SRodney W. Grimes if (verbose) {
252783b4710STim J. Robbins (void)fprintf(stderr, "%s: ", out);
2539b50d902SRodney W. Grimes if (isb.st_size > sb.st_size)
254783b4710STim J. Robbins (void)fprintf(stderr, "%.0f%% compression\n",
2559b50d902SRodney W. Grimes ((float)sb.st_size / isb.st_size) * 100.0);
2569b50d902SRodney W. Grimes else
257783b4710STim J. Robbins (void)fprintf(stderr, "%.0f%% expansion\n",
2589b50d902SRodney W. Grimes ((float)isb.st_size / sb.st_size) * 100.0);
2599b50d902SRodney W. Grimes }
2609b50d902SRodney W. Grimes }
2619b50d902SRodney W. Grimes return;
2629b50d902SRodney W. Grimes
2639b50d902SRodney W. Grimes err: if (ofp) {
2649b50d902SRodney W. Grimes if (oreg)
2659b50d902SRodney W. Grimes (void)unlink(out);
2669b50d902SRodney W. Grimes (void)fclose(ofp);
2679b50d902SRodney W. Grimes }
2689b50d902SRodney W. Grimes if (ifp)
2699b50d902SRodney W. Grimes (void)fclose(ifp);
2709b50d902SRodney W. Grimes }
2719b50d902SRodney W. Grimes
272305700d9SEd Schouten static void
decompress(const char * in,const char * out,int bits)27347e9e6a1SDavid Malone decompress(const char *in, const char *out, int bits)
2749b50d902SRodney W. Grimes {
275cb08795bSMark Murray size_t nr;
2769b50d902SRodney W. Grimes struct stat sb;
2779b50d902SRodney W. Grimes FILE *ifp, *ofp;
2789b50d902SRodney W. Grimes int exists, isreg, oreg;
2799b50d902SRodney W. Grimes u_char buf[1024];
2809b50d902SRodney W. Grimes
2819b50d902SRodney W. Grimes exists = !stat(out, &sb);
2829b50d902SRodney W. Grimes if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
2839b50d902SRodney W. Grimes return;
2849b50d902SRodney W. Grimes isreg = oreg = !exists || S_ISREG(sb.st_mode);
2859b50d902SRodney W. Grimes
2869b50d902SRodney W. Grimes ifp = ofp = NULL;
2879b50d902SRodney W. Grimes if ((ifp = zopen(in, "r", bits)) == NULL) {
2889b50d902SRodney W. Grimes cwarn("%s", in);
28933ffdd81STom Rhodes return;
2909b50d902SRodney W. Grimes }
2919b50d902SRodney W. Grimes if (stat(in, &sb)) {
2929b50d902SRodney W. Grimes cwarn("%s", in);
2939b50d902SRodney W. Grimes goto err;
2949b50d902SRodney W. Grimes }
2959b50d902SRodney W. Grimes if (!S_ISREG(sb.st_mode))
2969b50d902SRodney W. Grimes isreg = 0;
2979b50d902SRodney W. Grimes
29833ffdd81STom Rhodes /*
29933ffdd81STom Rhodes * Try to read the first few uncompressed bytes from the input file
30033ffdd81STom Rhodes * before blindly truncating the output file.
30133ffdd81STom Rhodes */
30233ffdd81STom Rhodes if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) {
30333ffdd81STom Rhodes cwarn("%s", in);
30433ffdd81STom Rhodes (void)fclose(ifp);
30533ffdd81STom Rhodes return;
30633ffdd81STom Rhodes }
30733ffdd81STom Rhodes if ((ofp = fopen(out, "w")) == NULL ||
30833ffdd81STom Rhodes (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) {
30933ffdd81STom Rhodes cwarn("%s", out);
310*b63800acSOleksandr Tymoshenko if (ofp)
311*b63800acSOleksandr Tymoshenko (void)fclose(ofp);
31233ffdd81STom Rhodes (void)fclose(ifp);
31333ffdd81STom Rhodes return;
31433ffdd81STom Rhodes }
31533ffdd81STom Rhodes
3169b50d902SRodney W. Grimes while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
3179b50d902SRodney W. Grimes if (fwrite(buf, 1, nr, ofp) != nr) {
3189b50d902SRodney W. Grimes cwarn("%s", out);
3199b50d902SRodney W. Grimes goto err;
3209b50d902SRodney W. Grimes }
3219b50d902SRodney W. Grimes
3229b50d902SRodney W. Grimes if (ferror(ifp) || fclose(ifp)) {
3239b50d902SRodney W. Grimes cwarn("%s", in);
3249b50d902SRodney W. Grimes goto err;
3259b50d902SRodney W. Grimes }
3269b50d902SRodney W. Grimes ifp = NULL;
3279b50d902SRodney W. Grimes
3289b50d902SRodney W. Grimes if (fclose(ofp)) {
3299b50d902SRodney W. Grimes cwarn("%s", out);
3309b50d902SRodney W. Grimes goto err;
3319b50d902SRodney W. Grimes }
3329b50d902SRodney W. Grimes
3339b50d902SRodney W. Grimes if (isreg) {
3349b50d902SRodney W. Grimes setfile(out, &sb);
3359b50d902SRodney W. Grimes
3369b50d902SRodney W. Grimes if (unlink(in))
3379b50d902SRodney W. Grimes cwarn("%s", in);
3389b50d902SRodney W. Grimes }
3399b50d902SRodney W. Grimes return;
3409b50d902SRodney W. Grimes
3419b50d902SRodney W. Grimes err: if (ofp) {
3429b50d902SRodney W. Grimes if (oreg)
3439b50d902SRodney W. Grimes (void)unlink(out);
3449b50d902SRodney W. Grimes (void)fclose(ofp);
3459b50d902SRodney W. Grimes }
3469b50d902SRodney W. Grimes if (ifp)
3479b50d902SRodney W. Grimes (void)fclose(ifp);
3489b50d902SRodney W. Grimes }
3499b50d902SRodney W. Grimes
350305700d9SEd Schouten static void
setfile(const char * name,struct stat * fs)35147e9e6a1SDavid Malone setfile(const char *name, struct stat *fs)
3529b50d902SRodney W. Grimes {
353d6b3ef63SJilles Tjoelker static struct timespec tspec[2];
3549b50d902SRodney W. Grimes
3559b50d902SRodney W. Grimes fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
3569b50d902SRodney W. Grimes
357d6b3ef63SJilles Tjoelker tspec[0] = fs->st_atim;
358d6b3ef63SJilles Tjoelker tspec[1] = fs->st_mtim;
359d6b3ef63SJilles Tjoelker if (utimensat(AT_FDCWD, name, tspec, 0))
360d6b3ef63SJilles Tjoelker cwarn("utimensat: %s", name);
3619b50d902SRodney W. Grimes
3629b50d902SRodney W. Grimes /*
3639b50d902SRodney W. Grimes * Changing the ownership probably won't succeed, unless we're root
3649b50d902SRodney W. Grimes * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
3659b50d902SRodney W. Grimes * the mode; current BSD behavior is to remove all setuid bits on
3669b50d902SRodney W. Grimes * chown. If chown fails, lose setuid/setgid bits.
3679b50d902SRodney W. Grimes */
3689b50d902SRodney W. Grimes if (chown(name, fs->st_uid, fs->st_gid)) {
3699b50d902SRodney W. Grimes if (errno != EPERM)
3709b50d902SRodney W. Grimes cwarn("chown: %s", name);
3719b50d902SRodney W. Grimes fs->st_mode &= ~(S_ISUID|S_ISGID);
3729b50d902SRodney W. Grimes }
373da94aa4eSTim Vanderhoek if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP)
374fae643c5SPhilippe Charnier cwarn("chmod: %s", name);
3759b50d902SRodney W. Grimes
376da94aa4eSTim Vanderhoek if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP)
3779b50d902SRodney W. Grimes cwarn("chflags: %s", name);
3789b50d902SRodney W. Grimes }
3799b50d902SRodney W. Grimes
380305700d9SEd Schouten static int
permission(const char * fname)38147e9e6a1SDavid Malone permission(const char *fname)
3829b50d902SRodney W. Grimes {
3839b50d902SRodney W. Grimes int ch, first;
3849b50d902SRodney W. Grimes
3859b50d902SRodney W. Grimes if (!isatty(fileno(stderr)))
3869b50d902SRodney W. Grimes return (0);
3879b50d902SRodney W. Grimes (void)fprintf(stderr, "overwrite %s? ", fname);
3889b50d902SRodney W. Grimes first = ch = getchar();
3899b50d902SRodney W. Grimes while (ch != '\n' && ch != EOF)
3909b50d902SRodney W. Grimes ch = getchar();
3919b50d902SRodney W. Grimes return (first == 'y');
3929b50d902SRodney W. Grimes }
3939b50d902SRodney W. Grimes
394305700d9SEd Schouten static void
usage(int iscompress)39547e9e6a1SDavid Malone usage(int iscompress)
3969b50d902SRodney W. Grimes {
3979b50d902SRodney W. Grimes if (iscompress)
3989b50d902SRodney W. Grimes (void)fprintf(stderr,
3999b50d902SRodney W. Grimes "usage: compress [-cfv] [-b bits] [file ...]\n");
4009b50d902SRodney W. Grimes else
4019b50d902SRodney W. Grimes (void)fprintf(stderr,
4029b50d902SRodney W. Grimes "usage: uncompress [-c] [-b bits] [file ...]\n");
4039b50d902SRodney W. Grimes exit(1);
4049b50d902SRodney W. Grimes }
4059b50d902SRodney W. Grimes
406305700d9SEd Schouten static void
cwarnx(const char * fmt,...)4079b50d902SRodney W. Grimes cwarnx(const char *fmt, ...)
4089b50d902SRodney W. Grimes {
4099b50d902SRodney W. Grimes va_list ap;
4107ddea7b8SWarner Losh
4119b50d902SRodney W. Grimes va_start(ap, fmt);
4129b50d902SRodney W. Grimes vwarnx(fmt, ap);
4139b50d902SRodney W. Grimes va_end(ap);
4149b50d902SRodney W. Grimes eval = 1;
4159b50d902SRodney W. Grimes }
4169b50d902SRodney W. Grimes
417305700d9SEd Schouten static void
cwarn(const char * fmt,...)4189b50d902SRodney W. Grimes cwarn(const char *fmt, ...)
4199b50d902SRodney W. Grimes {
4209b50d902SRodney W. Grimes va_list ap;
4217ddea7b8SWarner Losh
4229b50d902SRodney W. Grimes va_start(ap, fmt);
4239b50d902SRodney W. Grimes vwarn(fmt, ap);
4249b50d902SRodney W. Grimes va_end(ap);
4259b50d902SRodney W. Grimes eval = 1;
4269b50d902SRodney W. Grimes }
427