Annotation of src/usr.bin/compress/main.c, Revision 1.19
1.19 ! millert 1: /* $OpenBSD: main.c,v 1.18 2002/12/08 16:07:54 mickey Exp $ */
1.1 mickey 2:
1.18 mickey 3: static const char copyright[] =
4: "@(#) Copyright (c) 1992, 1993\n\
5: The Regents of the University of California. All rights reserved.\n"
6: "Copyright (c) 1997-2002 Michael Shalayeff\n";
1.1 mickey 7:
1.18 mickey 8: static const char license[] =
9: "\n"
10: " Redistribution and use in source and binary forms, with or without\n"
11: " modification, are permitted provided that the following conditions\n"
12: " are met:\n"
13: " 1. Redistributions of source code must retain the above copyright\n"
14: " notice, this list of conditions and the following disclaimer.\n"
15: " 2. Redistributions in binary form must reproduce the above copyright\n"
16: " notice, this list of conditions and the following disclaimer in the\n"
17: " documentation and/or other materials provided with the distribution.\n"
18: " 3. All advertising materials mentioning features or use of this software\n"
19: " must display the following acknowledgement:\n"
20: " This product includes software developed by the University of\n"
21: " California, Berkeley and its contributors.\n"
22: "\n"
23: " THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
24: " IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
25: " OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
26: " IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,\n"
27: " INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
28: " (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n"
29: " SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
30: " HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n"
31: " STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n"
32: " IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n"
33: " THE POSSIBILITY OF SUCH DAMAGE.\n";
1.1 mickey 34:
35: #ifndef lint
36: #if 0
37: static char sccsid[] = "@(#)compress.c 8.2 (Berkeley) 1/7/94";
38: #else
1.19 ! millert 39: static const char main_rcsid[] = "$OpenBSD: main.c,v 1.18 2002/12/08 16:07:54 mickey Exp $";
1.1 mickey 40: #endif
41: #endif /* not lint */
42:
43: #include <sys/param.h>
44: #include <sys/time.h>
45: #include <sys/stat.h>
46:
1.18 mickey 47: #include <getopt.h>
1.1 mickey 48: #include <err.h>
49: #include <errno.h>
1.19 ! millert 50: #include <fts.h>
1.1 mickey 51: #include <stdio.h>
52: #include <stdlib.h>
53: #include <string.h>
54: #include <unistd.h>
55: #include <fcntl.h>
56: #include <paths.h>
57: #include "compress.h"
58:
59: #define min(a,b) ((a) < (b)? (a) : (b))
60:
1.18 mickey 61: int pipin, force, verbose, testmode, list, nosave;
62: int savename, recurse;
63: int bits, cat, decomp;
1.1 mickey 64: extern char *__progname;
65:
1.18 mickey 66: const struct compressor {
1.1 mickey 67: char *name;
68: char *suffix;
1.17 millert 69: int (*check_header)(int, struct stat *, const char *);
70: void *(*open)(int, const char *, int);
71: int (*read)(void *, char *, int);
72: int (*write)(void *, const char *, int);
73: int (*close)(void *);
1.1 mickey 74: } c_table[] = {
75: #define M_COMPRESS (&c_table[0])
76: { "compress", ".Z", z_check_header, z_open, zread, zwrite, zclose },
77: #define M_DEFLATE (&c_table[1])
78: { "deflate", ".gz", gz_check_header, gz_open, gz_read, gz_write, gz_close },
1.18 mickey 79: #if 0
80: #define M_LZH (&c_table[2])
81: { "lzh", ".lzh", lzh_check_header, lzh_open, lzh_read, lzh_write, lzh_close },
82: #define M_ZIP (&c_table[3])
83: { "zip", ".zip", zip_check_header, zip_open, zip_read, zip_write, zip_close },
84: #define M_PACK (&c_table[4])
85: { "pack", ".pak",pak_check_header, pak_open, pak_read, pak_write, pak_close },
86: #endif
1.1 mickey 87: { NULL }
88: };
89:
1.18 mickey 90: int permission(const char *);
91: void setfile(const char *, struct stat *);
1.17 millert 92: void usage(void);
1.18 mickey 93: int compress(const char *, const char *, const struct compressor *, int, struct stat *);
94: int decompress(const char *, const char *, const struct compressor *, int, struct stat *);
95: const struct compressor *check_method(int, struct stat *, const char *);
96:
1.19 ! millert 97: #define OPTSTRING "123456789ab:cdfghlLnNOo:qrS:tvV"
1.18 mickey 98: const struct option longopts[] = {
99: { "ascii", no_argument, 0, 'a' },
100: { "stdout", no_argument, 0, 'c' },
101: { "to-stdout", no_argument, 0, 'c' },
102: { "decompress", no_argument, 0, 'd' },
103: { "uncompress", no_argument, 0, 'd' },
104: { "force", no_argument, 0, 'f' },
105: { "help", no_argument, 0, 'h' },
106: { "list", no_argument, 0, 'l' },
107: { "license", no_argument, 0, 'L' },
108: { "no-name", no_argument, 0, 'n' },
109: { "name", no_argument, 0, 'N' },
110: { "quiet", no_argument, 0, 'q' },
111: { "recursive", no_argument, 0, 'r' },
112: { "suffix", required_argument, 0, 'S' },
113: { "test", no_argument, 0, 't' },
114: { "verbose", no_argument, 0, 'v' },
115: { "version", no_argument, 0, 'V' },
116: { "fast", no_argument, 0, '1' },
117: { "best", no_argument, 0, '9' },
118: { NULL }
119: };
1.1 mickey 120:
121: int
122: main(argc, argv)
123: int argc;
124: char *argv[];
125: {
1.19 ! millert 126: FTS *ftsp;
! 127: FTSENT *entry;
! 128: struct stat osb;
1.18 mickey 129: const struct compressor *method;
1.19 ! millert 130: char *p, *s, *infile;
! 131: char outfile[MAXPATHLEN], _infile[MAXPATHLEN], suffix[16];
1.18 mickey 132: char *nargv[512]; /* some estimate based on ARG_MAX */
1.19 ! millert 133: int exists, oreg, ch, error, i, rc, oflag;
1.1 mickey 134:
1.19 ! millert 135: bits = cat = oflag = decomp = 0;
1.1 mickey 136: p = __progname;
137: if (p[0] == 'g') {
138: method = M_DEFLATE;
1.18 mickey 139: bits = 6;
1.1 mickey 140: p++;
141: } else
142: method = M_COMPRESS;
143:
144: decomp = 0;
145: if (!strcmp(p, "zcat")) {
146: decomp++;
147: cat++;
148: } else {
149: if (p[0] == 'u' && p[1] == 'n') {
150: p += 2;
151: decomp++;
152: }
153:
1.2 mickey 154: if (strcmp(p, "zip") &&
155: strcmp(p, "compress"))
1.1 mickey 156: errx(1, "unknown program name");
157: }
158:
1.18 mickey 159: strlcpy(suffix, method->suffix, sizeof(suffix));
160:
1.19 ! millert 161: nargv[0] = NULL;
1.18 mickey 162: if ((s = getenv("GZIP")) != NULL) {
163: char *last;
164:
165: nargv[0] = *argv++;
166: for (i = 1, (p = strtok_r(s, " ", &last)); p;
167: (p = strtok_r(NULL, " ", &last)), i++)
168: if (i < sizeof(nargv)/sizeof(nargv[1]) - argc - 1)
169: nargv[i] = p;
170: else {
171: errx(1, "GZIP is too long");
172: }
173: argc += i - 1;
174: while ((nargv[i++] = *argv++))
175: ;
176: argv = nargv;
177: }
178:
179: while ((ch = getopt_long(argc, argv, OPTSTRING, longopts, NULL)) != -1)
1.1 mickey 180: switch(ch) {
181: case '1':
182: case '2':
183: case '3':
184: case '4':
185: case '5':
186: case '6':
187: case '7':
188: case '8':
189: case '9':
190: method = M_DEFLATE;
1.18 mickey 191: strlcpy(suffix, method->suffix, sizeof(suffix));
1.1 mickey 192: bits = ch - '0';
193: break;
1.18 mickey 194: case 'a':
195: warnx("option -a is ignored on this system");
196: break;
1.1 mickey 197: case 'b':
198: bits = strtol(optarg, &p, 10);
1.7 denny 199: /*
200: * POSIX 1002.3 says 9 <= bits <= 14 for portable
201: * apps, but says the implementation may allow
202: * greater.
203: */
1.1 mickey 204: if (*p)
205: errx(1, "illegal bit count -- %s", optarg);
206: break;
207: case 'c':
208: cat++;
209: break;
210: case 'd': /* Backward compatible. */
211: decomp++;
212: break;
213: case 'f':
214: force++;
215: break;
216: case 'g':
217: method = M_DEFLATE;
1.18 mickey 218: strlcpy(suffix, method->suffix, sizeof(suffix));
219: bits = 6;
1.1 mickey 220: break;
221: case 'l':
222: list++;
223: break;
224: case 'n':
225: nosave++;
226: break;
227: case 'N':
1.18 mickey 228: nosave = 0; /* XXX not yet */
1.1 mickey 229: break;
230: case 'O':
231: method = M_COMPRESS;
1.18 mickey 232: strlcpy(suffix, method->suffix, sizeof(suffix));
1.1 mickey 233: break;
234: case 'o':
1.18 mickey 235: if (strlcpy(outfile, optarg,
236: sizeof(outfile)) >= sizeof(outfile))
237: errx(1, "-o argument is too long");
1.19 ! millert 238: oflag++;
1.1 mickey 239: break;
240: case 'q':
241: verbose = -1;
242: break;
243: case 'S':
244: p = suffix;
245: if (optarg[0] != '.')
246: *p++ = '.';
1.18 mickey 247: strlcpy(p, optarg, sizeof(suffix) - (p - suffix));
248: p = optarg;
1.1 mickey 249: break;
250: case 't':
251: testmode++;
252: break;
1.18 mickey 253: case 'V':
254: printf("%s\n%s\n%s\n", main_rcsid,
255: z_rcsid, gz_rcsid);
1.19 ! millert 256: exit (0);
1.1 mickey 257: case 'v':
258: verbose++;
259: break;
1.18 mickey 260: case 'L':
261: fputs(copyright, stderr);
262: fputs(license, stderr);
1.19 ! millert 263: exit (0);
1.18 mickey 264: case 'r':
1.19 ! millert 265: recurse++;
1.18 mickey 266: break;
267:
1.1 mickey 268: case 'h':
269: case '?':
270: default:
271: usage();
272: }
273: argc -= optind;
274: argv += optind;
275:
1.19 ! millert 276: if (argc == 0) {
! 277: if (nargv[0] == NULL)
! 278: argv = nargv;
! 279: /* XXX - make sure we don't oflow nargv in $GZIP case (millert) */
! 280: argv[0] = "/dev/stdin";
! 281: argv[1] = NULL;
! 282: pipin++;
! 283: cat++;
! 284: }
! 285: if (oflag && (recurse || argc > 1))
! 286: errx(1, "-o option may only be used with a single input file");
! 287: if (cat + testmode + oflag > 1)
! 288: errx(1, "may not mix -o, -c, or -t options");
! 289:
! 290: if ((ftsp = fts_open(argv, FTS_PHYSICAL|FTS_NOCHDIR, 0)) == NULL)
! 291: err(1, NULL);
! 292: /* XXX - set rc in cases where we "continue" below? */
! 293: for (rc = 0; (entry = fts_read(ftsp)) != NULL;) {
! 294: infile = entry->fts_path;
! 295: switch (entry->fts_info) {
! 296: case FTS_D:
! 297: if (!recurse) {
! 298: warnx("%s is a directory: ignored",
! 299: infile);
! 300: fts_set(ftsp, entry, FTS_SKIP);
! 301: }
! 302: continue;
! 303: case FTS_DP:
! 304: continue;
! 305: case FTS_NS:
! 306: /*
! 307: * If file does not exist and has no suffix,
! 308: * tack on the default suffix and try that.
! 309: */
! 310: /* XXX - is overwriting fts_statp legal? (millert) */
! 311: if (entry->fts_errno == ENOENT &&
! 312: strchr(entry->fts_accpath, '.') == NULL &&
! 313: snprintf(_infile, sizeof(_infile), "%s%s", infile,
! 314: suffix) < sizeof(_infile) &&
! 315: stat(_infile, entry->fts_statp) == 0 &&
! 316: S_ISREG(entry->fts_statp->st_mode)) {
! 317: infile = _infile;
! 318: break;
! 319: }
! 320: case FTS_ERR:
! 321: case FTS_DNR:
! 322: warnx("%s: %s", infile, strerror(entry->fts_errno));
! 323: error = 1;
! 324: continue;
! 325: default:
! 326: if (!S_ISREG(entry->fts_statp->st_mode)) {
! 327: warnx("%s not a regular file: unchanged",
! 328: infile);
! 329: continue;
1.18 mickey 330: }
1.19 ! millert 331: break;
1.9 mickey 332: }
1.1 mickey 333:
334: if (testmode)
335: strcpy(outfile, _PATH_DEVNULL);
1.19 ! millert 336: else if (cat)
1.1 mickey 337: strcpy(outfile, "/dev/stdout");
1.19 ! millert 338: else if (!oflag) {
! 339: if (decomp) {
! 340: const struct compressor *m = method;
! 341:
! 342: if ((s = strrchr(infile, '.')) != NULL &&
! 343: strcmp(s, suffix) != 0) {
! 344: for (m = &c_table[0];
! 345: m->name && strcmp(s, m->suffix);
! 346: m++)
! 347: ;
! 348: }
! 349: if (s == NULL || m->name == NULL) {
! 350: if (!recurse)
! 351: warnx("%s: unknown suffix: "
! 352: "ignored", infile);
! 353: continue;
! 354: }
! 355: method = m;
! 356: strlcpy(outfile, infile,
! 357: min(sizeof(outfile), (s - infile) + 1));
! 358: } else {
! 359: if (snprintf(outfile, sizeof(outfile),
! 360: "%s%s", infile, suffix) >= sizeof(outfile)) {
! 361: warnx("%s%s: name too long",
! 362: infile, suffix);
! 363: continue;
! 364: }
! 365: }
1.1 mickey 366: }
367:
1.19 ! millert 368: exists = !stat(outfile, &osb);
! 369: if (!force && exists && S_ISREG(osb.st_mode) &&
! 370: !permission(outfile))
1.1 mickey 371: continue;
372:
1.19 ! millert 373: oreg = !exists || S_ISREG(osb.st_mode);
1.1 mickey 374:
375: if (verbose > 0)
376: fprintf(stderr, "%s:\t", infile);
377:
1.19 ! millert 378: error = (decomp ? decompress : compress)
! 379: (infile, outfile, method, bits, entry->fts_statp);
1.1 mickey 380:
1.19 ! millert 381: if (!error && !cat && !testmode && stat(outfile, &osb) == 0) {
! 382: if (!force && !decomp &&
! 383: osb.st_size >= entry->fts_statp->st_size) {
1.1 mickey 384: if (verbose > 0)
385: fprintf(stderr, "file would grow; "
386: "left unmodified\n");
387: error = 1;
1.19 ! millert 388: rc = rc ? rc : 2;
1.1 mickey 389: } else {
1.19 ! millert 390: setfile(outfile, entry->fts_statp);
1.1 mickey 391:
392: if (unlink(infile) && verbose >= 0)
1.18 mickey 393: warn("input: %s", infile);
1.1 mickey 394:
395: if (verbose > 0) {
396: u_int ratio;
1.19 ! millert 397: ratio = (1000 * osb.st_size)
! 398: / entry->fts_statp->st_size;
1.1 mickey 399: fprintf(stderr, "%u", ratio / 10);
400: if (ratio % 10)
401: fprintf(stderr, ".%u",
402: ratio % 10);
403: fputc('%', stderr);
404: fputc(' ', stderr);
405: }
406: }
407: }
408:
1.5 mickey 409: if (error && oreg && unlink(outfile) && errno != ENOENT &&
1.18 mickey 410: verbose >= 0) {
411: if (force) {
412: warn("output: %s", outfile);
413: rc = 1;
414: } else
415: err(1, "output: %s", outfile);
416: } else if (!error && verbose > 0)
1.1 mickey 417: fputs("OK\n", stderr);
1.19 ! millert 418: }
1.1 mickey 419:
1.18 mickey 420: exit(rc);
1.1 mickey 421: }
422:
423: int
1.18 mickey 424: compress(in, out, method, bits, sb)
1.1 mickey 425: const char *in;
426: const char *out;
1.18 mickey 427: const struct compressor *method;
1.1 mickey 428: int bits;
1.18 mickey 429: struct stat *sb;
1.1 mickey 430: {
1.18 mickey 431: u_char buf[Z_BUFSIZE];
432: int error, ifd, ofd;
1.16 mpech 433: void *cookie;
434: ssize_t nr;
1.1 mickey 435:
436: error = 0;
437: cookie = NULL;
1.3 mickey 438:
439: if ((ofd = open(out, O_WRONLY|O_CREAT, S_IWUSR)) < 0) {
440: if (verbose >= 0)
441: warn("%s", out);
1.19 ! millert 442: return (-1);
1.3 mickey 443: }
444:
1.4 mickey 445: if (method != M_COMPRESS && !force && isatty(ofd)) {
1.3 mickey 446: if (verbose >= 0)
447: warnx("%s: won't write compressed data to terminal",
448: out);
1.19 ! millert 449: return (-1);
1.3 mickey 450: }
1.1 mickey 451:
1.18 mickey 452: if ((ifd = open(in, O_RDONLY)) < 0) {
453: if (verbose >= 0)
454: warn("%s", out);
1.19 ! millert 455: return (-1);
1.18 mickey 456: }
457:
458: if ((cookie = (*method->open)(ofd, "w", bits)) != NULL) {
1.1 mickey 459:
1.12 mickey 460: while ((nr = read(ifd, buf, sizeof(buf))) > 0)
1.1 mickey 461: if ((method->write)(cookie, buf, nr) != nr) {
462: if (verbose >= 0)
463: warn("%s", out);
464: error++;
465: break;
466: }
467: }
468:
1.18 mickey 469: if (cookie == NULL || nr < 0) {
1.1 mickey 470: if (!error && verbose >= 0)
471: warn("%s", in);
472: error++;
473: }
474:
1.3 mickey 475: if (cookie == NULL || (method->close)(cookie)) {
1.1 mickey 476: if (!error && verbose >= 0)
477: warn("%s", out);
478: error++;
479: (void) close(ofd);
480: }
481:
1.18 mickey 482: if (close(ifd)) {
483: if (!error && verbose >= 0)
484: warn("%s", out);
485: error++;
486: }
487:
1.19 ! millert 488: return (error ? -1 : 0);
1.1 mickey 489: }
490:
1.18 mickey 491: const struct compressor *
492: check_method(fd, sb, out)
1.1 mickey 493: int fd;
1.18 mickey 494: struct stat *sb;
1.1 mickey 495: const char *out;
496: {
1.18 mickey 497: const struct compressor *method;
1.1 mickey 498:
499: for (method = &c_table[0];
1.18 mickey 500: method->name != NULL && !(*method->check_header)(fd, sb, out);
1.1 mickey 501: method++)
502: ;
503:
504: if (method->name == NULL)
505: method = NULL;
506:
1.19 ! millert 507: return (method);
1.1 mickey 508: }
509:
510: int
1.18 mickey 511: decompress(in, out, method, bits, sb)
1.1 mickey 512: const char *in;
513: const char *out;
1.18 mickey 514: const struct compressor *method;
1.1 mickey 515: int bits;
1.18 mickey 516: struct stat *sb;
1.1 mickey 517: {
1.18 mickey 518: u_char buf[Z_BUFSIZE];
519: int error, ifd, ofd;
1.16 mpech 520: void *cookie;
521: ssize_t nr;
1.1 mickey 522:
523: error = 0;
524: cookie = NULL;
525:
1.3 mickey 526: if ((ifd = open(in, O_RDONLY)) < 0) {
527: if (verbose >= 0)
528: warn("%s", in);
529: return -1;
530: }
531:
532: if (!force && isatty(ifd)) {
533: if (verbose >= 0)
534: warnx("%s: won't read compressed data from terminal",
535: in);
536: close (ifd);
537: return -1;
538: }
539:
1.18 mickey 540: if (!pipin && (method = check_method(ifd, sb, out)) == NULL) {
1.3 mickey 541: if (verbose >= 0)
542: warnx("%s: unrecognized file format", in);
1.13 d 543: close (ifd);
1.3 mickey 544: return -1;
545: }
546:
1.19 ! millert 547: if ((ofd = open(out, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR)) < 0) {
1.18 mickey 548: if (verbose >= 0)
549: warn("%s", in);
550: return -1;
551: }
552:
553: if ((cookie = (*method->open)(ifd, "r", bits)) != NULL) {
1.1 mickey 554:
1.12 mickey 555: while ((nr = (method->read)(cookie, buf, sizeof(buf))) > 0)
1.1 mickey 556: if (write(ofd, buf, nr) != nr) {
557: if (verbose >= 0)
558: warn("%s", out);
559: error++;
560: break;
561: }
562: }
563:
1.18 mickey 564: if (cookie == NULL || (method->close)(cookie) || nr < 0) {
1.1 mickey 565: if (!error && verbose >= 0)
1.18 mickey 566: warn("%s", in);
1.1 mickey 567: error++;
1.18 mickey 568: close (ifd);
1.1 mickey 569: }
570:
1.18 mickey 571: if (close(ofd)) {
1.1 mickey 572: if (!error && verbose >= 0)
1.18 mickey 573: warn("%s", out);
1.1 mickey 574: error++;
575: }
576:
577: return error;
578: }
579:
580: void
581: setfile(name, fs)
1.18 mickey 582: const char *name;
1.16 mpech 583: struct stat *fs;
1.1 mickey 584: {
1.18 mickey 585: struct timeval tv[2];
1.1 mickey 586:
587: fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
588:
589: TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
590: TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
591: if (utimes(name, tv))
592: warn("utimes: %s", name);
593:
594: /*
595: * Changing the ownership probably won't succeed, unless we're root
596: * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
597: * the mode; current BSD behavior is to remove all setuid bits on
598: * chown. If chown fails, lose setuid/setgid bits.
599: */
600: if (chown(name, fs->st_uid, fs->st_gid)) {
601: if (errno != EPERM)
602: warn("chown: %s", name);
603: fs->st_mode &= ~(S_ISUID|S_ISGID);
604: }
605: if (chmod(name, fs->st_mode))
606: warn("chown: %s", name);
607:
1.8 millert 608: if (fs->st_flags && chflags(name, fs->st_flags))
1.1 mickey 609: warn("chflags: %s", name);
610: }
611:
612: int
613: permission(fname)
1.18 mickey 614: const char *fname;
1.1 mickey 615: {
616: int ch, first;
617:
618: if (!isatty(fileno(stderr)))
619: return (0);
620: (void)fprintf(stderr, "overwrite %s? ", fname);
621: first = ch = getchar();
622: while (ch != '\n' && ch != EOF)
623: ch = getchar();
624: return (first == 'y');
625: }
626:
627: void
628: usage()
629: {
630: fprintf(stderr,
1.18 mickey 631: "usage: %s [-cdfghlnLOqrStvV] [-b <bits>] [-[0-9]] [file ...]\n",
632: __progname);
1.1 mickey 633: exit(1);
634: }