home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / unzip / part06 < prev    next >
Internet Message Format  |  1994-09-19  |  71KB

  1. From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i071:  unzip - Info-ZIP portable UnZip, version 5.12, Part06/20
  4. Date: 18 Sep 1994 23:14:56 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <35j380$qn8@sparky.sterling.com>
  9. X-Md4-Signature: 949d3d4c8937c422284df2c765b0012c
  10.  
  11. Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  12. Posting-number: Volume 44, Issue 71
  13. Archive-name: unzip/part06
  14. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
  15. Supersedes: unzip50: Volume 31, Issue 104-117
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  unzip-5.12/extract.c unzip-5.12/vms/cmdline.c
  22. # Wrapped by kent@sparky on Sat Sep 17 23:33:39 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 6 (of 20)."'
  26. if test -f 'unzip-5.12/extract.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'unzip-5.12/extract.c'\"
  28. else
  29.   echo shar: Extracting \"'unzip-5.12/extract.c'\" \(46513 characters\)
  30.   sed "s/^X//" >'unzip-5.12/extract.c' <<'END_OF_FILE'
  31. X/*---------------------------------------------------------------------------
  32. X
  33. X  extract.c
  34. X
  35. X  This file contains the high-level routines ("driver routines") for extrac-
  36. X  ting and testing zipfile members.  It calls the low-level routines in files
  37. X  explode.c, inflate.c, unreduce.c and unshrink.c.
  38. X
  39. X  ---------------------------------------------------------------------------*/
  40. X
  41. X
  42. X#include "unzip.h"
  43. X#include "crypt.h"
  44. X#ifdef MSWIN
  45. X#  include "wizunzip.h"
  46. X#  include "replace.h"
  47. X#endif
  48. X
  49. Xint newfile;      /* used also in file_io.c (flush()) */
  50. Xulg *crc_32_tab;  /* used also in file_io.c and crypt.c (full version) */
  51. X
  52. Xstatic void makecrc __((void));
  53. Xstatic int store_info __((void));
  54. Xstatic int extract_or_test_member __((void));
  55. X
  56. X
  57. X/*******************************/
  58. X/*  Strings used in extract.c  */
  59. X/*******************************/
  60. X
  61. Xstatic char Far VersionMsg[] =
  62. X  "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  63. Xstatic char Far ComprMsg[] =
  64. X  "   skipping: %-22s  compression method %d\n";
  65. Xstatic char Far FilNamMsg[] =
  66. X  "%s:  bad filename length (%s)\n";
  67. Xstatic char Far ExtFieldMsg[] =
  68. X  "%s:  bad extra field length (%s)\n";
  69. Xstatic char Far OffsetMsg[] =
  70. X  "file #%d:  bad zipfile offset (%s):  %ld\n";
  71. Xstatic char Far ExtractMsg[] =
  72. X  "%8sing: %-22s  %s%s";
  73. X#ifndef SFX
  74. X   static char Far LengthMsg[] =
  75. X     "%s  %s:  %ld bytes required to uncompress to %lu bytes;\n    %s\
  76. X      supposed to require %lu bytes%s%s%s\n";
  77. X#endif
  78. X
  79. Xstatic char Far BadFileCommLength[] = "\n%s:  bad file comment length\n";
  80. Xstatic char Far LocalHdrSig[] = "local header sig";
  81. Xstatic char Far BadLocalHdr[] = "\nfile #%d:  bad local header\n";
  82. Xstatic char Far AttemptRecompensate[] = "  (attempting to re-compensate)\n";
  83. Xstatic char Far SkipVolumeLabel[] = "   skipping: %-22s  %svolume label\n";
  84. Xstatic char Far ReplaceQuery[] =
  85. X  "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  86. Xstatic char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
  87. Xstatic char Far NewName[] = "new name: ";
  88. Xstatic char Far InvalidResponse[] = "error:  invalid response [%c]\n";
  89. Xstatic char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n";
  90. Xstatic char Far ZeroFilesTested[] = "Caution:  zero files tested in %s.\n";
  91. X
  92. X#ifndef VMS
  93. X   static char Far VMSFormat[] =
  94. X     "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
  95. X#endif
  96. X
  97. X#ifdef CRYPT
  98. X   static char Far SkipCantGetPasswd[] =
  99. X     "   skipping: %-22s  unable to get password\n";
  100. X   static char Far SkipIncorrectPasswd[] =
  101. X     "   skipping: %-22s  incorrect password\n";
  102. X   static char Far FilesSkipBadPasswd[] =
  103. X     "%d file%s skipped because of incorrect password.\n";
  104. X   static char Far MaybeBadPasswd[] =
  105. X     "    (may instead be incorrect password)\n";
  106. X#else
  107. X   static char Far SkipEncrypted[] =
  108. X     "   skipping: %-22s  encrypted (not supported)\n";
  109. X#endif
  110. X
  111. Xstatic char Far NoErrInCompData[] =
  112. X  "No errors detected in compressed data of %s.\n";
  113. Xstatic char Far NoErrInTestedFiles[] =
  114. X  "No errors detected in %s for the %d file%s tested.\n";
  115. Xstatic char Far FilesSkipped[] =
  116. X  "%d file%s skipped because of unsupported compression or encoding.\n";
  117. X
  118. Xstatic char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
  119. Xstatic char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
  120. Xstatic char Far NotEnoughMem[] = "not enough memory to ";
  121. Xstatic char Far InvalidComprData[] = "invalid compressed data to ";
  122. Xstatic char Far Inflate[] = "inflate";
  123. X
  124. X#ifndef SFX
  125. X   static char Far Explode[] = "explode";
  126. X   static char Far Unshrink[] = "unshrink";
  127. X#endif
  128. X
  129. Xstatic char Far FileUnknownCompMethod[] = "%s:  unknown compression method\n";
  130. Xstatic char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
  131. Xstatic char Far UnsupportedExtraField[] =
  132. X  "warning:  unsupported extra field compression type--skipping\n";
  133. Xstatic char Far BadExtraFieldCRC[] =
  134. X  "error [%s]:  bad extra field CRC %08lx (should be %08lx)\n";
  135. X
  136. X
  137. X
  138. X
  139. X
  140. X/**************************************/
  141. X/*  Function extract_or_test_files()  */
  142. X/**************************************/
  143. X
  144. Xint extract_or_test_files()    /* return PK-type error code */
  145. X{
  146. X    uch *cd_inptr;
  147. X    int cd_incnt, error, error_in_archive=PK_COOL;
  148. X    int i, j, renamed, query, len, filnum=(-1), blknum=0;
  149. X    int *fn_matched=NULL, *xn_matched=NULL;
  150. X    ush members_remaining, num_skipped=0, num_bad_pwd=0;
  151. X    long cd_bufstart, bufstart, inbuf_offset, request;
  152. X    LONGINT old_extra_bytes=0L;
  153. X    static min_info info[DIR_BLKSIZ];
  154. X
  155. X
  156. X/*---------------------------------------------------------------------------
  157. X    The basic idea of this function is as follows.  Since the central di-
  158. X    rectory lies at the end of the zipfile and the member files lie at the
  159. X    beginning or middle or wherever, it is not very desirable to simply
  160. X    read a central directory entry, jump to the member and extract it, and
  161. X    then jump back to the central directory.  In the case of a large zipfile
  162. X    this would lead to a whole lot of disk-grinding, especially if each mem-
  163. X    ber file is small.  Instead, we read from the central directory the per-
  164. X    tinent information for a block of files, then go extract/test the whole
  165. X    block.  Thus this routine contains two small(er) loops within a very
  166. X    large outer loop:  the first of the small ones reads a block of files
  167. X    from the central directory; the second extracts or tests each file; and
  168. X    the outer one loops over blocks.  There's some file-pointer positioning
  169. X    stuff in between, but that's about it.  Btw, it's because of this jump-
  170. X    ing around that we can afford to be lenient if an error occurs in one of
  171. X    the member files:  we should still be able to go find the other members,
  172. X    since we know the offset of each from the beginning of the zipfile.
  173. X  ---------------------------------------------------------------------------*/
  174. X
  175. X    pInfo = info;
  176. X    members_remaining = ecrec.total_entries_central_dir;
  177. X#if (defined(CRYPT) || !defined(NO_ZIPINFO))
  178. X    newzip = TRUE;
  179. X#endif
  180. X
  181. X    /* malloc space for CRC table and generate it */
  182. X    if ((crc_32_tab = (ulg *)malloc(256*sizeof(ulg))) == (ulg *)NULL)
  183. X        return PK_MEM2;
  184. X    makecrc();
  185. X
  186. X    /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
  187. X    if (filespecs > 0  &&
  188. X        (fn_matched=(int *)malloc(filespecs*sizeof(int))) != (int *)NULL)
  189. X        for (i = 0;  i < filespecs;  ++i)
  190. X            fn_matched[i] = FALSE;
  191. X    if (xfilespecs > 0  &&
  192. X        (xn_matched=(int *)malloc(xfilespecs*sizeof(int))) != (int *)NULL)
  193. X        for (i = 0;  i < xfilespecs;  ++i)
  194. X            xn_matched[i] = FALSE;
  195. X
  196. X/*---------------------------------------------------------------------------
  197. X    Begin main loop over blocks of member files.  We know the entire central
  198. X    directory is on this disk:  we would not have any of this information un-
  199. X    less the end-of-central-directory record was on this disk, and we would
  200. X    not have gotten to this routine unless this is also the disk on which
  201. X    the central directory starts.  In practice, this had better be the ONLY
  202. X    disk in the archive, but maybe someday we'll add multi-disk support.
  203. X  ---------------------------------------------------------------------------*/
  204. X
  205. X    while (members_remaining) {
  206. X        j = 0;
  207. X
  208. X        /*
  209. X         * Loop through files in central directory, storing offsets, file
  210. X         * attributes, case-conversion and text-conversion flags until block
  211. X         * size is reached.
  212. X         */
  213. X
  214. X        while (members_remaining && (j < DIR_BLKSIZ)) {
  215. X            --members_remaining;
  216. X            pInfo = &info[j];
  217. X
  218. X            if (readbuf(sig, 4) == 0) {
  219. X                error_in_archive = PK_EOF;
  220. X                members_remaining = 0;  /* ...so no more left to do */
  221. X                break;
  222. X            }
  223. X            if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  224. X                FPRINTF(stderr, LoadFarString(CentSigMsg), j);  /* sig not found */
  225. X                FPRINTF(stderr, LoadFarString(ReportMsg));   /* check binary transfers */
  226. X                error_in_archive = PK_BADERR;
  227. X                members_remaining = 0;  /* ...so no more left to do */
  228. X                break;
  229. X            }
  230. X            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  231. X            if ((error = process_cdir_file_hdr()) != PK_COOL) {
  232. X                error_in_archive = error;   /* only PK_EOF defined */
  233. X                members_remaining = 0;  /* ...so no more left to do */
  234. X                break;
  235. X            }
  236. X            if ((error = do_string(crec.filename_length,FILENAME)) != PK_COOL) {
  237. X                if (error > error_in_archive)
  238. X                    error_in_archive = error;
  239. X                if (error > PK_WARN) {  /* fatal:  no more left to do */
  240. X                    FPRINTF(stderr, LoadFarString(FilNamMsg), filename, "central");
  241. X                    members_remaining = 0;
  242. X                    break;
  243. X                }
  244. X            }
  245. X            if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0)
  246. X            {
  247. X                if (error > error_in_archive)
  248. X                    error_in_archive = error;
  249. X                if (error > PK_WARN) {  /* fatal */
  250. X                    FPRINTF(stderr, LoadFarString(ExtFieldMsg), filename, "central");
  251. X                    members_remaining = 0;
  252. X                    break;
  253. X                }
  254. X            }
  255. X            if ((error = do_string(crec.file_comment_length,SKIP)) != PK_COOL) {
  256. X                if (error > error_in_archive)
  257. X                    error_in_archive = error;
  258. X                if (error > PK_WARN) {  /* fatal */
  259. X                    FPRINTF(stderr, LoadFarString(BadFileCommLength),
  260. X                            filename);
  261. X                    members_remaining = 0;
  262. X                    break;
  263. X                }
  264. X            }
  265. X            if (process_all_files) {
  266. X                if (store_info())
  267. X                    ++j;  /* file is OK; info[] stored; continue with next */
  268. X                else
  269. X                    ++num_skipped;
  270. X            } else {
  271. X                int   do_this_file = FALSE;
  272. X                char  **pfn = pfnames-1;
  273. X
  274. X                while (*++pfn)
  275. X                    if (match(filename, *pfn, C_flag)) {
  276. X                        do_this_file = TRUE;   /* ^-- ignore case or not? */
  277. X                        if (fn_matched)
  278. X                            fn_matched[pfn-pfnames] = TRUE;
  279. X                        break;       /* found match, so stop looping */
  280. X                    }
  281. X                if (do_this_file) {  /* check if this is an excluded file */
  282. X                    char  **pxn = pxnames-1;
  283. X
  284. X                    while (*++pxn)
  285. X                        if (match(filename, *pxn, C_flag)) {
  286. X                            do_this_file = FALSE;  /* ^-- ignore case or not? */
  287. X                            if (xn_matched)
  288. X                                xn_matched[pxn-pxnames] = TRUE;
  289. X                            break;
  290. X                        }
  291. X                }
  292. X                if (do_this_file)
  293. X                    if (store_info())
  294. X                        ++j;            /* file is OK */
  295. X                    else
  296. X                        ++num_skipped;  /* unsupp. compression or encryption */
  297. X            } /* end if (process_all_files) */
  298. X
  299. X
  300. X        } /* end while-loop (adding files to current block) */
  301. X
  302. X        /* save position in central directory so can come back later */
  303. X        cd_bufstart = cur_zipfile_bufstart;
  304. X        cd_inptr = inptr;
  305. X        cd_incnt = incnt;
  306. X
  307. X    /*-----------------------------------------------------------------------
  308. X        Second loop:  process files in current block, extracting or testing
  309. X        each one.
  310. X      -----------------------------------------------------------------------*/
  311. X
  312. X        for (i = 0; i < j; ++i) {
  313. X            filnum = i + blknum*DIR_BLKSIZ;
  314. X            pInfo = &info[i];
  315. X
  316. X            /* if the target position is not within the current input buffer
  317. X             * (either haven't yet read far enough, or (maybe) skipping back-
  318. X             * ward), skip to the target position and reset readbuf(). */
  319. X
  320. X            /* LSEEK(pInfo->offset):  */
  321. X            request = pInfo->offset + extra_bytes;
  322. X            inbuf_offset = request % INBUFSIZ;
  323. X            bufstart = request - inbuf_offset;
  324. X
  325. X            Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
  326. X              request, inbuf_offset));
  327. X            Trace((stderr,
  328. X              "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  329. X              bufstart, cur_zipfile_bufstart));
  330. X            if (request < 0) {
  331. X                FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn,
  332. X                  LoadFarString(ReportMsg));
  333. X                error_in_archive = PK_ERR;
  334. X                if (filnum == 0 && extra_bytes != 0L) {
  335. X                    FPRINTF(stderr, LoadFarString(AttemptRecompensate));
  336. X                    old_extra_bytes = extra_bytes;
  337. X                    extra_bytes = 0L;
  338. X                    request = pInfo->offset; /* could also check if this != 0 */
  339. X                    inbuf_offset = request % INBUFSIZ;
  340. X                    bufstart = request - inbuf_offset;
  341. X                    Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
  342. X                      request, inbuf_offset));
  343. X                    Trace((stderr,
  344. X                      "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  345. X                      bufstart, cur_zipfile_bufstart));
  346. X                } else {
  347. X                    error_in_archive = PK_BADERR;
  348. X                    continue;  /* this one hosed; try next */
  349. X                }
  350. X            }
  351. X            /* try again */
  352. X            if (request < 0) {
  353. X                Trace((stderr, "debug: recompensated request still < 0\n"));
  354. X                FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn,
  355. X                  LoadFarString(ReportMsg));
  356. X                error_in_archive = PK_BADERR;
  357. X                continue;
  358. X            } else if (bufstart != cur_zipfile_bufstart) {
  359. X                Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
  360. X                cur_zipfile_bufstart = lseek(zipfd,(LONGINT)bufstart,SEEK_SET);
  361. X                if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) {
  362. X                    FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "lseek",
  363. X                      bufstart);
  364. X                    error_in_archive = PK_BADERR;
  365. X                    continue;   /* can still do next file */
  366. X                }
  367. X                inptr = inbuf + (int)inbuf_offset;
  368. X                incnt -= (int)inbuf_offset;
  369. X            } else {
  370. X                incnt += (inptr-inbuf) - (int)inbuf_offset;
  371. X                inptr = inbuf + (int)inbuf_offset;
  372. X            }
  373. X
  374. X            /* should be in proper position now, so check for sig */
  375. X            if (readbuf(sig, 4) == 0) {  /* bad offset */
  376. X                FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF",
  377. X                  request);
  378. X                error_in_archive = PK_BADERR;
  379. X                continue;   /* but can still try next one */
  380. X            }
  381. X            if (strncmp(sig, local_hdr_sig, 4)) {
  382. X                FPRINTF(stderr, LoadFarString(OffsetMsg), filnum,
  383. X                  LoadFarStringSmall(LocalHdrSig), request);
  384. X                error_in_archive = PK_ERR;
  385. X                if ((filnum == 0 && extra_bytes != 0L) ||
  386. X                    (extra_bytes == 0L && old_extra_bytes != 0L)) {
  387. X                    FPRINTF(stderr, LoadFarString(AttemptRecompensate));
  388. X                    if (extra_bytes) {
  389. X                        old_extra_bytes = extra_bytes;
  390. X                        extra_bytes = 0L;
  391. X                    } else
  392. X                        extra_bytes = old_extra_bytes;  /* third attempt */
  393. X                    LSEEK(pInfo->offset)
  394. X                    if (readbuf(sig, 4) == 0) {  /* bad offset */
  395. X                        FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF",
  396. X                          request);
  397. X                        error_in_archive = PK_BADERR;
  398. X                        continue;   /* but can still try next one */
  399. X                    }
  400. X                    if (strncmp(sig, local_hdr_sig, 4)) {
  401. X                        FPRINTF(stderr, LoadFarString(OffsetMsg), filnum,
  402. X                          LoadFarStringSmall(LocalHdrSig), request);
  403. X                        error_in_archive = PK_BADERR;
  404. X                        continue;
  405. X                    }
  406. X                } else
  407. X                    continue;  /* this one hosed; try next */
  408. X            }
  409. X            if ((error = process_local_file_hdr()) != PK_COOL) {
  410. X                FPRINTF(stderr, LoadFarString(BadLocalHdr), filnum);
  411. X                error_in_archive = error;   /* only PK_EOF defined */
  412. X                continue;   /* can still try next one */
  413. X            }
  414. X            if ((error = do_string(lrec.filename_length,FILENAME)) != PK_COOL) {
  415. X                if (error > error_in_archive)
  416. X                    error_in_archive = error;
  417. X                if (error > PK_WARN) {
  418. X                    FPRINTF(stderr, LoadFarString(FilNamMsg), filename, "local");
  419. X                    continue;   /* go on to next one */
  420. X                }
  421. X            }
  422. X            if (extra_field != (uch *)NULL) {
  423. X                free(extra_field);
  424. X                extra_field = (uch *)NULL;
  425. X            }
  426. X            if ((error = do_string(lrec.extra_field_length,EXTRA_FIELD)) != 0) {
  427. X                if (error > error_in_archive)
  428. X                    error_in_archive = error;
  429. X                if (error > PK_WARN) {
  430. X                    FPRINTF(stderr, LoadFarString(ExtFieldMsg), filename, "local");
  431. X                    continue;   /* go on */
  432. X                }
  433. X            }
  434. X
  435. X            /*
  436. X             * just about to extract file:  if extracting to disk, check if
  437. X             * already exists, and if so, take appropriate action according to
  438. X             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  439. X             * loop because we don't store the possibly renamed filename[] in
  440. X             * info[])
  441. X             */
  442. X            if (!tflag && !cflag) {
  443. X                renamed = FALSE;   /* user hasn't renamed output file yet */
  444. X
  445. Xstartover:
  446. X                query = FALSE;
  447. X#ifdef MACOS
  448. X                macflag = (pInfo->hostnum == MAC_);
  449. X#endif
  450. X                /* mapname can create dirs if not freshening or if renamed */
  451. X                if ((error = mapname(renamed)) > PK_WARN) {
  452. X                    if (error == IZ_CREATED_DIR) {
  453. X
  454. X                        /* GRR:  add code to set times/attribs on dirs--
  455. X                         * save to list, sort when done (a la zip), set
  456. X                         * times/attributes on deepest dirs first */
  457. X
  458. X                    } else if (error == IZ_VOL_LABEL) {
  459. X                        FPRINTF(stderr,
  460. X                          LoadFarString(SkipVolumeLabel), filename,
  461. X#ifdef DOS_NT_OS2
  462. X                          volflag? "hard disk " :
  463. X#endif
  464. X                          "");
  465. X                    /*  if (!error_in_archive)
  466. X                            error_in_archive = PK_WARN;  */
  467. X                    } else if (error > PK_ERR  &&  error_in_archive < PK_ERR)
  468. X                        error_in_archive = PK_ERR;
  469. X                    Trace((stderr, "mapname(%s) returns error = %d\n", filename,
  470. X                      error));
  471. X                    continue;   /* go on to next file */
  472. X                }
  473. X
  474. X                switch (check_for_newer(filename)) {
  475. X                    case DOES_NOT_EXIST:
  476. X                        if (fflag && !renamed)  /* don't skip if just renamed */
  477. X                            continue;   /* freshen (no new files):  skip */
  478. X                        break;
  479. X                    case EXISTS_AND_OLDER:
  480. X                        if (overwrite_none)
  481. X                            continue;   /* never overwrite:  skip file */
  482. X                        if (!overwrite_all && !force_flag)
  483. X                            query = TRUE;
  484. X                        break;
  485. X                    case EXISTS_AND_NEWER:             /* (or equal) */
  486. X                        if (overwrite_none || (uflag && !renamed))
  487. X                            continue;  /* skip if update/freshen & orig name */
  488. X                        if (!overwrite_all && !force_flag)
  489. X                            query = TRUE;
  490. X                        break;
  491. X                }
  492. X                if (query) {
  493. X#ifdef MSWIN
  494. X                    FARPROC lpfnprocReplace;
  495. X                    int ReplaceDlgRetVal;   /* replace dialog return value */
  496. X
  497. X                    ShowCursor(FALSE);      /* turn off cursor */
  498. X                    SetCursor(hSaveCursor); /* restore the cursor */
  499. X                    lpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);
  500. X                    ReplaceDlgRetVal = DialogBoxParam(hInst, "Replace",
  501. X                      hWndMain, lpfnprocReplace, (DWORD)(LPSTR)filename);
  502. X                    FreeProcInstance(lpfnprocReplace);
  503. X                    hSaveCursor = SetCursor(hHourGlass);
  504. X                    ShowCursor(TRUE);
  505. X                    switch (ReplaceDlgRetVal) {
  506. X                        case IDM_REPLACE_RENAME:
  507. X                            renamed = TRUE;
  508. X                            goto startover;
  509. X                        case IDM_REPLACE_YES:
  510. X                            break;
  511. X                        case IDM_REPLACE_ALL:
  512. X                            overwrite_all = TRUE;
  513. X                            overwrite_none = FALSE;  /* just to make sure */
  514. X                            break;
  515. X                        case IDM_REPLACE_NONE:
  516. X                            overwrite_none = TRUE;
  517. X                            overwrite_all = FALSE;  /* make sure */
  518. X                            force_flag = FALSE;     /* ditto */
  519. X                            /* FALL THROUGH, skip */
  520. X                        case IDM_REPLACE_NO:
  521. X                            continue;
  522. X                    }
  523. X#else /* !MSWIN */
  524. Xreprompt:
  525. X                    FPRINTF(stderr, LoadFarString(ReplaceQuery), filename);
  526. X                    FFLUSH(stderr);
  527. X                    if (fgets(answerbuf, 9, stdin) == (char *)NULL) {
  528. X                        FPRINTF(stderr, LoadFarString(AssumeNone));
  529. X                        FFLUSH(stderr);
  530. X                        *answerbuf = 'N';
  531. X                        if (!error_in_archive)
  532. X                            error_in_archive = 1;  /* not extracted:  warning */
  533. X                    }
  534. X                    switch (*answerbuf) {
  535. X                        case 'A':   /* dangerous option:  force caps */
  536. X                            overwrite_all = TRUE;
  537. X                            overwrite_none = FALSE;  /* just to make sure */
  538. X                            break;
  539. X                        case 'r':
  540. X                        case 'R':
  541. X                            do {
  542. X                                FPRINTF(stderr, LoadFarString(NewName));
  543. X                                FFLUSH(stderr);
  544. X                                fgets(filename, FILNAMSIZ, stdin);
  545. X                                /* usually get \n here:  better check for it */
  546. X                                len = strlen(filename);
  547. X                                if (filename[len-1] == '\n')
  548. X                                    filename[--len] = 0;
  549. X                            } while (len == 0);
  550. X                            renamed = TRUE;
  551. X                            goto startover;   /* sorry for a goto */
  552. X                        case 'y':
  553. X                        case 'Y':
  554. X                            break;
  555. X                        case 'N':
  556. X                            overwrite_none = TRUE;
  557. X                            overwrite_all = FALSE;  /* make sure */
  558. X                            force_flag = FALSE;     /* ditto */
  559. X                            /* FALL THROUGH, skip */
  560. X                        case 'n':
  561. X                            continue;   /* skip file */
  562. X                        default:
  563. X                            FPRINTF(stderr, LoadFarString(InvalidResponse),
  564. X                              *answerbuf);   /* warn the user */
  565. X                            goto reprompt;   /* why not another goto? */
  566. X                    } /* end switch (*answerbuf) */
  567. X#endif /* ?MSWIN */
  568. X                } /* end if (query) */
  569. X            } /* end if (extracting to disk) */
  570. X
  571. X#ifdef CRYPT
  572. X            if (pInfo->encrypted && (error = decrypt()) != PK_COOL) {
  573. X                if (error == PK_MEM2) {
  574. X                    if (error > error_in_archive)
  575. X                        error_in_archive = error;
  576. X                    FPRINTF(stderr,
  577. X                      LoadFarString(SkipCantGetPasswd), filename);
  578. X                } else {  /* (error == PK_WARN) */
  579. X                    if (!((tflag && qflag) || (!tflag && !QCOND2)))
  580. X                        FPRINTF(stderr,
  581. X                          LoadFarString(SkipIncorrectPasswd), filename);
  582. X                    ++num_bad_pwd;
  583. X                }
  584. X                continue;   /* go on to next file */
  585. X            }
  586. X#endif /* CRYPT */
  587. X            disk_full = 0;
  588. X            if ((error = extract_or_test_member()) != PK_COOL) {
  589. X                if (error > error_in_archive)
  590. X                    error_in_archive = error;       /* ...and keep going */
  591. X                if (disk_full > 1) {
  592. X                    free(crc_32_tab);
  593. X                    if (fn_matched)
  594. X                        free(fn_matched);
  595. X                    if (xn_matched)
  596. X                        free(xn_matched);
  597. X                    return error_in_archive;        /* (unless disk full) */
  598. X                }
  599. X            }
  600. X        } /* end for-loop (i:  files in current block) */
  601. X
  602. X
  603. X        /*
  604. X         * Jump back to where we were in the central directory, then go and do
  605. X         * the next batch of files.
  606. X         */
  607. X
  608. X        cur_zipfile_bufstart = lseek(zipfd, (LONGINT)cd_bufstart, SEEK_SET);
  609. X        read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error */
  610. X        inptr = cd_inptr;
  611. X        incnt = cd_incnt;
  612. X        ++blknum;
  613. X
  614. X#ifdef TEST
  615. X        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  616. X        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
  617. X          cur_zipfile_bufstart);
  618. X        printf("inptr-inbuf = %d\n", inptr-inbuf);
  619. X        printf("incnt = %d\n\n", incnt);
  620. X#endif
  621. X
  622. X    } /* end while-loop (blocks of files in central directory) */
  623. X
  624. X/*---------------------------------------------------------------------------
  625. X    Check for unmatched filespecs on command line and print warning if any
  626. X    found.  Free allocated memory.
  627. X  ---------------------------------------------------------------------------*/
  628. X
  629. X    if (fn_matched) {
  630. X        for (i = 0;  i < filespecs;  ++i)
  631. X            if (!fn_matched[i])
  632. X                FPRINTF(stderr, LoadFarString(FilenameNotMatched),
  633. X                  pfnames[i]);
  634. X        free(fn_matched);
  635. X    }
  636. X    if (xn_matched) {
  637. X        for (i = 0;  i < xfilespecs;  ++i)
  638. X            if (!xn_matched[i])
  639. X                FPRINTF(stderr, LoadFarString(ExclFilenameNotMatched),
  640. X                  pxnames[i]);
  641. X        free(xn_matched);
  642. X    }
  643. X    free(crc_32_tab);
  644. X
  645. X/*---------------------------------------------------------------------------
  646. X    Double-check that we're back at the end-of-central-directory record, and
  647. X    print quick summary of results, if we were just testing the archive.  We
  648. X    send the summary to stdout so that people doing the testing in the back-
  649. X    ground and redirecting to a file can just do a "tail" on the output file.
  650. X  ---------------------------------------------------------------------------*/
  651. X
  652. X    if (readbuf(sig, 4) == 0)
  653. X        error_in_archive = PK_EOF;
  654. X    if (strncmp(sig, end_central_sig, 4)) {         /* just to make sure */
  655. X        FPRINTF(stderr, LoadFarString(EndSigMsg));  /* didn't find sig */
  656. X        FPRINTF(stderr, LoadFarString(ReportMsg));  /* check binary transfers */
  657. X        if (!error_in_archive)       /* don't overwrite stronger error */
  658. X            error_in_archive = PK_WARN;
  659. X    }
  660. X    ++filnum;  /* initialized to -1, so now zero if no files found */
  661. X    if (tflag) {
  662. X        int num=filnum - num_bad_pwd;
  663. X
  664. X        if (qflag < 2) {         /* GRR 930710:  was (qflag == 1) */
  665. X            if (error_in_archive)
  666. X                PRINTF(LoadFarString(ErrorInArchive),
  667. X                  (error_in_archive == 1)? "warning-" : "", zipfn);
  668. X            else if (num == 0)
  669. X                PRINTF(LoadFarString(ZeroFilesTested), zipfn);
  670. X            else if (process_all_files && (num_skipped+num_bad_pwd == 0))
  671. X                PRINTF(LoadFarString(NoErrInCompData), zipfn);
  672. X            else
  673. X                PRINTF(LoadFarString(NoErrInTestedFiles),
  674. X                  zipfn, num, (num==1)? "":"s");
  675. X            if (num_skipped > 0)
  676. X                PRINTF(LoadFarString(FilesSkipped), num_skipped,
  677. X                  (num_skipped==1)? "":"s");
  678. X#ifdef CRYPT
  679. X            if (num_bad_pwd > 0)
  680. X                PRINTF(LoadFarString(FilesSkipBadPasswd),
  681. X                  num_bad_pwd, (num_bad_pwd==1)? "":"s");
  682. X#endif /* CRYPT */
  683. X        } else if ((qflag == 0) && !error_in_archive && (num == 0))
  684. X            PRINTF(LoadFarString(ZeroFilesTested), zipfn);
  685. X    }
  686. X
  687. X    /* give warning if files not tested or extracted */
  688. X    if ((filnum == 0) && error_in_archive <= PK_WARN)
  689. X        error_in_archive = PK_FIND;   /* no files found at all */
  690. X    else if ((num_skipped > 0) && !error_in_archive)
  691. X        error_in_archive = PK_WARN;
  692. X#ifdef CRYPT
  693. X    else if ((num_bad_pwd > 0) && !error_in_archive)
  694. X        error_in_archive = PK_WARN;
  695. X#endif /* CRYPT */
  696. X
  697. X    return error_in_archive;
  698. X
  699. X} /* end function extract_or_test_files() */
  700. X
  701. X
  702. X
  703. X
  704. X
  705. X/**********************/
  706. X/* Function makecrc() */
  707. X/**********************/
  708. X
  709. Xstatic void makecrc()
  710. X/*
  711. X  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
  712. X  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
  713. X
  714. X  Polynomials over GF(2) are represented in binary, one bit per coefficient,
  715. X  with the lowest powers in the most significant bit.  Then adding polynomials
  716. X  is just exclusive-or, and multiplying a polynomial by x is a right shift by
  717. X  one.  If we call the above polynomial p, and represent a byte as the
  718. X  polynomial q, also with the lowest power in the most significant bit (so the
  719. X  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  720. X  where a mod b means the remainder after dividing a by b.
  721. X
  722. X  This calculation is done using the shift-register method of multiplying and
  723. X  taking the remainder.  The register is initialized to zero, and for each
  724. X  incoming bit, x^32 is added mod p to the register if the bit is a one (where
  725. X  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  726. X  x (which is shifting right by one and adding x^32 mod p if the bit shifted
  727. X  out is a one).  We start with the highest power (least significant bit) of
  728. X  q and repeat for all eight bits of q.
  729. X
  730. X  The table is simply the CRC of all possible eight bit values.  This is all
  731. X  the information needed to generate CRC's on data a byte at a time for all
  732. X  combinations of CRC register values and incoming bytes.  The table is
  733. X  written to stdout as 256 long hexadecimal values in C language format.
  734. X*/
  735. X{
  736. X    ulg crc;   /* crc shift register */
  737. X    ulg xor;   /* polynomial exclusive-or pattern */
  738. X    int i;     /* counter for all possible eight bit values */
  739. X    int k;     /* byte being shifted into crc apparatus */
  740. X    /* terms of polynomial defining this crc (except x^32): */
  741. X    static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
  742. X
  743. X    /* make exclusive-or pattern from polynomial (0xedb88320) */
  744. X    xor = 0L;
  745. X    for (i = 0; i < sizeof(p)/sizeof(uch); i++)
  746. X        xor |= 1L << (31 - p[i]);
  747. X
  748. X    crc_32_tab[0] = 0L;
  749. X    Trace((stderr, "makecrc():  crc_32_tab[] = {\n  0x%08lxL", crc_32_tab[0]));
  750. X    /* the idea to initialize the register with the byte instead of
  751. X     * zero was stolen from Haruhiko Okumura's ar002 */
  752. X    for (i = 1; i < 256; i++) {
  753. X        crc = i;
  754. X        for (k = 8; k; k--)
  755. X            crc = crc & 1 ? (crc >> 1) ^ xor : crc >> 1;
  756. X        crc_32_tab[i] = crc;
  757. X        Trace((stderr, i % 5 ? ", 0x%08lxL" : ",\n  0x%08lxL", crc_32_tab[i]));
  758. X    }
  759. X    Trace((stderr, "\n};\n"));
  760. X
  761. X} /* end function makecrc() */
  762. X
  763. X
  764. X
  765. X
  766. X
  767. X/***************************/
  768. X/*  Function store_info()  */
  769. X/***************************/
  770. X
  771. Xstatic int store_info()   /* return 0 if skipping, 1 if OK */
  772. X{
  773. X#ifdef SFX
  774. X#  define UNKN_COMPR \
  775. X   (crec.compression_method!=STORED && crec.compression_method!=DEFLATED)
  776. X#else
  777. X#  define UNKN_COMPR \
  778. X   (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
  779. X#endif
  780. X
  781. X/*---------------------------------------------------------------------------
  782. X    Check central directory info for version/compatibility requirements.
  783. X  ---------------------------------------------------------------------------*/
  784. X
  785. X    pInfo->encrypted = crec.general_purpose_bit_flag & 1;       /* bit field */
  786. X    pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;/* bit field */
  787. X    pInfo->textfile = crec.internal_file_attributes & 1;        /* bit field */
  788. X    pInfo->crc = crec.crc32;
  789. X    pInfo->compr_size = crec.csize;
  790. X
  791. X    switch (aflag) {
  792. X        case 0:
  793. X            pInfo->textmode = FALSE;   /* bit field */
  794. X            break;
  795. X        case 1:
  796. X            pInfo->textmode = pInfo->textfile;   /* auto-convert mode */
  797. X            break;
  798. X        default:  /* case 2: */
  799. X            pInfo->textmode = TRUE;
  800. X            break;
  801. X    }
  802. X
  803. X    if (crec.version_needed_to_extract[1] == VMS_) {
  804. X        if (crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  805. X            if (!((tflag && qflag) || (!tflag && !QCOND2)))
  806. X                FPRINTF(stderr, LoadFarString(VersionMsg), filename, "VMS",
  807. X                  crec.version_needed_to_extract[0] / 10,
  808. X                  crec.version_needed_to_extract[0] % 10,
  809. X                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10);
  810. X            return 0;
  811. X        }
  812. X#ifndef VMS   /* won't be able to use extra field, but still have data */
  813. X        else if (!tflag && !force_flag) {  /* if forcing, extract regardless */
  814. X            FPRINTF(stderr, LoadFarString(VMSFormat), filename);
  815. X            FFLUSH(stderr);
  816. X            fgets(answerbuf, 9, stdin);
  817. X            if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
  818. X                return 0;
  819. X        }
  820. X#endif /* !VMS */
  821. X    /* usual file type:  don't need VMS to extract */
  822. X    } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
  823. X        if (!((tflag && qflag) || (!tflag && !QCOND2)))
  824. X            FPRINTF(stderr, LoadFarString(VersionMsg), filename, "PK",
  825. X              crec.version_needed_to_extract[0] / 10,
  826. X              crec.version_needed_to_extract[0] % 10,
  827. X              UNZIP_VERSION / 10, UNZIP_VERSION % 10);
  828. X        return 0;
  829. X    }
  830. X
  831. X    if UNKN_COMPR {
  832. X        if (!((tflag && qflag) || (!tflag && !QCOND2)))
  833. X            FPRINTF(stderr, LoadFarString(ComprMsg), filename,
  834. X              crec.compression_method);
  835. X        return 0;
  836. X    }
  837. X#ifndef CRYPT
  838. X    if (pInfo->encrypted) {
  839. X        if (!((tflag && qflag) || (!tflag && !QCOND2)))
  840. X            FPRINTF(stderr, LoadFarString(SkipEncrypted), filename);
  841. X        return 0;
  842. X    }
  843. X#endif /* !CRYPT */
  844. X
  845. X    /* map whatever file attributes we have into the local format */
  846. X    mapattr();   /* GRR:  worry about return value later */
  847. X
  848. X    pInfo->offset = (long) crec.relative_offset_local_header;
  849. X    return 1;
  850. X
  851. X} /* end function store_info() */
  852. X
  853. X
  854. X
  855. X
  856. X
  857. X/***************************************/
  858. X/*  Function extract_or_test_member()  */
  859. X/***************************************/
  860. X
  861. Xstatic int extract_or_test_member()    /* return PK-type error code */
  862. X{
  863. X    char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
  864. X    register int b;
  865. X    int r, error=PK_COOL;
  866. X
  867. X
  868. X
  869. X/*---------------------------------------------------------------------------
  870. X    Initialize variables, buffers, etc.
  871. X  ---------------------------------------------------------------------------*/
  872. X
  873. X    bits_left = 0;     /* unreduce and unshrink only */
  874. X    bitbuf = 0L;       /* unreduce and unshrink only */
  875. X    zipeof = 0;        /* unreduce and unshrink only */
  876. X    newfile = TRUE;
  877. X    crc32val = 0xFFFFFFFFL;
  878. X
  879. X#ifdef SYMLINKS
  880. X    /* if file came from Unix and is a symbolic link and we are extracting
  881. X     * to disk, prepare to restore the link */
  882. X    if (S_ISLNK(pInfo->file_attr) && (pInfo->hostnum == UNIX_) && !tflag &&
  883. X        !cflag && (lrec.ucsize > 0))
  884. X        symlnk = TRUE;
  885. X    else
  886. X        symlnk = FALSE;
  887. X#endif /* SYMLINKS */
  888. X
  889. X    if (tflag) {
  890. X        if (!qflag) {
  891. X            FPRINTF(stdout, LoadFarString(ExtractMsg), "test", filename, "", "");
  892. X            fflush(stdout);
  893. X        }
  894. X    } else {
  895. X        if (cflag) {
  896. X            outfile = stdout;
  897. X#ifdef DOS_NT_OS2
  898. X            setmode(fileno(outfile), O_BINARY);
  899. X#           define NEWLINE "\r\n"
  900. X#else
  901. X#           define NEWLINE "\n"
  902. X#endif
  903. X#ifdef VMS
  904. X            if (open_outfile())   /* VMS:  required even for stdout! */
  905. X                return PK_DISK;
  906. X#endif
  907. X        } else if (open_outfile())
  908. X            return PK_DISK;
  909. X    }
  910. X
  911. X/*---------------------------------------------------------------------------
  912. X    Unpack the file.
  913. X  ---------------------------------------------------------------------------*/
  914. X
  915. X    switch (lrec.compression_method) {
  916. X        case STORED:
  917. X            if (!tflag && QCOND2) {
  918. X#ifdef SYMLINKS
  919. X                if (symlnk)   /* can also be deflated, but rarer... */
  920. X                    FPRINTF(stdout, LoadFarString(ExtractMsg), "link", filename,
  921. X                      "", "");
  922. X                else
  923. X#endif /* SYMLINKS */
  924. X                FPRINTF(stdout, LoadFarString(ExtractMsg), "extract", filename,
  925. X                  (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
  926. X                  : (lrec.ucsize == 0L? nul : (pInfo->textfile? txt : bin)),
  927. X                  cflag? NEWLINE : "");
  928. X                fflush(stdout);
  929. X            }
  930. X            outptr = slide;
  931. X            outcnt = 0L;
  932. X            while ((b = NEXTBYTE) != EOF && !disk_full) {
  933. X                *outptr++ = (uch)b;
  934. X                if (++outcnt == WSIZE) {
  935. X                    flush(slide, outcnt, 0);
  936. X                    outptr = slide;
  937. X                    outcnt = 0L;
  938. X                }
  939. X            }
  940. X            if (outcnt)          /* flush final (partial) buffer */
  941. X                flush(slide, outcnt, 0);
  942. X            break;
  943. X
  944. X#ifndef SFX
  945. X        case SHRUNK:
  946. X            if (!tflag && QCOND2) {
  947. X                FPRINTF(stdout, LoadFarString(ExtractMsg),
  948. X                  LoadFarStringSmall(Unshrink), filename,
  949. X                  (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
  950. X                  : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
  951. X                fflush(stdout);
  952. X            }
  953. X            if ((r = unshrink()) != PK_COOL) {
  954. X                if ((tflag && qflag) || (!tflag && !QCOND2))
  955. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile),
  956. X                      LoadFarString(NotEnoughMem),
  957. X                      LoadFarStringSmall2(Unshrink),
  958. X                      filename);
  959. X                else
  960. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile),
  961. X                      LoadFarString(NotEnoughMem),
  962. X                      LoadFarStringSmall2(Unshrink));
  963. X                error = r;
  964. X            }
  965. X            break;
  966. X
  967. X        case REDUCED1:
  968. X        case REDUCED2:
  969. X        case REDUCED3:
  970. X        case REDUCED4:
  971. X            if (!tflag && QCOND2) {
  972. X                FPRINTF(stdout, LoadFarString(ExtractMsg), "unreduc", filename,
  973. X                  (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
  974. X                  : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
  975. X                fflush(stdout);
  976. X            }
  977. X            unreduce();
  978. X            break;
  979. X
  980. X        case IMPLODED:
  981. X            if (!tflag && QCOND2) {
  982. X                FPRINTF(stdout, LoadFarString(ExtractMsg), "explod", filename,
  983. X                  (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
  984. X                  : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
  985. X                fflush(stdout);
  986. X            }
  987. X            if (((r = explode()) != 0) && (r != 5)) {   /* treat 5 specially */
  988. X                if ((tflag && qflag) || (!tflag && !QCOND2))
  989. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile), r == 3?
  990. X                      LoadFarString(NotEnoughMem) :
  991. X                      LoadFarString(InvalidComprData),
  992. X                      LoadFarStringSmall2(Explode), filename);
  993. X                else
  994. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  995. X                      LoadFarString(NotEnoughMem) :
  996. X                      LoadFarString(InvalidComprData),
  997. X                      LoadFarStringSmall2(Explode));
  998. X                error = (r == 3)? PK_MEM3 : PK_ERR;
  999. X            }
  1000. X            if (r == 5) {
  1001. X                int warning = ((ulg)used_csize <= lrec.csize);
  1002. X
  1003. X                if ((tflag && qflag) || (!tflag && !QCOND2))
  1004. X                    FPRINTF(stderr, LoadFarString(LengthMsg), "", warning?
  1005. X                      "warning":"error", used_csize, lrec.ucsize, warning?
  1006. X                      "  ":"", lrec.csize, " [", filename, "]");
  1007. X                else
  1008. X                    FPRINTF(stderr, LoadFarString(LengthMsg), "\n", warning?
  1009. X                      "warning":"error", used_csize, lrec.ucsize, warning?
  1010. X                      "  ":"", lrec.csize, "", "", ".");
  1011. X                error = warning? PK_WARN : PK_ERR;
  1012. X            }
  1013. X            break;
  1014. X#endif /* !SFX */
  1015. X
  1016. X        case DEFLATED:
  1017. X            if (!tflag && QCOND2) {
  1018. X                FPRINTF(stdout, LoadFarString(ExtractMsg), "inflat", filename,
  1019. X                  (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
  1020. X                  : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
  1021. X                fflush(stdout);
  1022. X            }
  1023. X            if ((r = inflate()) != 0) {
  1024. X                if ((tflag && qflag) || (!tflag && !QCOND2))
  1025. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile), r == 3?
  1026. X                      LoadFarString(NotEnoughMem) :
  1027. X                      LoadFarString(InvalidComprData),
  1028. X                      LoadFarStringSmall2(Inflate), filename);
  1029. X                else
  1030. X                    FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1031. X                      LoadFarString(NotEnoughMem) :
  1032. X                      LoadFarString(InvalidComprData),
  1033. X                      LoadFarStringSmall2(Inflate));
  1034. X                error = (r == 3)? PK_MEM3 : PK_ERR;
  1035. X            }
  1036. X            break;
  1037. X
  1038. X        default:   /* should never get to this point */
  1039. X            FPRINTF(stderr, LoadFarString(FileUnknownCompMethod), filename);
  1040. X            /* close and delete file before return? */
  1041. X            return PK_WARN;
  1042. X
  1043. X    } /* end switch (compression method) */
  1044. X
  1045. X    if (disk_full) {            /* set by flush() */
  1046. X        if (disk_full > 1)
  1047. X            return PK_DISK;
  1048. X        error = PK_WARN;
  1049. X    }
  1050. X
  1051. X/*---------------------------------------------------------------------------
  1052. X    Close the file and set its date and time (not necessarily in that order),
  1053. X    and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
  1054. X    machines (redundant on 32-bit machines).
  1055. X  ---------------------------------------------------------------------------*/
  1056. X
  1057. X#ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
  1058. X    if (!tflag)             /* don't close NULL file */
  1059. X#else
  1060. X    if (!tflag && !cflag)   /* don't close NULL file or stdout */
  1061. X#endif
  1062. X        close_outfile();
  1063. X
  1064. X    if (error > PK_WARN)  /* don't print redundant CRC error if error already */
  1065. X        return error;
  1066. X
  1067. X    if ((crc32val = ((~crc32val) & 0xFFFFFFFFL)) != lrec.crc32) {
  1068. X        /* if quiet enough, we haven't output the filename yet:  do it */
  1069. X        if ((tflag && qflag) || (!tflag && !QCOND2))
  1070. X            FPRINTF(stderr, "%-22s ", filename);
  1071. X        FPRINTF(stderr, LoadFarString(BadCRC), crc32val, lrec.crc32);
  1072. X#ifdef CRYPT
  1073. X        if (pInfo->encrypted)
  1074. X          FPRINTF(stderr, LoadFarString(MaybeBadPasswd));
  1075. X#endif
  1076. X        FFLUSH(stderr);
  1077. X        error = PK_ERR;
  1078. X    } else if (tflag) {
  1079. X        if (!qflag)
  1080. X            FPRINTF(stdout, " OK\n");
  1081. X    } else {
  1082. X        if (QCOND2 && !error)
  1083. X            FPRINTF(stdout, "\n"); /* GRR:  is stdout reset to text mode yet? */
  1084. X    }
  1085. X
  1086. X    return error;
  1087. X
  1088. X} /* end function extract_or_test_member() */
  1089. X
  1090. X
  1091. X
  1092. X
  1093. X
  1094. X/***************************/
  1095. X/*  Function memextract()  */
  1096. X/***************************/
  1097. X
  1098. Xint memextract(tgt, tgtsize, src, srcsize)   /* extract compressed extra */
  1099. X    uch *tgt, *src;                          /*  field block; return PK- */
  1100. X    ulg tgtsize, srcsize;                    /*  type error level */
  1101. X{
  1102. X    uch *old_inptr=inptr;
  1103. X    int  old_incnt=incnt, r, error=PK_OK;
  1104. X    ush  method;
  1105. X    ulg  extra_field_crc;
  1106. X
  1107. X
  1108. X    method = makeword(src);
  1109. X    extra_field_crc = makelong(src+2);
  1110. X
  1111. X    /* compressed extra field exists completely in memory at this location: */
  1112. X    inptr = src + 2 + 4;      /* method and extra_field_crc */
  1113. X    incnt = (int)(csize = (long)(srcsize - (2 + 4)));
  1114. X    mem_mode = TRUE;
  1115. X
  1116. X    switch (method) {
  1117. X        case STORED:
  1118. X            memcpy((char *)tgt, (char *)inptr, (extent)incnt);
  1119. X            outcnt = csize;   /* for CRC calculation */
  1120. X            break;
  1121. X        case DEFLATED:
  1122. X            if ((r = inflate()) != 0) {
  1123. X                FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1124. X                  LoadFarString(NotEnoughMem) :
  1125. X                  LoadFarString(InvalidComprData),
  1126. X                  LoadFarStringSmall2(Inflate));
  1127. X                error = (r == 3)? PK_MEM3 : PK_ERR;
  1128. X            }
  1129. X            if (outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
  1130. X                break;
  1131. X            if (outcnt <= tgtsize)
  1132. X                memcpy((char *)tgt, (char *)slide, (extent)outcnt);
  1133. X            else
  1134. X                error = PK_MEM4;   /* GRR:  should be passed up via SetEAs() */
  1135. X            break;
  1136. X        default:
  1137. X            FPRINTF(stderr, LoadFarString(UnsupportedExtraField));
  1138. X            error = PK_WARN;   /* GRR:  should be passed on up via SetEAs() */
  1139. X            break;
  1140. X    }
  1141. X
  1142. X    inptr = old_inptr;
  1143. X    incnt = old_incnt;
  1144. X    mem_mode = FALSE;
  1145. X
  1146. X    if (!error) {
  1147. X        register ulg crcval = 0xFFFFFFFFL;
  1148. X        register ulg n = outcnt;   /* or tgtsize?? */
  1149. X        register uch *p = tgt;
  1150. X
  1151. X        while (n--)
  1152. X            crcval = crc_32_tab[((uch)crcval ^ (*p++)) & 0xff] ^ (crcval >> 8);
  1153. X        crcval = (~crcval) & 0xFFFFFFFFL;
  1154. X
  1155. X        if (crcval != extra_field_crc) {
  1156. X            FPRINTF(stderr, LoadFarString(BadExtraFieldCRC),
  1157. X              zipfn, crcval, extra_field_crc);
  1158. X            error = PK_WARN;
  1159. X        }
  1160. X    }
  1161. X    return error;
  1162. X
  1163. X} /* end function memextract() */
  1164. END_OF_FILE
  1165.   if test 46513 -ne `wc -c <'unzip-5.12/extract.c'`; then
  1166.     echo shar: \"'unzip-5.12/extract.c'\" unpacked with wrong size!
  1167.   fi
  1168.   # end of 'unzip-5.12/extract.c'
  1169. fi
  1170. if test -f 'unzip-5.12/vms/cmdline.c' -a "${1}" != "-c" ; then 
  1171.   echo shar: Will not clobber existing file \"'unzip-5.12/vms/cmdline.c'\"
  1172. else
  1173.   echo shar: Extracting \"'unzip-5.12/vms/cmdline.c'\" \(20360 characters\)
  1174.   sed "s/^X//" >'unzip-5.12/vms/cmdline.c' <<'END_OF_FILE'
  1175. X#define module_name VMS_UNZIP_CMDLINE
  1176. X#define module_ident "02-002"
  1177. X/*
  1178. X**
  1179. X**  Facility:    UNZIP
  1180. X**
  1181. X**  Module:    VMS_UNZIP_CMDLINE
  1182. X**
  1183. X**  Author:    Hunter Goatley <goathunter@wkuvx1.wku.edu>
  1184. X**
  1185. X**  Date:    12 Jul 94 (orig. Zip version, 30 Jul 93)
  1186. X**
  1187. X**  Abstract:    Routines to handle a VMS CLI interface for UnZip.  The CLI
  1188. X**        command line is parsed and a new argc/argv are built and
  1189. X**        returned to UnZip.
  1190. X**
  1191. X**  Modified by:
  1192. X**
  1193. X**    02-002        Hunter Goatley        16-JUL-1994 10:20
  1194. X**        Fixed some typos.
  1195. X**    02-001        Cave Newt             14-JUL-1994 15:18
  1196. X**        Removed obsolete /EXTRACT option; fixed /*TEXT options;
  1197. X**        wrote VMSCLI usage() function
  1198. X**    02-000        Hunter Goatley        12-JUL-1994 00:00
  1199. X**        Original UnZip version (v5.11).
  1200. X**    01-000        Hunter Goatley        30-JUL-1993 07:54
  1201. X**        Original version (for Zip v1.9p1).
  1202. X**
  1203. X*/
  1204. X
  1205. X
  1206. X#ifdef __alpha
  1207. X#pragma module module_name module_ident
  1208. X#else
  1209. X#module module_name module_ident
  1210. X#endif
  1211. X
  1212. X#include "unzip.h"
  1213. X#include "version.h"    /* for usage() */
  1214. X
  1215. X#include <ssdef.h>
  1216. X#include <descrip.h>
  1217. X#include <climsgdef.h>
  1218. X#include <clidef.h>
  1219. X#include <lib$routines.h>
  1220. X#include <str$routines.h>
  1221. X
  1222. X#ifndef CLI$_COMMA
  1223. Xglobalvalue CLI$_COMMA;
  1224. X#endif
  1225. X
  1226. X/*
  1227. X**  "Macro" to initialize a dynamic string descriptor.
  1228. X*/
  1229. X#define init_dyndesc(dsc) {\
  1230. X    dsc.dsc$w_length = 0;\
  1231. X    dsc.dsc$b_dtype = DSC$K_DTYPE_T;\
  1232. X    dsc.dsc$b_class = DSC$K_CLASS_D;\
  1233. X    dsc.dsc$a_pointer = 0;}
  1234. X
  1235. X/*
  1236. X**  Define descriptors for all of the CLI parameters and qualifiers.
  1237. X*/
  1238. X#if 0
  1239. X$DESCRIPTOR(cli_extract,    "EXTRACT");    /* obsolete */
  1240. X#endif
  1241. X$DESCRIPTOR(cli_autotext,    "AUTOTEXT");    /* -a */
  1242. X$DESCRIPTOR(cli_text,        "TEXT");    /* -aa */
  1243. X$DESCRIPTOR(cli_case_insensitive,    "CASE_INSENSITIVE");    /* -C */
  1244. X$DESCRIPTOR(cli_screen,        "SCREEN");    /* -c */
  1245. X$DESCRIPTOR(cli_directory,    "DIRECTORY");    /* see JUNK */
  1246. X$DESCRIPTOR(cli_freshen,    "FRESHEN");    /* -f */
  1247. X$DESCRIPTOR(cli_junk,        "JUNK");    /* -j */
  1248. X$DESCRIPTOR(cli_lowercase,    "LOWERCASE");    /* -L */
  1249. X$DESCRIPTOR(cli_list,        "LIST");    /* -l */
  1250. X$DESCRIPTOR(cli_brief,        "BRIEF");    /* -l */
  1251. X$DESCRIPTOR(cli_full,        "FULL");    /* -v */
  1252. X$DESCRIPTOR(cli_overwrite,    "OVERWRITE");    /* -o, -n */
  1253. X$DESCRIPTOR(cli_quiet,        "QUIET");    /* -q */
  1254. X$DESCRIPTOR(cli_super_quiet,    "SUPER_QUIET");    /* -qq */
  1255. X$DESCRIPTOR(cli_test,        "TEST");    /* -t */
  1256. X$DESCRIPTOR(cli_type,        "TYPE");    /* -c */
  1257. X$DESCRIPTOR(cli_pipe,        "PIPE");    /* -p */
  1258. X$DESCRIPTOR(cli_uppercase,    "UPPERCASE");    /* -U */
  1259. X$DESCRIPTOR(cli_update,        "UPDATE");    /* -u */
  1260. X$DESCRIPTOR(cli_version,    "VERSION");    /* -V */
  1261. X$DESCRIPTOR(cli_verbose,    "VERBOSE");    /* -v */
  1262. X$DESCRIPTOR(cli_restore,    "RESTORE");    /* -X */
  1263. X$DESCRIPTOR(cli_comment,    "COMMENT");    /* -z */
  1264. X$DESCRIPTOR(cli_exclude,    "EXCLUDE");    /* -x */
  1265. X
  1266. X$DESCRIPTOR(cli_information,    "ZIPINFO");    /* -Z */
  1267. X$DESCRIPTOR(cli_short,        "SHORT");    /* -Zs */
  1268. X$DESCRIPTOR(cli_medium,        "MEDIUM");    /* -Zm */
  1269. X$DESCRIPTOR(cli_long,        "LONG");    /* -Zl */
  1270. X$DESCRIPTOR(cli_header,        "HEADER");    /* -Zh */
  1271. X$DESCRIPTOR(cli_totals,        "TOTALS");    /* -Zt */
  1272. X$DESCRIPTOR(cli_times,        "TIMES");    /* -ZT */
  1273. X$DESCRIPTOR(cli_one_line,    "ONE_LINE");    /* -Z2 */
  1274. X
  1275. X$DESCRIPTOR(cli_yyz,        "YYZ");
  1276. X
  1277. X$DESCRIPTOR(cli_zipfile,    "ZIPFILE");
  1278. X$DESCRIPTOR(cli_infile,        "INFILE");
  1279. X$DESCRIPTOR(unzip_command,    "unzip ");
  1280. X$DESCRIPTOR(blank,        " ");
  1281. X
  1282. X#ifdef __alpha
  1283. Xextern void *vms_unzip_cld;
  1284. X#else
  1285. Xglobalref void *vms_unzip_cld;
  1286. X#endif
  1287. X
  1288. X/* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */
  1289. X
  1290. Xextern unsigned long cli$dcl_parse ();
  1291. Xextern unsigned long cli$present ();
  1292. Xextern unsigned long cli$get_value ();
  1293. X
  1294. Xunsigned long vms_unzip_cmdline (int *, char ***);
  1295. Xunsigned long get_list (struct dsc$descriptor_s *, char **,
  1296. X            struct dsc$descriptor_d *, char);
  1297. Xunsigned long check_cli (struct dsc$descriptor_s *);
  1298. X
  1299. X
  1300. X#ifdef TEST
  1301. Xunsigned long
  1302. Xmain(int argc, char **argv)
  1303. X{
  1304. X    register status;
  1305. X    return (vms_unzip_cmdline(&argc, &argv));
  1306. X}
  1307. X#endif /* TEST */
  1308. X
  1309. X
  1310. Xunsigned long
  1311. Xvms_unzip_cmdline (int *argc_p, char ***argv_p)
  1312. X{
  1313. X/*
  1314. X**  Routine:    vms_unzip_cmdline
  1315. X**
  1316. X**  Function:
  1317. X**
  1318. X**    Parse the DCL command line and create a fake argv array to be
  1319. X**    handed off to Zip.
  1320. X**
  1321. X**    NOTE: the argv[] is built as we go, so all the parameters are
  1322. X**    checked in the appropriate order!!
  1323. X**
  1324. X**  Formal parameters:
  1325. X**
  1326. X**    argc_p        - Address of int to receive the new argc
  1327. X**    argv_p        - Address of char ** to receive the argv address
  1328. X**
  1329. X**  Calling sequence:
  1330. X**
  1331. X**    status = vms_unzip_cmdline (&argc, &argv);
  1332. X**
  1333. X**  Returns:
  1334. X**
  1335. X**    SS$_NORMAL    - Success.
  1336. X**    SS$_INSFMEM    - A malloc() or realloc() failed
  1337. X**    SS$_ABORT    - Bad time value
  1338. X**
  1339. X*/
  1340. X    register status;
  1341. X    char options[256];
  1342. X    char *the_cmd_line;
  1343. X    char *ptr;
  1344. X    int  x, len, zipinfo;
  1345. X
  1346. X    int new_argc;
  1347. X    char **new_argv;
  1348. X
  1349. X    struct dsc$descriptor_d work_str;
  1350. X    struct dsc$descriptor_d foreign_cmdline;
  1351. X    struct dsc$descriptor_d output_directory;
  1352. X
  1353. X    init_dyndesc (work_str);
  1354. X    init_dyndesc (foreign_cmdline);
  1355. X    init_dyndesc (output_directory);
  1356. X
  1357. X    /*
  1358. X    **  See if the program was invoked by the CLI (SET COMMAND) or by
  1359. X    **  a foreign command definition.  Check for /YYZ, which is a
  1360. X    **  valid default qualifier solely for this test.
  1361. X    */
  1362. X    status = check_cli (&cli_yyz);
  1363. X    if (!(status & 1)) {
  1364. X    lib$get_foreign (&foreign_cmdline);
  1365. X    /*
  1366. X    **  If nothing was returned or the first character is a "-", then
  1367. X    **  assume it's a UNIX-style command and return.
  1368. X    */
  1369. X        if ((foreign_cmdline.dsc$w_length == 0) || (*(foreign_cmdline.dsc$a_pointer) == '-'))
  1370. X            return(SS$_NORMAL);
  1371. X
  1372. X    str$concat (&work_str, &unzip_command, &foreign_cmdline);
  1373. X    status = cli$dcl_parse(&work_str, &vms_unzip_cld, lib$get_input,
  1374. X            lib$get_input, 0);
  1375. X    if (!(status & 1)) return(status);
  1376. X    }
  1377. X
  1378. X    /*
  1379. X    **  There's always going to be an new_argv[] because of the image name.
  1380. X    */
  1381. X    if ((the_cmd_line = (char *) malloc (sizeof("unzip")+1)) == NULL)
  1382. X    return(SS$_INSFMEM);
  1383. X
  1384. X    strcpy (the_cmd_line, "unzip");
  1385. X
  1386. X    /*
  1387. X    **  First, check to see if any of the regular options were specified.
  1388. X    */
  1389. X
  1390. X    options[0] = '-';
  1391. X    ptr = &options[1];        /* Point to temporary buffer */
  1392. X
  1393. X    /*
  1394. X    **  Is it Zipinfo??
  1395. X    */
  1396. X    zipinfo = 0;
  1397. X    status = cli$present (&cli_information);
  1398. X    if (status & 1) {
  1399. X
  1400. X    zipinfo = 1;
  1401. X
  1402. X    *ptr++ = 'Z';
  1403. X    *ptr++ = ' ';
  1404. X    *ptr++ = '-';
  1405. X
  1406. X    if (cli$present(&cli_one_line) & 1)
  1407. X        *ptr++ = '2';
  1408. X    if (cli$present(&cli_short) & 1)
  1409. X        *ptr++ = 's';
  1410. X    if (cli$present(&cli_medium) & 1)
  1411. X        *ptr++ = 'm';
  1412. X    if (cli$present(&cli_long) & 1)
  1413. X        *ptr++ = 'l';
  1414. X    if (cli$present(&cli_header) & 1)
  1415. X        *ptr++ = 'h';
  1416. X    if (cli$present(&cli_comment) & 1)
  1417. X        *ptr++ = 'c';
  1418. X    if (cli$present(&cli_totals) & 1)
  1419. X        *ptr++ = 't';
  1420. X    if (cli$present(&cli_times) & 1)
  1421. X        *ptr++ = 'T';
  1422. X
  1423. X    /* If no other options were specified, remove the " -". */
  1424. X    if (*(ptr - 1) == '-')
  1425. X        ptr = ptr - 2;
  1426. X
  1427. X    }
  1428. X    else {
  1429. X
  1430. X#if 0
  1431. X    /*
  1432. X    **  Extract files?
  1433. X    */
  1434. X    status = cli$present (&cli_extract);
  1435. X    if (status == CLI$_NEGATED)
  1436. X    *ptr++ = '-';
  1437. X    if (status != CLI$_ABSENT)
  1438. X    *ptr++ = 'x';
  1439. X#endif
  1440. X
  1441. X    /*
  1442. X    **  Convert all files as text (CR LF -> LF, etc.)
  1443. X    */
  1444. X    status = cli$present (&cli_text);
  1445. X    if (status == CLI$_NEGATED)
  1446. X    *ptr++ = '-';
  1447. X    if (status != CLI$_ABSENT) {
  1448. X    *ptr++ = 'a';
  1449. X    *ptr++ = 'a';
  1450. X    }
  1451. X
  1452. X    /*
  1453. X    **  Auto-convert only text files as text
  1454. X    */
  1455. X    status = cli$present (&cli_autotext);
  1456. X    if (status == CLI$_NEGATED)
  1457. X    *ptr++ = '-';
  1458. X    if (status != CLI$_ABSENT)
  1459. X    *ptr++ = 'a';
  1460. X
  1461. X    /*
  1462. X    **  Extract files to screen?
  1463. X    */
  1464. X    status = cli$present (&cli_screen);
  1465. X    if (status == CLI$_NEGATED)
  1466. X    *ptr++ = '-';
  1467. X    if (status != CLI$_ABSENT)
  1468. X    *ptr++ = 'c';
  1469. X
  1470. X    /*
  1471. X    **  Re-create directory structure?  (default)
  1472. X    */
  1473. X    status = cli$present (&cli_directory);
  1474. X    if (status == CLI$_PRESENT) {
  1475. X    status = cli$get_value (&cli_directory, &output_directory);
  1476. X    }
  1477. X
  1478. X    /*
  1479. X    **  Freshen existing files, create none
  1480. X    */
  1481. X    status = cli$present (&cli_freshen);
  1482. X    if (status == CLI$_NEGATED)
  1483. X    *ptr++ = '-';
  1484. X    if (status != CLI$_ABSENT)
  1485. X    *ptr++ = 'f';
  1486. X
  1487. X    /*
  1488. X    **  Junk stored directory names on unzip
  1489. X    */
  1490. X    status = cli$present (&cli_junk);
  1491. X    if (status == CLI$_NEGATED)
  1492. X    *ptr++ = '-';
  1493. X    if (status != CLI$_ABSENT)
  1494. X    *ptr++ = 'j';
  1495. X
  1496. X    /*
  1497. X    **  List contents (/BRIEF or /FULL (default))
  1498. X    */
  1499. X    status = cli$present (&cli_list);
  1500. X    if (status & 1) {
  1501. X    if (cli$present(&cli_full) & 1)
  1502. X       *ptr++ = 'v';
  1503. X    else
  1504. X       *ptr++ = 'l';
  1505. X    }
  1506. X
  1507. X    /*
  1508. X    **  Overwrite files?
  1509. X    */
  1510. X    status = cli$present (&cli_overwrite);
  1511. X    if (status == CLI$_NEGATED)
  1512. X    *ptr++ = 'n';
  1513. X    else if (status != CLI$_ABSENT)
  1514. X    *ptr++ = 'o';
  1515. X
  1516. X    /*
  1517. X    **  Pipe files to SYS$OUTPUT with no informationals?
  1518. X    */
  1519. X    status = cli$present (&cli_pipe);
  1520. X    if (status != CLI$_ABSENT)
  1521. X    *ptr++ = 'p';
  1522. X
  1523. X    /*
  1524. X    **  Quiet
  1525. X    */
  1526. X    status = cli$present (&cli_quiet);
  1527. X    if (status & 1)
  1528. X    *ptr++ = 'q';
  1529. X
  1530. X    status = cli$present (&cli_super_quiet);
  1531. X    if (status & 1)
  1532. X    *ptr++ = 'q';
  1533. X
  1534. X    /*
  1535. X    **  Test archive integrity
  1536. X    */
  1537. X    status = cli$present (&cli_test);
  1538. X    if (status == CLI$_NEGATED)
  1539. X    *ptr++ = '-';
  1540. X    if (status != CLI$_ABSENT)
  1541. X    *ptr++ = 't';
  1542. X
  1543. X    /*
  1544. X    **  Match filenames case-insensitively (-C)
  1545. X    */
  1546. X    status = cli$present (&cli_case_insensitive);
  1547. X    if (status == CLI$_NEGATED)
  1548. X    *ptr++ = '-';
  1549. X    if (status != CLI$_ABSENT)
  1550. X    *ptr++ = 'C';
  1551. X
  1552. X    /*
  1553. X    **  Make (some) names lowercase
  1554. X    */
  1555. X    status = cli$present (&cli_lowercase);
  1556. X    if (status == CLI$_NEGATED)
  1557. X    *ptr++ = '-';
  1558. X    if (status != CLI$_ABSENT)
  1559. X    *ptr++ = 'L';
  1560. X
  1561. X    /*
  1562. X    **  Uppercase (don't convert to lower)
  1563. X    */
  1564. X    status = cli$present (&cli_uppercase);
  1565. X    if (status == CLI$_NEGATED)
  1566. X    *ptr++ = '-';
  1567. X    if (status != CLI$_ABSENT)
  1568. X    *ptr++ = 'U';
  1569. X
  1570. X    /*
  1571. X    **  Update (extract only new and newer files)
  1572. X    */
  1573. X    status = cli$present (&cli_update);
  1574. X    if (status == CLI$_NEGATED)
  1575. X    *ptr++ = '-';
  1576. X    if (status != CLI$_ABSENT)
  1577. X    *ptr++ = 'u';
  1578. X
  1579. X    /*
  1580. X    **  Version (retain VMS/DEC-20 file versions)
  1581. X    */
  1582. X    status = cli$present (&cli_version);
  1583. X    if (status == CLI$_NEGATED)
  1584. X    *ptr++ = '-';
  1585. X    if (status != CLI$_ABSENT)
  1586. X    *ptr++ = 'V';
  1587. X
  1588. X    /*
  1589. X    **  Verbose
  1590. X    */
  1591. X    status = cli$present (&cli_verbose);
  1592. X    if (status & 1)
  1593. X    *ptr++ = 'v';
  1594. X
  1595. X    /*
  1596. X    **  Restore owner/protection info
  1597. X    */
  1598. X    status = cli$present (&cli_restore);
  1599. X    if (status == CLI$_NEGATED)
  1600. X    *ptr++ = '-';
  1601. X    if (status != CLI$_ABSENT)
  1602. X    *ptr++ = 'X';
  1603. X
  1604. X    /*
  1605. X    **  Display only the archive comment
  1606. X    */
  1607. X    status = cli$present (&cli_comment);
  1608. X    if (status == CLI$_NEGATED)
  1609. X    *ptr++ = '-';
  1610. X    if (status != CLI$_ABSENT)
  1611. X    *ptr++ = 'z';
  1612. X
  1613. X    }    /* Zipinfo check way up there.... */
  1614. X
  1615. X    /*
  1616. X    **  If the user didn't give any DCL qualifier, assume he wants the
  1617. X    **  Un*x interface.
  1618. X    if (ptr == &options[1])
  1619. X      return(SS$_NORMAL);
  1620. X    */
  1621. X
  1622. X    /*
  1623. X    **  Now copy the final options string to the_cmd_line.
  1624. X    */
  1625. X    x = ptr - &options[0];
  1626. X    if (x > 1) {
  1627. X    options[x] = '\0';
  1628. X    len = strlen(the_cmd_line) + x + 2;
  1629. X    if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  1630. X        return(SS$_INSFMEM);
  1631. X    strcat (the_cmd_line, " ");
  1632. X    strcat (the_cmd_line, options);
  1633. X    }
  1634. X
  1635. X    /*
  1636. X    **  Now get the specified zip file name.
  1637. X    */
  1638. X    status = cli$present (&cli_zipfile);
  1639. X    if (status & 1) {
  1640. X    status = cli$get_value (&cli_zipfile, &work_str);
  1641. X
  1642. X    len = strlen(the_cmd_line) + work_str.dsc$w_length + 2;
  1643. X    if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  1644. X        return(SS$_INSFMEM);
  1645. X    strcat (the_cmd_line, " ");
  1646. X    x = strlen(the_cmd_line);
  1647. X    strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,
  1648. X        work_str.dsc$w_length);
  1649. X    the_cmd_line[len] = '\0';
  1650. X
  1651. X    }
  1652. X
  1653. X    /*
  1654. X    **  Run through the list of files to unzip.
  1655. X    */
  1656. X    status = cli$present (&cli_infile);
  1657. X    if (status & 1) {
  1658. X    len = strlen(the_cmd_line) + 2;
  1659. X    if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  1660. X        return(SS$_INSFMEM);
  1661. X    strcat (the_cmd_line, " ");
  1662. X    status = get_list (&cli_infile, &the_cmd_line, &foreign_cmdline, ' ');
  1663. X    if (!(status & 1)) return (status);
  1664. X    }
  1665. X
  1666. X    /*
  1667. X    **  Get the list of files to exclude, if there are any.
  1668. X    */
  1669. X    status = cli$present (&cli_exclude);
  1670. X    if (status & 1) {
  1671. X    len = strlen(the_cmd_line) + 5;
  1672. X    if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  1673. X        return(SS$_INSFMEM);
  1674. X    strcat (the_cmd_line, " -x ");
  1675. X    status = get_list (&cli_exclude, &the_cmd_line, &foreign_cmdline, ' ');
  1676. X    if (!(status & 1)) return (status);
  1677. X    }
  1678. X
  1679. X    /*
  1680. X    **  Get the output directory, for UnZip.
  1681. X    **/
  1682. X    if (output_directory.dsc$w_length != 0) {
  1683. X    len = strlen(the_cmd_line) + output_directory.dsc$w_length + 5;
  1684. X    if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  1685. X        return(SS$_INSFMEM);
  1686. X    strcat (the_cmd_line, " -d ");
  1687. X    x = strlen(the_cmd_line);
  1688. X    strncpy(&the_cmd_line[x], output_directory.dsc$a_pointer,
  1689. X        output_directory.dsc$w_length);
  1690. X    the_cmd_line[len] = '\0';
  1691. X    }
  1692. X
  1693. X    /*
  1694. X    **  Now that we've built our new UNIX-like command line, count the
  1695. X    **  number of args and build an argv array.
  1696. X    */
  1697. X
  1698. X#if defined(TEST) || defined(DEBUG)
  1699. X    printf("%s\n",the_cmd_line);
  1700. X#endif /* TEST */
  1701. X
  1702. X    new_argc = 1;
  1703. X    for (ptr = the_cmd_line;
  1704. X     (ptr = strchr(ptr,' ')) != NULL;
  1705. X     ptr++, new_argc++);
  1706. X
  1707. X    /*
  1708. X    **  Allocate memory for the new argv[].  The last element of argv[]
  1709. X    **  is supposed to be 0, so allocate enough for new_argc+1.
  1710. X    */
  1711. X    if ((new_argv = (char **) calloc (new_argc+1, sizeof(char *))) == NULL)
  1712. X    return(SS$_INSFMEM);
  1713. X
  1714. X    /*
  1715. X    **  For each option, store the address in new_argv[] and convert the
  1716. X    **  separating blanks to nulls so each argv[] string is terminated.
  1717. X    */
  1718. X    for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {
  1719. X    new_argv[x] = ptr;
  1720. X    if ((ptr = strchr (ptr, ' ')) != NULL)
  1721. X        *ptr++ = '\0';
  1722. X    }
  1723. X    new_argv[new_argc] = 0;
  1724. X
  1725. X#if defined(TEST) || defined(DEBUG)
  1726. X    printf("new_argc    = %d\n", new_argc);
  1727. X    for (x = 0; x < new_argc; x++)
  1728. X    printf("new_argv[%d] = %s\n", x, new_argv[x]);
  1729. X#endif /* TEST */
  1730. X
  1731. X    /*
  1732. X    **  All finished.  Return the new argc and argv[] addresses to Zip.
  1733. X    */
  1734. X    *argc_p = new_argc;
  1735. X    *argv_p = new_argv;
  1736. X
  1737. X    return(SS$_NORMAL);
  1738. X}
  1739. X
  1740. X
  1741. X
  1742. Xunsigned long
  1743. Xget_list (struct dsc$descriptor_s *qual, char **str,
  1744. X      struct dsc$descriptor_d *cmdline, char c)
  1745. X{
  1746. X/*
  1747. X**  Routine:    get_list
  1748. X**
  1749. X**  Function:    This routine runs through a comma-separated CLI list
  1750. X**        and copies the strings to the command line.  The
  1751. X**        specified separation character is used to separate
  1752. X**        the strings on the command line.
  1753. X**
  1754. X**        All strings are converted to lower-case.
  1755. X**
  1756. X**  Formal parameters:
  1757. X**
  1758. X**    qual    - Address of descriptor for the qualifier name
  1759. X**    str    - Address of pointer pointing to string (command line)
  1760. X**    c    - Character to use to separate the list items
  1761. X**
  1762. X*/
  1763. X
  1764. X    register status;
  1765. X    struct dsc$descriptor_d work_str;
  1766. X
  1767. X    init_dyndesc(work_str);
  1768. X
  1769. X    status = cli$present (qual);
  1770. X    if (status & 1) {
  1771. X
  1772. X    unsigned long len, old_len, lower_it, ind, sind;
  1773. X
  1774. X    len = strlen(*str);
  1775. X    while ((status = cli$get_value (qual, &work_str)) & 1) {
  1776. X        /*
  1777. X        **  Just in case the string doesn't exist yet, though it does.
  1778. X        */
  1779. X        if (*str == NULL) {
  1780. X        len = work_str.dsc$w_length + 1;
  1781. X        if ((*str = (char *) malloc (work_str.dsc$w_length)) == NULL)
  1782. X            return(SS$_INSFMEM);
  1783. X        strncpy(*str,work_str.dsc$a_pointer,len);
  1784. X        } else {
  1785. X        char *src, *dst; int x;
  1786. X        old_len = len;
  1787. X        len += work_str.dsc$w_length + 1;
  1788. X        if ((*str = (char *) realloc (*str, len)) == NULL)
  1789. X            return(SS$_INSFMEM);
  1790. X
  1791. X        /*
  1792. X        **  Look for the filename in the original foreign command
  1793. X        **  line to see if it was originally quoted.  If so, then
  1794. X        **  don't convert it to lowercase.
  1795. X        */
  1796. X        lower_it = 0;
  1797. X        str$find_first_substring (cmdline, &ind, &sind, &work_str);
  1798. X        if (*(cmdline->dsc$a_pointer + ind - 2) == '"')
  1799. X            lower_it = 1;
  1800. X
  1801. X        /*
  1802. X        **  Copy the string to the buffer, converting to lowercase.
  1803. X        */
  1804. X        src = work_str.dsc$a_pointer;
  1805. X        dst = *str+old_len;
  1806. X        for (x = 0; x < work_str.dsc$w_length; x++) {
  1807. X            if (!lower_it && ((*src >= 'A') && (*src <= 'Z')))
  1808. X            *dst++ = *src++ + 32;
  1809. X            else
  1810. X            *dst++ = *src++;
  1811. X        }
  1812. X        }
  1813. X        if (status == CLI$_COMMA)
  1814. X        (*str)[len-1] = c;
  1815. X        else
  1816. X        (*str)[len-1] = '\0';
  1817. X    }
  1818. X    }
  1819. X
  1820. X    return (SS$_NORMAL);
  1821. X
  1822. X}
  1823. X
  1824. X
  1825. Xunsigned long
  1826. Xcheck_cli (struct dsc$descriptor_s *qual)
  1827. X{
  1828. X/*
  1829. X**  Routine:    check_cli
  1830. X**
  1831. X**  Function:    Check to see if a CLD was used to invoke the program.
  1832. X**
  1833. X**  Formal parameters:
  1834. X**
  1835. X**    qual    - Address of descriptor for qualifier name to check.
  1836. X**
  1837. X*/
  1838. X    lib$establish(lib$sig_to_ret);    /* Establish condition handler */
  1839. X    return (cli$present(qual));        /* Just see if something was given */
  1840. X}
  1841. X
  1842. X
  1843. X
  1844. X#ifndef SFX
  1845. X
  1846. X#ifdef VMSWILD
  1847. X#  define ZI_XMPL  "*, %, () (e.g., \"(a-j)*pk.%%\")"
  1848. X#else
  1849. X#  define ZI_XMPL  "*, ?, [] (e.g., \"[a-j]*pk.??\")"
  1850. X#endif
  1851. X
  1852. Xint usage( int error)   /* VMSCLI version; returns PK-type error code */
  1853. X{
  1854. X    FILE *usagefp;
  1855. X    extern char UnzipUsageLine1[];
  1856. X
  1857. X
  1858. X/*---------------------------------------------------------------------------
  1859. X    If user requested usage, send it to stdout; else send to stderr.
  1860. X  ---------------------------------------------------------------------------*/
  1861. X
  1862. X    if (error)
  1863. X        usagefp = (FILE *)stderr;
  1864. X    else
  1865. X        usagefp = (FILE *)stdout;
  1866. X
  1867. X/*---------------------------------------------------------------------------
  1868. X    Print either ZipInfo usage or UnZip usage, depending on incantation.
  1869. X  ---------------------------------------------------------------------------*/
  1870. X
  1871. X    if (zipinfo_mode) {
  1872. X
  1873. X#ifndef NO_ZIPINFO
  1874. X
  1875. X        fprintf(usagefp, "\
  1876. XZipInfo %s, by Newtware and the fine folks at Info-ZIP.\n\n\
  1877. XList name, date/time, attribute, size, compression method, etc., about files\n\
  1878. Xin list (excluding those in xlist) contained in the specified .zip archive(s).\
  1879. X\n\"file[.zip]\" may be a wildcard name containing %s.\n", ZI_VERSION, ZI_XMPL);
  1880. X
  1881. X        fprintf(usagefp, "\n\
  1882. X   usage:  zipinfo file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\n\
  1883. X   or:  unzip /ZIPINFO file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\
  1884. X\n\nmain\
  1885. X listing-format options:              /SHORT   short \"ls -l\" format (def.)\n\
  1886. X  /ONE_LINE  just filenames, one/line     /MEDIUM  medium Unix \"ls -l\" format\n\
  1887. X  /VERBOSE   verbose, multi-page format   /LONG    long Unix \"ls -l\" format\n\
  1888. X    ");
  1889. X
  1890. X        fprintf(usagefp, "\n\
  1891. Xmiscellaneous options:\n  \
  1892. X/HEADER   print header line       /TOTALS  totals for listed files or for all\n\
  1893. X  /COMMENT  print zipfile comment   /TIMES   times in sortable decimal format\n\
  1894. X  /EXCLUDE=(file-spec1,etc.)  exclude file-specs from listing\n");
  1895. X
  1896. X        fprintf(usagefp, "\nRemember that non-lowercase filespecs must be\
  1897. X quoted in VMS (e.g., \"Makefile\").\n");
  1898. X
  1899. X#endif /* !NO_ZIPINFO */
  1900. X
  1901. X    } else {   /* UnZip mode */
  1902. X
  1903. X        fprintf(usagefp, UnzipUsageLine1, UZ_VERSION);
  1904. X
  1905. X#ifdef BETA
  1906. X        fprintf(usagefp, "\
  1907. X      THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n",
  1908. X          "", "");
  1909. X#endif
  1910. X
  1911. X        fprintf(usagefp, "\
  1912. XUsage: unzip file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options /modifiers\
  1913. X\n  Default action is to extract files in list, except those in xlist, to exdir\
  1914. X;\n  file[.zip] may be a wildcard.  %s\n\n",
  1915. X#ifdef NO_ZIPINFO
  1916. X          "(ZipInfo mode is disabled in this version.)"
  1917. X#else
  1918. X          "Type \"unzip /ZIPINFO\" for ZipInfo-mode usage."
  1919. X#endif
  1920. X          );
  1921. X
  1922. X        fprintf(usagefp, "\
  1923. XMajor options include:\n\
  1924. X   /[NO]TEST, /LIST, /[NO]SCREEN, /PIPE, /[NO]FRESHEN, /[NO]UPDATE,\n\
  1925. X   /[NO]COMMENT, /DIRECTORY=directory-spec, /EXCLUDE=(file-spec1,etc.)\n\n\
  1926. XModifiers include:\n\
  1927. X   /BRIEF, /FULL, /[NO]AUTOTEXT, /[NO]TEXT, /[NO]OVERWRITE, /[NO]JUNK,\n\
  1928. X   /QUIET, /SUPER_QUIET, /[NO]CASE_INSENSITIVE, /[NO]LOWERCASE,\n\
  1929. X   /[NO]VERSION, /[NO]RESTORE\n\n");
  1930. X
  1931. X        fprintf(usagefp, "\
  1932. XExamples (see unzip.doc or \"HELP UNZIP\" for more info):\n   \
  1933. Xunzip edit1 /EXCL=joe.jou /CASE_INSENSITIVE    => extract all files except\n   \
  1934. X   joe.jou (or JOE.JOU, or any combination of case) from zipfile edit1.zip\n   \
  1935. Xunzip zip201 \"Makefile.VMS\" vms/*.[ch]         => extract VMS Makefile and\n\
  1936. X      *.c and *.h files; must quote uppercase names if /CASE_INSENS not used\n\
  1937. X   unzip foo /DIR=tmp:[.test] /JUNK /AUTO /OVER   => extract all files to temp.\
  1938. X\n      directory without paths, auto-converting text files and overwriting\n");
  1939. X
  1940. X    } /* end if (zipinfo_mode) */
  1941. X
  1942. X    if (error)
  1943. X        return PK_PARAM;
  1944. X    else
  1945. X        return PK_COOL;     /* just wanted usage screen: no error */
  1946. X
  1947. X} /* end function usage() */
  1948. X
  1949. X#endif /* !SFX */
  1950. END_OF_FILE
  1951.   if test 20360 -ne `wc -c <'unzip-5.12/vms/cmdline.c'`; then
  1952.     echo shar: \"'unzip-5.12/vms/cmdline.c'\" unpacked with wrong size!
  1953.   fi
  1954.   # end of 'unzip-5.12/vms/cmdline.c'
  1955. fi
  1956. echo shar: End of archive 6 \(of 20\).
  1957. cp /dev/null ark6isdone
  1958. MISSING=""
  1959. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  1960.     if test ! -f ark${I}isdone ; then
  1961.     MISSING="${MISSING} ${I}"
  1962.     fi
  1963. done
  1964. if test "${MISSING}" = "" ; then
  1965.     echo You have unpacked all 20 archives.
  1966.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1967. else
  1968.     echo You still must unpack the following archives:
  1969.     echo "        " ${MISSING}
  1970. fi
  1971. exit 0
  1972. exit 0 # Just in case...
  1973.