home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
unzip
/
part06
< prev
next >
Wrap
Internet Message Format
|
1994-09-19
|
71KB
From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
Newsgroups: comp.sources.misc
Subject: v44i071: unzip - Info-ZIP portable UnZip, version 5.12, Part06/20
Date: 18 Sep 1994 23:14:56 -0500
Organization: Sterling Software
Sender: kent@sparky.sterling.com
Approved: kent@sparky.sterling.com
Message-ID: <35j380$qn8@sparky.sterling.com>
X-Md4-Signature: 949d3d4c8937c422284df2c765b0012c
Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
Posting-number: Volume 44, Issue 71
Archive-name: unzip/part06
Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
Supersedes: unzip50: Volume 31, Issue 104-117
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: unzip-5.12/extract.c unzip-5.12/vms/cmdline.c
# Wrapped by kent@sparky on Sat Sep 17 23:33:39 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 6 (of 20)."'
if test -f 'unzip-5.12/extract.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unzip-5.12/extract.c'\"
else
echo shar: Extracting \"'unzip-5.12/extract.c'\" \(46513 characters\)
sed "s/^X//" >'unzip-5.12/extract.c' <<'END_OF_FILE'
X/*---------------------------------------------------------------------------
X
X extract.c
X
X This file contains the high-level routines ("driver routines") for extrac-
X ting and testing zipfile members. It calls the low-level routines in files
X explode.c, inflate.c, unreduce.c and unshrink.c.
X
X ---------------------------------------------------------------------------*/
X
X
X#include "unzip.h"
X#include "crypt.h"
X#ifdef MSWIN
X# include "wizunzip.h"
X# include "replace.h"
X#endif
X
Xint newfile; /* used also in file_io.c (flush()) */
Xulg *crc_32_tab; /* used also in file_io.c and crypt.c (full version) */
X
Xstatic void makecrc __((void));
Xstatic int store_info __((void));
Xstatic int extract_or_test_member __((void));
X
X
X/*******************************/
X/* Strings used in extract.c */
X/*******************************/
X
Xstatic char Far VersionMsg[] =
X " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";
Xstatic char Far ComprMsg[] =
X " skipping: %-22s compression method %d\n";
Xstatic char Far FilNamMsg[] =
X "%s: bad filename length (%s)\n";
Xstatic char Far ExtFieldMsg[] =
X "%s: bad extra field length (%s)\n";
Xstatic char Far OffsetMsg[] =
X "file #%d: bad zipfile offset (%s): %ld\n";
Xstatic char Far ExtractMsg[] =
X "%8sing: %-22s %s%s";
X#ifndef SFX
X static char Far LengthMsg[] =
X "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\
X supposed to require %lu bytes%s%s%s\n";
X#endif
X
Xstatic char Far BadFileCommLength[] = "\n%s: bad file comment length\n";
Xstatic char Far LocalHdrSig[] = "local header sig";
Xstatic char Far BadLocalHdr[] = "\nfile #%d: bad local header\n";
Xstatic char Far AttemptRecompensate[] = " (attempting to re-compensate)\n";
Xstatic char Far SkipVolumeLabel[] = " skipping: %-22s %svolume label\n";
Xstatic char Far ReplaceQuery[] =
X "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
Xstatic char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
Xstatic char Far NewName[] = "new name: ";
Xstatic char Far InvalidResponse[] = "error: invalid response [%c]\n";
Xstatic char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n";
Xstatic char Far ZeroFilesTested[] = "Caution: zero files tested in %s.\n";
X
X#ifndef VMS
X static char Far VMSFormat[] =
X "\n%s: stored in VMS format. Extract anyway? (y/n) ";
X#endif
X
X#ifdef CRYPT
X static char Far SkipCantGetPasswd[] =
X " skipping: %-22s unable to get password\n";
X static char Far SkipIncorrectPasswd[] =
X " skipping: %-22s incorrect password\n";
X static char Far FilesSkipBadPasswd[] =
X "%d file%s skipped because of incorrect password.\n";
X static char Far MaybeBadPasswd[] =
X " (may instead be incorrect password)\n";
X#else
X static char Far SkipEncrypted[] =
X " skipping: %-22s encrypted (not supported)\n";
X#endif
X
Xstatic char Far NoErrInCompData[] =
X "No errors detected in compressed data of %s.\n";
Xstatic char Far NoErrInTestedFiles[] =
X "No errors detected in %s for the %d file%s tested.\n";
Xstatic char Far FilesSkipped[] =
X "%d file%s skipped because of unsupported compression or encoding.\n";
X
Xstatic char Far ErrUnzipFile[] = " error: %s%s %s\n";
Xstatic char Far ErrUnzipNoFile[] = "\n error: %s%s\n";
Xstatic char Far NotEnoughMem[] = "not enough memory to ";
Xstatic char Far InvalidComprData[] = "invalid compressed data to ";
Xstatic char Far Inflate[] = "inflate";
X
X#ifndef SFX
X static char Far Explode[] = "explode";
X static char Far Unshrink[] = "unshrink";
X#endif
X
Xstatic char Far FileUnknownCompMethod[] = "%s: unknown compression method\n";
Xstatic char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n";
Xstatic char Far UnsupportedExtraField[] =
X "warning: unsupported extra field compression type--skipping\n";
Xstatic char Far BadExtraFieldCRC[] =
X "error [%s]: bad extra field CRC %08lx (should be %08lx)\n";
X
X
X
X
X
X/**************************************/
X/* Function extract_or_test_files() */
X/**************************************/
X
Xint extract_or_test_files() /* return PK-type error code */
X{
X uch *cd_inptr;
X int cd_incnt, error, error_in_archive=PK_COOL;
X int i, j, renamed, query, len, filnum=(-1), blknum=0;
X int *fn_matched=NULL, *xn_matched=NULL;
X ush members_remaining, num_skipped=0, num_bad_pwd=0;
X long cd_bufstart, bufstart, inbuf_offset, request;
X LONGINT old_extra_bytes=0L;
X static min_info info[DIR_BLKSIZ];
X
X
X/*---------------------------------------------------------------------------
X The basic idea of this function is as follows. Since the central di-
X rectory lies at the end of the zipfile and the member files lie at the
X beginning or middle or wherever, it is not very desirable to simply
X read a central directory entry, jump to the member and extract it, and
X then jump back to the central directory. In the case of a large zipfile
X this would lead to a whole lot of disk-grinding, especially if each mem-
X ber file is small. Instead, we read from the central directory the per-
X tinent information for a block of files, then go extract/test the whole
X block. Thus this routine contains two small(er) loops within a very
X large outer loop: the first of the small ones reads a block of files
X from the central directory; the second extracts or tests each file; and
X the outer one loops over blocks. There's some file-pointer positioning
X stuff in between, but that's about it. Btw, it's because of this jump-
X ing around that we can afford to be lenient if an error occurs in one of
X the member files: we should still be able to go find the other members,
X since we know the offset of each from the beginning of the zipfile.
X ---------------------------------------------------------------------------*/
X
X pInfo = info;
X members_remaining = ecrec.total_entries_central_dir;
X#if (defined(CRYPT) || !defined(NO_ZIPINFO))
X newzip = TRUE;
X#endif
X
X /* malloc space for CRC table and generate it */
X if ((crc_32_tab = (ulg *)malloc(256*sizeof(ulg))) == (ulg *)NULL)
X return PK_MEM2;
X makecrc();
X
X /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
X if (filespecs > 0 &&
X (fn_matched=(int *)malloc(filespecs*sizeof(int))) != (int *)NULL)
X for (i = 0; i < filespecs; ++i)
X fn_matched[i] = FALSE;
X if (xfilespecs > 0 &&
X (xn_matched=(int *)malloc(xfilespecs*sizeof(int))) != (int *)NULL)
X for (i = 0; i < xfilespecs; ++i)
X xn_matched[i] = FALSE;
X
X/*---------------------------------------------------------------------------
X Begin main loop over blocks of member files. We know the entire central
X directory is on this disk: we would not have any of this information un-
X less the end-of-central-directory record was on this disk, and we would
X not have gotten to this routine unless this is also the disk on which
X the central directory starts. In practice, this had better be the ONLY
X disk in the archive, but maybe someday we'll add multi-disk support.
X ---------------------------------------------------------------------------*/
X
X while (members_remaining) {
X j = 0;
X
X /*
X * Loop through files in central directory, storing offsets, file
X * attributes, case-conversion and text-conversion flags until block
X * size is reached.
X */
X
X while (members_remaining && (j < DIR_BLKSIZ)) {
X --members_remaining;
X pInfo = &info[j];
X
X if (readbuf(sig, 4) == 0) {
X error_in_archive = PK_EOF;
X members_remaining = 0; /* ...so no more left to do */
X break;
X }
X if (strncmp(sig, central_hdr_sig, 4)) { /* just to make sure */
X FPRINTF(stderr, LoadFarString(CentSigMsg), j); /* sig not found */
X FPRINTF(stderr, LoadFarString(ReportMsg)); /* check binary transfers */
X error_in_archive = PK_BADERR;
X members_remaining = 0; /* ...so no more left to do */
X break;
X }
X /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
X if ((error = process_cdir_file_hdr()) != PK_COOL) {
X error_in_archive = error; /* only PK_EOF defined */
X members_remaining = 0; /* ...so no more left to do */
X break;
X }
X if ((error = do_string(crec.filename_length,FILENAME)) != PK_COOL) {
X if (error > error_in_archive)
X error_in_archive = error;
X if (error > PK_WARN) { /* fatal: no more left to do */
X FPRINTF(stderr, LoadFarString(FilNamMsg), filename, "central");
X members_remaining = 0;
X break;
X }
X }
X if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0)
X {
X if (error > error_in_archive)
X error_in_archive = error;
X if (error > PK_WARN) { /* fatal */
X FPRINTF(stderr, LoadFarString(ExtFieldMsg), filename, "central");
X members_remaining = 0;
X break;
X }
X }
X if ((error = do_string(crec.file_comment_length,SKIP)) != PK_COOL) {
X if (error > error_in_archive)
X error_in_archive = error;
X if (error > PK_WARN) { /* fatal */
X FPRINTF(stderr, LoadFarString(BadFileCommLength),
X filename);
X members_remaining = 0;
X break;
X }
X }
X if (process_all_files) {
X if (store_info())
X ++j; /* file is OK; info[] stored; continue with next */
X else
X ++num_skipped;
X } else {
X int do_this_file = FALSE;
X char **pfn = pfnames-1;
X
X while (*++pfn)
X if (match(filename, *pfn, C_flag)) {
X do_this_file = TRUE; /* ^-- ignore case or not? */
X if (fn_matched)
X fn_matched[pfn-pfnames] = TRUE;
X break; /* found match, so stop looping */
X }
X if (do_this_file) { /* check if this is an excluded file */
X char **pxn = pxnames-1;
X
X while (*++pxn)
X if (match(filename, *pxn, C_flag)) {
X do_this_file = FALSE; /* ^-- ignore case or not? */
X if (xn_matched)
X xn_matched[pxn-pxnames] = TRUE;
X break;
X }
X }
X if (do_this_file)
X if (store_info())
X ++j; /* file is OK */
X else
X ++num_skipped; /* unsupp. compression or encryption */
X } /* end if (process_all_files) */
X
X
X } /* end while-loop (adding files to current block) */
X
X /* save position in central directory so can come back later */
X cd_bufstart = cur_zipfile_bufstart;
X cd_inptr = inptr;
X cd_incnt = incnt;
X
X /*-----------------------------------------------------------------------
X Second loop: process files in current block, extracting or testing
X each one.
X -----------------------------------------------------------------------*/
X
X for (i = 0; i < j; ++i) {
X filnum = i + blknum*DIR_BLKSIZ;
X pInfo = &info[i];
X
X /* if the target position is not within the current input buffer
X * (either haven't yet read far enough, or (maybe) skipping back-
X * ward), skip to the target position and reset readbuf(). */
X
X /* LSEEK(pInfo->offset): */
X request = pInfo->offset + extra_bytes;
X inbuf_offset = request % INBUFSIZ;
X bufstart = request - inbuf_offset;
X
X Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
X request, inbuf_offset));
X Trace((stderr,
X "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
X bufstart, cur_zipfile_bufstart));
X if (request < 0) {
X FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn,
X LoadFarString(ReportMsg));
X error_in_archive = PK_ERR;
X if (filnum == 0 && extra_bytes != 0L) {
X FPRINTF(stderr, LoadFarString(AttemptRecompensate));
X old_extra_bytes = extra_bytes;
X extra_bytes = 0L;
X request = pInfo->offset; /* could also check if this != 0 */
X inbuf_offset = request % INBUFSIZ;
X bufstart = request - inbuf_offset;
X Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
X request, inbuf_offset));
X Trace((stderr,
X "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
X bufstart, cur_zipfile_bufstart));
X } else {
X error_in_archive = PK_BADERR;
X continue; /* this one hosed; try next */
X }
X }
X /* try again */
X if (request < 0) {
X Trace((stderr, "debug: recompensated request still < 0\n"));
X FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn,
X LoadFarString(ReportMsg));
X error_in_archive = PK_BADERR;
X continue;
X } else if (bufstart != cur_zipfile_bufstart) {
X Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
X cur_zipfile_bufstart = lseek(zipfd,(LONGINT)bufstart,SEEK_SET);
X if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) {
X FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "lseek",
X bufstart);
X error_in_archive = PK_BADERR;
X continue; /* can still do next file */
X }
X inptr = inbuf + (int)inbuf_offset;
X incnt -= (int)inbuf_offset;
X } else {
X incnt += (inptr-inbuf) - (int)inbuf_offset;
X inptr = inbuf + (int)inbuf_offset;
X }
X
X /* should be in proper position now, so check for sig */
X if (readbuf(sig, 4) == 0) { /* bad offset */
X FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF",
X request);
X error_in_archive = PK_BADERR;
X continue; /* but can still try next one */
X }
X if (strncmp(sig, local_hdr_sig, 4)) {
X FPRINTF(stderr, LoadFarString(OffsetMsg), filnum,
X LoadFarStringSmall(LocalHdrSig), request);
X error_in_archive = PK_ERR;
X if ((filnum == 0 && extra_bytes != 0L) ||
X (extra_bytes == 0L && old_extra_bytes != 0L)) {
X FPRINTF(stderr, LoadFarString(AttemptRecompensate));
X if (extra_bytes) {
X old_extra_bytes = extra_bytes;
X extra_bytes = 0L;
X } else
X extra_bytes = old_extra_bytes; /* third attempt */
X LSEEK(pInfo->offset)
X if (readbuf(sig, 4) == 0) { /* bad offset */
X FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF",
X request);
X error_in_archive = PK_BADERR;
X continue; /* but can still try next one */
X }
X if (strncmp(sig, local_hdr_sig, 4)) {
X FPRINTF(stderr, LoadFarString(OffsetMsg), filnum,
X LoadFarStringSmall(LocalHdrSig), request);
X error_in_archive = PK_BADERR;
X continue;
X }
X } else
X continue; /* this one hosed; try next */
X }
X if ((error = process_local_file_hdr()) != PK_COOL) {
X FPRINTF(stderr, LoadFarString(BadLocalHdr), filnum);
X error_in_archive = error; /* only PK_EOF defined */
X continue; /* can still try next one */
X }
X if ((error = do_string(lrec.filename_length,FILENAME)) != PK_COOL) {
X if (error > error_in_archive)
X error_in_archive = error;
X if (error > PK_WARN) {
X FPRINTF(stderr, LoadFarString(FilNamMsg), filename, "local");
X continue; /* go on to next one */
X }
X }
X if (extra_field != (uch *)NULL) {
X free(extra_field);
X extra_field = (uch *)NULL;
X }
X if ((error = do_string(lrec.extra_field_length,EXTRA_FIELD)) != 0) {
X if (error > error_in_archive)
X error_in_archive = error;
X if (error > PK_WARN) {
X FPRINTF(stderr, LoadFarString(ExtFieldMsg), filename, "local");
X continue; /* go on */
X }
X }
X
X /*
X * just about to extract file: if extracting to disk, check if
X * already exists, and if so, take appropriate action according to
X * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
X * loop because we don't store the possibly renamed filename[] in
X * info[])
X */
X if (!tflag && !cflag) {
X renamed = FALSE; /* user hasn't renamed output file yet */
X
Xstartover:
X query = FALSE;
X#ifdef MACOS
X macflag = (pInfo->hostnum == MAC_);
X#endif
X /* mapname can create dirs if not freshening or if renamed */
X if ((error = mapname(renamed)) > PK_WARN) {
X if (error == IZ_CREATED_DIR) {
X
X /* GRR: add code to set times/attribs on dirs--
X * save to list, sort when done (a la zip), set
X * times/attributes on deepest dirs first */
X
X } else if (error == IZ_VOL_LABEL) {
X FPRINTF(stderr,
X LoadFarString(SkipVolumeLabel), filename,
X#ifdef DOS_NT_OS2
X volflag? "hard disk " :
X#endif
X "");
X /* if (!error_in_archive)
X error_in_archive = PK_WARN; */
X } else if (error > PK_ERR && error_in_archive < PK_ERR)
X error_in_archive = PK_ERR;
X Trace((stderr, "mapname(%s) returns error = %d\n", filename,
X error));
X continue; /* go on to next file */
X }
X
X switch (check_for_newer(filename)) {
X case DOES_NOT_EXIST:
X if (fflag && !renamed) /* don't skip if just renamed */
X continue; /* freshen (no new files): skip */
X break;
X case EXISTS_AND_OLDER:
X if (overwrite_none)
X continue; /* never overwrite: skip file */
X if (!overwrite_all && !force_flag)
X query = TRUE;
X break;
X case EXISTS_AND_NEWER: /* (or equal) */
X if (overwrite_none || (uflag && !renamed))
X continue; /* skip if update/freshen & orig name */
X if (!overwrite_all && !force_flag)
X query = TRUE;
X break;
X }
X if (query) {
X#ifdef MSWIN
X FARPROC lpfnprocReplace;
X int ReplaceDlgRetVal; /* replace dialog return value */
X
X ShowCursor(FALSE); /* turn off cursor */
X SetCursor(hSaveCursor); /* restore the cursor */
X lpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);
X ReplaceDlgRetVal = DialogBoxParam(hInst, "Replace",
X hWndMain, lpfnprocReplace, (DWORD)(LPSTR)filename);
X FreeProcInstance(lpfnprocReplace);
X hSaveCursor = SetCursor(hHourGlass);
X ShowCursor(TRUE);
X switch (ReplaceDlgRetVal) {
X case IDM_REPLACE_RENAME:
X renamed = TRUE;
X goto startover;
X case IDM_REPLACE_YES:
X break;
X case IDM_REPLACE_ALL:
X overwrite_all = TRUE;
X overwrite_none = FALSE; /* just to make sure */
X break;
X case IDM_REPLACE_NONE:
X overwrite_none = TRUE;
X overwrite_all = FALSE; /* make sure */
X force_flag = FALSE; /* ditto */
X /* FALL THROUGH, skip */
X case IDM_REPLACE_NO:
X continue;
X }
X#else /* !MSWIN */
Xreprompt:
X FPRINTF(stderr, LoadFarString(ReplaceQuery), filename);
X FFLUSH(stderr);
X if (fgets(answerbuf, 9, stdin) == (char *)NULL) {
X FPRINTF(stderr, LoadFarString(AssumeNone));
X FFLUSH(stderr);
X *answerbuf = 'N';
X if (!error_in_archive)
X error_in_archive = 1; /* not extracted: warning */
X }
X switch (*answerbuf) {
X case 'A': /* dangerous option: force caps */
X overwrite_all = TRUE;
X overwrite_none = FALSE; /* just to make sure */
X break;
X case 'r':
X case 'R':
X do {
X FPRINTF(stderr, LoadFarString(NewName));
X FFLUSH(stderr);
X fgets(filename, FILNAMSIZ, stdin);
X /* usually get \n here: better check for it */
X len = strlen(filename);
X if (filename[len-1] == '\n')
X filename[--len] = 0;
X } while (len == 0);
X renamed = TRUE;
X goto startover; /* sorry for a goto */
X case 'y':
X case 'Y':
X break;
X case 'N':
X overwrite_none = TRUE;
X overwrite_all = FALSE; /* make sure */
X force_flag = FALSE; /* ditto */
X /* FALL THROUGH, skip */
X case 'n':
X continue; /* skip file */
X default:
X FPRINTF(stderr, LoadFarString(InvalidResponse),
X *answerbuf); /* warn the user */
X goto reprompt; /* why not another goto? */
X } /* end switch (*answerbuf) */
X#endif /* ?MSWIN */
X } /* end if (query) */
X } /* end if (extracting to disk) */
X
X#ifdef CRYPT
X if (pInfo->encrypted && (error = decrypt()) != PK_COOL) {
X if (error == PK_MEM2) {
X if (error > error_in_archive)
X error_in_archive = error;
X FPRINTF(stderr,
X LoadFarString(SkipCantGetPasswd), filename);
X } else { /* (error == PK_WARN) */
X if (!((tflag && qflag) || (!tflag && !QCOND2)))
X FPRINTF(stderr,
X LoadFarString(SkipIncorrectPasswd), filename);
X ++num_bad_pwd;
X }
X continue; /* go on to next file */
X }
X#endif /* CRYPT */
X disk_full = 0;
X if ((error = extract_or_test_member()) != PK_COOL) {
X if (error > error_in_archive)
X error_in_archive = error; /* ...and keep going */
X if (disk_full > 1) {
X free(crc_32_tab);
X if (fn_matched)
X free(fn_matched);
X if (xn_matched)
X free(xn_matched);
X return error_in_archive; /* (unless disk full) */
X }
X }
X } /* end for-loop (i: files in current block) */
X
X
X /*
X * Jump back to where we were in the central directory, then go and do
X * the next batch of files.
X */
X
X cur_zipfile_bufstart = lseek(zipfd, (LONGINT)cd_bufstart, SEEK_SET);
X read(zipfd, (char *)inbuf, INBUFSIZ); /* were there b4 ==> no error */
X inptr = cd_inptr;
X incnt = cd_incnt;
X ++blknum;
X
X#ifdef TEST
X printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
X printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
X cur_zipfile_bufstart);
X printf("inptr-inbuf = %d\n", inptr-inbuf);
X printf("incnt = %d\n\n", incnt);
X#endif
X
X } /* end while-loop (blocks of files in central directory) */
X
X/*---------------------------------------------------------------------------
X Check for unmatched filespecs on command line and print warning if any
X found. Free allocated memory.
X ---------------------------------------------------------------------------*/
X
X if (fn_matched) {
X for (i = 0; i < filespecs; ++i)
X if (!fn_matched[i])
X FPRINTF(stderr, LoadFarString(FilenameNotMatched),
X pfnames[i]);
X free(fn_matched);
X }
X if (xn_matched) {
X for (i = 0; i < xfilespecs; ++i)
X if (!xn_matched[i])
X FPRINTF(stderr, LoadFarString(ExclFilenameNotMatched),
X pxnames[i]);
X free(xn_matched);
X }
X free(crc_32_tab);
X
X/*---------------------------------------------------------------------------
X Double-check that we're back at the end-of-central-directory record, and
X print quick summary of results, if we were just testing the archive. We
X send the summary to stdout so that people doing the testing in the back-
X ground and redirecting to a file can just do a "tail" on the output file.
X ---------------------------------------------------------------------------*/
X
X if (readbuf(sig, 4) == 0)
X error_in_archive = PK_EOF;
X if (strncmp(sig, end_central_sig, 4)) { /* just to make sure */
X FPRINTF(stderr, LoadFarString(EndSigMsg)); /* didn't find sig */
X FPRINTF(stderr, LoadFarString(ReportMsg)); /* check binary transfers */
X if (!error_in_archive) /* don't overwrite stronger error */
X error_in_archive = PK_WARN;
X }
X ++filnum; /* initialized to -1, so now zero if no files found */
X if (tflag) {
X int num=filnum - num_bad_pwd;
X
X if (qflag < 2) { /* GRR 930710: was (qflag == 1) */
X if (error_in_archive)
X PRINTF(LoadFarString(ErrorInArchive),
X (error_in_archive == 1)? "warning-" : "", zipfn);
X else if (num == 0)
X PRINTF(LoadFarString(ZeroFilesTested), zipfn);
X else if (process_all_files && (num_skipped+num_bad_pwd == 0))
X PRINTF(LoadFarString(NoErrInCompData), zipfn);
X else
X PRINTF(LoadFarString(NoErrInTestedFiles),
X zipfn, num, (num==1)? "":"s");
X if (num_skipped > 0)
X PRINTF(LoadFarString(FilesSkipped), num_skipped,
X (num_skipped==1)? "":"s");
X#ifdef CRYPT
X if (num_bad_pwd > 0)
X PRINTF(LoadFarString(FilesSkipBadPasswd),
X num_bad_pwd, (num_bad_pwd==1)? "":"s");
X#endif /* CRYPT */
X } else if ((qflag == 0) && !error_in_archive && (num == 0))
X PRINTF(LoadFarString(ZeroFilesTested), zipfn);
X }
X
X /* give warning if files not tested or extracted */
X if ((filnum == 0) && error_in_archive <= PK_WARN)
X error_in_archive = PK_FIND; /* no files found at all */
X else if ((num_skipped > 0) && !error_in_archive)
X error_in_archive = PK_WARN;
X#ifdef CRYPT
X else if ((num_bad_pwd > 0) && !error_in_archive)
X error_in_archive = PK_WARN;
X#endif /* CRYPT */
X
X return error_in_archive;
X
X} /* end function extract_or_test_files() */
X
X
X
X
X
X/**********************/
X/* Function makecrc() */
X/**********************/
X
Xstatic void makecrc()
X/*
X Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
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.
X
X Polynomials over GF(2) are represented in binary, one bit per coefficient,
X with the lowest powers in the most significant bit. Then adding polynomials
X is just exclusive-or, and multiplying a polynomial by x is a right shift by
X one. If we call the above polynomial p, and represent a byte as the
X polynomial q, also with the lowest power in the most significant bit (so the
X byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
X where a mod b means the remainder after dividing a by b.
X
X This calculation is done using the shift-register method of multiplying and
X taking the remainder. The register is initialized to zero, and for each
X incoming bit, x^32 is added mod p to the register if the bit is a one (where
X x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
X x (which is shifting right by one and adding x^32 mod p if the bit shifted
X out is a one). We start with the highest power (least significant bit) of
X q and repeat for all eight bits of q.
X
X The table is simply the CRC of all possible eight bit values. This is all
X the information needed to generate CRC's on data a byte at a time for all
X combinations of CRC register values and incoming bytes. The table is
X written to stdout as 256 long hexadecimal values in C language format.
X*/
X{
X ulg crc; /* crc shift register */
X ulg xor; /* polynomial exclusive-or pattern */
X int i; /* counter for all possible eight bit values */
X int k; /* byte being shifted into crc apparatus */
X /* terms of polynomial defining this crc (except x^32): */
X static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
X
X /* make exclusive-or pattern from polynomial (0xedb88320) */
X xor = 0L;
X for (i = 0; i < sizeof(p)/sizeof(uch); i++)
X xor |= 1L << (31 - p[i]);
X
X crc_32_tab[0] = 0L;
X Trace((stderr, "makecrc(): crc_32_tab[] = {\n 0x%08lxL", crc_32_tab[0]));
X /* the idea to initialize the register with the byte instead of
X * zero was stolen from Haruhiko Okumura's ar002 */
X for (i = 1; i < 256; i++) {
X crc = i;
X for (k = 8; k; k--)
X crc = crc & 1 ? (crc >> 1) ^ xor : crc >> 1;
X crc_32_tab[i] = crc;
X Trace((stderr, i % 5 ? ", 0x%08lxL" : ",\n 0x%08lxL", crc_32_tab[i]));
X }
X Trace((stderr, "\n};\n"));
X
X} /* end function makecrc() */
X
X
X
X
X
X/***************************/
X/* Function store_info() */
X/***************************/
X
Xstatic int store_info() /* return 0 if skipping, 1 if OK */
X{
X#ifdef SFX
X# define UNKN_COMPR \
X (crec.compression_method!=STORED && crec.compression_method!=DEFLATED)
X#else
X# define UNKN_COMPR \
X (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
X#endif
X
X/*---------------------------------------------------------------------------
X Check central directory info for version/compatibility requirements.
X ---------------------------------------------------------------------------*/
X
X pInfo->encrypted = crec.general_purpose_bit_flag & 1; /* bit field */
X pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;/* bit field */
X pInfo->textfile = crec.internal_file_attributes & 1; /* bit field */
X pInfo->crc = crec.crc32;
X pInfo->compr_size = crec.csize;
X
X switch (aflag) {
X case 0:
X pInfo->textmode = FALSE; /* bit field */
X break;
X case 1:
X pInfo->textmode = pInfo->textfile; /* auto-convert mode */
X break;
X default: /* case 2: */
X pInfo->textmode = TRUE;
X break;
X }
X
X if (crec.version_needed_to_extract[1] == VMS_) {
X if (crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
X if (!((tflag && qflag) || (!tflag && !QCOND2)))
X FPRINTF(stderr, LoadFarString(VersionMsg), filename, "VMS",
X crec.version_needed_to_extract[0] / 10,
X crec.version_needed_to_extract[0] % 10,
X VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10);
X return 0;
X }
X#ifndef VMS /* won't be able to use extra field, but still have data */
X else if (!tflag && !force_flag) { /* if forcing, extract regardless */
X FPRINTF(stderr, LoadFarString(VMSFormat), filename);
X FFLUSH(stderr);
X fgets(answerbuf, 9, stdin);
X if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
X return 0;
X }
X#endif /* !VMS */
X /* usual file type: don't need VMS to extract */
X } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
X if (!((tflag && qflag) || (!tflag && !QCOND2)))
X FPRINTF(stderr, LoadFarString(VersionMsg), filename, "PK",
X crec.version_needed_to_extract[0] / 10,
X crec.version_needed_to_extract[0] % 10,
X UNZIP_VERSION / 10, UNZIP_VERSION % 10);
X return 0;
X }
X
X if UNKN_COMPR {
X if (!((tflag && qflag) || (!tflag && !QCOND2)))
X FPRINTF(stderr, LoadFarString(ComprMsg), filename,
X crec.compression_method);
X return 0;
X }
X#ifndef CRYPT
X if (pInfo->encrypted) {
X if (!((tflag && qflag) || (!tflag && !QCOND2)))
X FPRINTF(stderr, LoadFarString(SkipEncrypted), filename);
X return 0;
X }
X#endif /* !CRYPT */
X
X /* map whatever file attributes we have into the local format */
X mapattr(); /* GRR: worry about return value later */
X
X pInfo->offset = (long) crec.relative_offset_local_header;
X return 1;
X
X} /* end function store_info() */
X
X
X
X
X
X/***************************************/
X/* Function extract_or_test_member() */
X/***************************************/
X
Xstatic int extract_or_test_member() /* return PK-type error code */
X{
X char *nul="[empty] ", *txt="[text] ", *bin="[binary]";
X register int b;
X int r, error=PK_COOL;
X
X
X
X/*---------------------------------------------------------------------------
X Initialize variables, buffers, etc.
X ---------------------------------------------------------------------------*/
X
X bits_left = 0; /* unreduce and unshrink only */
X bitbuf = 0L; /* unreduce and unshrink only */
X zipeof = 0; /* unreduce and unshrink only */
X newfile = TRUE;
X crc32val = 0xFFFFFFFFL;
X
X#ifdef SYMLINKS
X /* if file came from Unix and is a symbolic link and we are extracting
X * to disk, prepare to restore the link */
X if (S_ISLNK(pInfo->file_attr) && (pInfo->hostnum == UNIX_) && !tflag &&
X !cflag && (lrec.ucsize > 0))
X symlnk = TRUE;
X else
X symlnk = FALSE;
X#endif /* SYMLINKS */
X
X if (tflag) {
X if (!qflag) {
X FPRINTF(stdout, LoadFarString(ExtractMsg), "test", filename, "", "");
X fflush(stdout);
X }
X } else {
X if (cflag) {
X outfile = stdout;
X#ifdef DOS_NT_OS2
X setmode(fileno(outfile), O_BINARY);
X# define NEWLINE "\r\n"
X#else
X# define NEWLINE "\n"
X#endif
X#ifdef VMS
X if (open_outfile()) /* VMS: required even for stdout! */
X return PK_DISK;
X#endif
X } else if (open_outfile())
X return PK_DISK;
X }
X
X/*---------------------------------------------------------------------------
X Unpack the file.
X ---------------------------------------------------------------------------*/
X
X switch (lrec.compression_method) {
X case STORED:
X if (!tflag && QCOND2) {
X#ifdef SYMLINKS
X if (symlnk) /* can also be deflated, but rarer... */
X FPRINTF(stdout, LoadFarString(ExtractMsg), "link", filename,
X "", "");
X else
X#endif /* SYMLINKS */
X FPRINTF(stdout, LoadFarString(ExtractMsg), "extract", filename,
X (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
X : (lrec.ucsize == 0L? nul : (pInfo->textfile? txt : bin)),
X cflag? NEWLINE : "");
X fflush(stdout);
X }
X outptr = slide;
X outcnt = 0L;
X while ((b = NEXTBYTE) != EOF && !disk_full) {
X *outptr++ = (uch)b;
X if (++outcnt == WSIZE) {
X flush(slide, outcnt, 0);
X outptr = slide;
X outcnt = 0L;
X }
X }
X if (outcnt) /* flush final (partial) buffer */
X flush(slide, outcnt, 0);
X break;
X
X#ifndef SFX
X case SHRUNK:
X if (!tflag && QCOND2) {
X FPRINTF(stdout, LoadFarString(ExtractMsg),
X LoadFarStringSmall(Unshrink), filename,
X (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
X : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
X fflush(stdout);
X }
X if ((r = unshrink()) != PK_COOL) {
X if ((tflag && qflag) || (!tflag && !QCOND2))
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile),
X LoadFarString(NotEnoughMem),
X LoadFarStringSmall2(Unshrink),
X filename);
X else
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile),
X LoadFarString(NotEnoughMem),
X LoadFarStringSmall2(Unshrink));
X error = r;
X }
X break;
X
X case REDUCED1:
X case REDUCED2:
X case REDUCED3:
X case REDUCED4:
X if (!tflag && QCOND2) {
X FPRINTF(stdout, LoadFarString(ExtractMsg), "unreduc", filename,
X (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
X : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
X fflush(stdout);
X }
X unreduce();
X break;
X
X case IMPLODED:
X if (!tflag && QCOND2) {
X FPRINTF(stdout, LoadFarString(ExtractMsg), "explod", filename,
X (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
X : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
X fflush(stdout);
X }
X if (((r = explode()) != 0) && (r != 5)) { /* treat 5 specially */
X if ((tflag && qflag) || (!tflag && !QCOND2))
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile), r == 3?
X LoadFarString(NotEnoughMem) :
X LoadFarString(InvalidComprData),
X LoadFarStringSmall2(Explode), filename);
X else
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
X LoadFarString(NotEnoughMem) :
X LoadFarString(InvalidComprData),
X LoadFarStringSmall2(Explode));
X error = (r == 3)? PK_MEM3 : PK_ERR;
X }
X if (r == 5) {
X int warning = ((ulg)used_csize <= lrec.csize);
X
X if ((tflag && qflag) || (!tflag && !QCOND2))
X FPRINTF(stderr, LoadFarString(LengthMsg), "", warning?
X "warning":"error", used_csize, lrec.ucsize, warning?
X " ":"", lrec.csize, " [", filename, "]");
X else
X FPRINTF(stderr, LoadFarString(LengthMsg), "\n", warning?
X "warning":"error", used_csize, lrec.ucsize, warning?
X " ":"", lrec.csize, "", "", ".");
X error = warning? PK_WARN : PK_ERR;
X }
X break;
X#endif /* !SFX */
X
X case DEFLATED:
X if (!tflag && QCOND2) {
X FPRINTF(stdout, LoadFarString(ExtractMsg), "inflat", filename,
X (aflag != 1 /* && pInfo->textfile == pInfo->textmode */ )? ""
X : (pInfo->textfile? txt : bin), cflag? NEWLINE : "");
X fflush(stdout);
X }
X if ((r = inflate()) != 0) {
X if ((tflag && qflag) || (!tflag && !QCOND2))
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipFile), r == 3?
X LoadFarString(NotEnoughMem) :
X LoadFarString(InvalidComprData),
X LoadFarStringSmall2(Inflate), filename);
X else
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
X LoadFarString(NotEnoughMem) :
X LoadFarString(InvalidComprData),
X LoadFarStringSmall2(Inflate));
X error = (r == 3)? PK_MEM3 : PK_ERR;
X }
X break;
X
X default: /* should never get to this point */
X FPRINTF(stderr, LoadFarString(FileUnknownCompMethod), filename);
X /* close and delete file before return? */
X return PK_WARN;
X
X } /* end switch (compression method) */
X
X if (disk_full) { /* set by flush() */
X if (disk_full > 1)
X return PK_DISK;
X error = PK_WARN;
X }
X
X/*---------------------------------------------------------------------------
X Close the file and set its date and time (not necessarily in that order),
X and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit
X machines (redundant on 32-bit machines).
X ---------------------------------------------------------------------------*/
X
X#ifdef VMS /* VMS: required even for stdout! (final flush) */
X if (!tflag) /* don't close NULL file */
X#else
X if (!tflag && !cflag) /* don't close NULL file or stdout */
X#endif
X close_outfile();
X
X if (error > PK_WARN) /* don't print redundant CRC error if error already */
X return error;
X
X if ((crc32val = ((~crc32val) & 0xFFFFFFFFL)) != lrec.crc32) {
X /* if quiet enough, we haven't output the filename yet: do it */
X if ((tflag && qflag) || (!tflag && !QCOND2))
X FPRINTF(stderr, "%-22s ", filename);
X FPRINTF(stderr, LoadFarString(BadCRC), crc32val, lrec.crc32);
X#ifdef CRYPT
X if (pInfo->encrypted)
X FPRINTF(stderr, LoadFarString(MaybeBadPasswd));
X#endif
X FFLUSH(stderr);
X error = PK_ERR;
X } else if (tflag) {
X if (!qflag)
X FPRINTF(stdout, " OK\n");
X } else {
X if (QCOND2 && !error)
X FPRINTF(stdout, "\n"); /* GRR: is stdout reset to text mode yet? */
X }
X
X return error;
X
X} /* end function extract_or_test_member() */
X
X
X
X
X
X/***************************/
X/* Function memextract() */
X/***************************/
X
Xint memextract(tgt, tgtsize, src, srcsize) /* extract compressed extra */
X uch *tgt, *src; /* field block; return PK- */
X ulg tgtsize, srcsize; /* type error level */
X{
X uch *old_inptr=inptr;
X int old_incnt=incnt, r, error=PK_OK;
X ush method;
X ulg extra_field_crc;
X
X
X method = makeword(src);
X extra_field_crc = makelong(src+2);
X
X /* compressed extra field exists completely in memory at this location: */
X inptr = src + 2 + 4; /* method and extra_field_crc */
X incnt = (int)(csize = (long)(srcsize - (2 + 4)));
X mem_mode = TRUE;
X
X switch (method) {
X case STORED:
X memcpy((char *)tgt, (char *)inptr, (extent)incnt);
X outcnt = csize; /* for CRC calculation */
X break;
X case DEFLATED:
X if ((r = inflate()) != 0) {
X FPRINTF(stderr, LoadFarStringSmall(ErrUnzipNoFile), r == 3?
X LoadFarString(NotEnoughMem) :
X LoadFarString(InvalidComprData),
X LoadFarStringSmall2(Inflate));
X error = (r == 3)? PK_MEM3 : PK_ERR;
X }
X if (outcnt == 0L) /* inflate's final FLUSH sets outcnt */
X break;
X if (outcnt <= tgtsize)
X memcpy((char *)tgt, (char *)slide, (extent)outcnt);
X else
X error = PK_MEM4; /* GRR: should be passed up via SetEAs() */
X break;
X default:
X FPRINTF(stderr, LoadFarString(UnsupportedExtraField));
X error = PK_WARN; /* GRR: should be passed on up via SetEAs() */
X break;
X }
X
X inptr = old_inptr;
X incnt = old_incnt;
X mem_mode = FALSE;
X
X if (!error) {
X register ulg crcval = 0xFFFFFFFFL;
X register ulg n = outcnt; /* or tgtsize?? */
X register uch *p = tgt;
X
X while (n--)
X crcval = crc_32_tab[((uch)crcval ^ (*p++)) & 0xff] ^ (crcval >> 8);
X crcval = (~crcval) & 0xFFFFFFFFL;
X
X if (crcval != extra_field_crc) {
X FPRINTF(stderr, LoadFarString(BadExtraFieldCRC),
X zipfn, crcval, extra_field_crc);
X error = PK_WARN;
X }
X }
X return error;
X
X} /* end function memextract() */
END_OF_FILE
if test 46513 -ne `wc -c <'unzip-5.12/extract.c'`; then
echo shar: \"'unzip-5.12/extract.c'\" unpacked with wrong size!
fi
# end of 'unzip-5.12/extract.c'
fi
if test -f 'unzip-5.12/vms/cmdline.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unzip-5.12/vms/cmdline.c'\"
else
echo shar: Extracting \"'unzip-5.12/vms/cmdline.c'\" \(20360 characters\)
sed "s/^X//" >'unzip-5.12/vms/cmdline.c' <<'END_OF_FILE'
X#define module_name VMS_UNZIP_CMDLINE
X#define module_ident "02-002"
X/*
X**
X** Facility: UNZIP
X**
X** Module: VMS_UNZIP_CMDLINE
X**
X** Author: Hunter Goatley <goathunter@wkuvx1.wku.edu>
X**
X** Date: 12 Jul 94 (orig. Zip version, 30 Jul 93)
X**
X** Abstract: Routines to handle a VMS CLI interface for UnZip. The CLI
X** command line is parsed and a new argc/argv are built and
X** returned to UnZip.
X**
X** Modified by:
X**
X** 02-002 Hunter Goatley 16-JUL-1994 10:20
X** Fixed some typos.
X** 02-001 Cave Newt 14-JUL-1994 15:18
X** Removed obsolete /EXTRACT option; fixed /*TEXT options;
X** wrote VMSCLI usage() function
X** 02-000 Hunter Goatley 12-JUL-1994 00:00
X** Original UnZip version (v5.11).
X** 01-000 Hunter Goatley 30-JUL-1993 07:54
X** Original version (for Zip v1.9p1).
X**
X*/
X
X
X#ifdef __alpha
X#pragma module module_name module_ident
X#else
X#module module_name module_ident
X#endif
X
X#include "unzip.h"
X#include "version.h" /* for usage() */
X
X#include <ssdef.h>
X#include <descrip.h>
X#include <climsgdef.h>
X#include <clidef.h>
X#include <lib$routines.h>
X#include <str$routines.h>
X
X#ifndef CLI$_COMMA
Xglobalvalue CLI$_COMMA;
X#endif
X
X/*
X** "Macro" to initialize a dynamic string descriptor.
X*/
X#define init_dyndesc(dsc) {\
X dsc.dsc$w_length = 0;\
X dsc.dsc$b_dtype = DSC$K_DTYPE_T;\
X dsc.dsc$b_class = DSC$K_CLASS_D;\
X dsc.dsc$a_pointer = 0;}
X
X/*
X** Define descriptors for all of the CLI parameters and qualifiers.
X*/
X#if 0
X$DESCRIPTOR(cli_extract, "EXTRACT"); /* obsolete */
X#endif
X$DESCRIPTOR(cli_autotext, "AUTOTEXT"); /* -a */
X$DESCRIPTOR(cli_text, "TEXT"); /* -aa */
X$DESCRIPTOR(cli_case_insensitive, "CASE_INSENSITIVE"); /* -C */
X$DESCRIPTOR(cli_screen, "SCREEN"); /* -c */
X$DESCRIPTOR(cli_directory, "DIRECTORY"); /* see JUNK */
X$DESCRIPTOR(cli_freshen, "FRESHEN"); /* -f */
X$DESCRIPTOR(cli_junk, "JUNK"); /* -j */
X$DESCRIPTOR(cli_lowercase, "LOWERCASE"); /* -L */
X$DESCRIPTOR(cli_list, "LIST"); /* -l */
X$DESCRIPTOR(cli_brief, "BRIEF"); /* -l */
X$DESCRIPTOR(cli_full, "FULL"); /* -v */
X$DESCRIPTOR(cli_overwrite, "OVERWRITE"); /* -o, -n */
X$DESCRIPTOR(cli_quiet, "QUIET"); /* -q */
X$DESCRIPTOR(cli_super_quiet, "SUPER_QUIET"); /* -qq */
X$DESCRIPTOR(cli_test, "TEST"); /* -t */
X$DESCRIPTOR(cli_type, "TYPE"); /* -c */
X$DESCRIPTOR(cli_pipe, "PIPE"); /* -p */
X$DESCRIPTOR(cli_uppercase, "UPPERCASE"); /* -U */
X$DESCRIPTOR(cli_update, "UPDATE"); /* -u */
X$DESCRIPTOR(cli_version, "VERSION"); /* -V */
X$DESCRIPTOR(cli_verbose, "VERBOSE"); /* -v */
X$DESCRIPTOR(cli_restore, "RESTORE"); /* -X */
X$DESCRIPTOR(cli_comment, "COMMENT"); /* -z */
X$DESCRIPTOR(cli_exclude, "EXCLUDE"); /* -x */
X
X$DESCRIPTOR(cli_information, "ZIPINFO"); /* -Z */
X$DESCRIPTOR(cli_short, "SHORT"); /* -Zs */
X$DESCRIPTOR(cli_medium, "MEDIUM"); /* -Zm */
X$DESCRIPTOR(cli_long, "LONG"); /* -Zl */
X$DESCRIPTOR(cli_header, "HEADER"); /* -Zh */
X$DESCRIPTOR(cli_totals, "TOTALS"); /* -Zt */
X$DESCRIPTOR(cli_times, "TIMES"); /* -ZT */
X$DESCRIPTOR(cli_one_line, "ONE_LINE"); /* -Z2 */
X
X$DESCRIPTOR(cli_yyz, "YYZ");
X
X$DESCRIPTOR(cli_zipfile, "ZIPFILE");
X$DESCRIPTOR(cli_infile, "INFILE");
X$DESCRIPTOR(unzip_command, "unzip ");
X$DESCRIPTOR(blank, " ");
X
X#ifdef __alpha
Xextern void *vms_unzip_cld;
X#else
Xglobalref void *vms_unzip_cld;
X#endif
X
X/* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */
X
Xextern unsigned long cli$dcl_parse ();
Xextern unsigned long cli$present ();
Xextern unsigned long cli$get_value ();
X
Xunsigned long vms_unzip_cmdline (int *, char ***);
Xunsigned long get_list (struct dsc$descriptor_s *, char **,
X struct dsc$descriptor_d *, char);
Xunsigned long check_cli (struct dsc$descriptor_s *);
X
X
X#ifdef TEST
Xunsigned long
Xmain(int argc, char **argv)
X{
X register status;
X return (vms_unzip_cmdline(&argc, &argv));
X}
X#endif /* TEST */
X
X
Xunsigned long
Xvms_unzip_cmdline (int *argc_p, char ***argv_p)
X{
X/*
X** Routine: vms_unzip_cmdline
X**
X** Function:
X**
X** Parse the DCL command line and create a fake argv array to be
X** handed off to Zip.
X**
X** NOTE: the argv[] is built as we go, so all the parameters are
X** checked in the appropriate order!!
X**
X** Formal parameters:
X**
X** argc_p - Address of int to receive the new argc
X** argv_p - Address of char ** to receive the argv address
X**
X** Calling sequence:
X**
X** status = vms_unzip_cmdline (&argc, &argv);
X**
X** Returns:
X**
X** SS$_NORMAL - Success.
X** SS$_INSFMEM - A malloc() or realloc() failed
X** SS$_ABORT - Bad time value
X**
X*/
X register status;
X char options[256];
X char *the_cmd_line;
X char *ptr;
X int x, len, zipinfo;
X
X int new_argc;
X char **new_argv;
X
X struct dsc$descriptor_d work_str;
X struct dsc$descriptor_d foreign_cmdline;
X struct dsc$descriptor_d output_directory;
X
X init_dyndesc (work_str);
X init_dyndesc (foreign_cmdline);
X init_dyndesc (output_directory);
X
X /*
X ** See if the program was invoked by the CLI (SET COMMAND) or by
X ** a foreign command definition. Check for /YYZ, which is a
X ** valid default qualifier solely for this test.
X */
X status = check_cli (&cli_yyz);
X if (!(status & 1)) {
X lib$get_foreign (&foreign_cmdline);
X /*
X ** If nothing was returned or the first character is a "-", then
X ** assume it's a UNIX-style command and return.
X */
X if ((foreign_cmdline.dsc$w_length == 0) || (*(foreign_cmdline.dsc$a_pointer) == '-'))
X return(SS$_NORMAL);
X
X str$concat (&work_str, &unzip_command, &foreign_cmdline);
X status = cli$dcl_parse(&work_str, &vms_unzip_cld, lib$get_input,
X lib$get_input, 0);
X if (!(status & 1)) return(status);
X }
X
X /*
X ** There's always going to be an new_argv[] because of the image name.
X */
X if ((the_cmd_line = (char *) malloc (sizeof("unzip")+1)) == NULL)
X return(SS$_INSFMEM);
X
X strcpy (the_cmd_line, "unzip");
X
X /*
X ** First, check to see if any of the regular options were specified.
X */
X
X options[0] = '-';
X ptr = &options[1]; /* Point to temporary buffer */
X
X /*
X ** Is it Zipinfo??
X */
X zipinfo = 0;
X status = cli$present (&cli_information);
X if (status & 1) {
X
X zipinfo = 1;
X
X *ptr++ = 'Z';
X *ptr++ = ' ';
X *ptr++ = '-';
X
X if (cli$present(&cli_one_line) & 1)
X *ptr++ = '2';
X if (cli$present(&cli_short) & 1)
X *ptr++ = 's';
X if (cli$present(&cli_medium) & 1)
X *ptr++ = 'm';
X if (cli$present(&cli_long) & 1)
X *ptr++ = 'l';
X if (cli$present(&cli_header) & 1)
X *ptr++ = 'h';
X if (cli$present(&cli_comment) & 1)
X *ptr++ = 'c';
X if (cli$present(&cli_totals) & 1)
X *ptr++ = 't';
X if (cli$present(&cli_times) & 1)
X *ptr++ = 'T';
X
X /* If no other options were specified, remove the " -". */
X if (*(ptr - 1) == '-')
X ptr = ptr - 2;
X
X }
X else {
X
X#if 0
X /*
X ** Extract files?
X */
X status = cli$present (&cli_extract);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'x';
X#endif
X
X /*
X ** Convert all files as text (CR LF -> LF, etc.)
X */
X status = cli$present (&cli_text);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT) {
X *ptr++ = 'a';
X *ptr++ = 'a';
X }
X
X /*
X ** Auto-convert only text files as text
X */
X status = cli$present (&cli_autotext);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'a';
X
X /*
X ** Extract files to screen?
X */
X status = cli$present (&cli_screen);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'c';
X
X /*
X ** Re-create directory structure? (default)
X */
X status = cli$present (&cli_directory);
X if (status == CLI$_PRESENT) {
X status = cli$get_value (&cli_directory, &output_directory);
X }
X
X /*
X ** Freshen existing files, create none
X */
X status = cli$present (&cli_freshen);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'f';
X
X /*
X ** Junk stored directory names on unzip
X */
X status = cli$present (&cli_junk);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'j';
X
X /*
X ** List contents (/BRIEF or /FULL (default))
X */
X status = cli$present (&cli_list);
X if (status & 1) {
X if (cli$present(&cli_full) & 1)
X *ptr++ = 'v';
X else
X *ptr++ = 'l';
X }
X
X /*
X ** Overwrite files?
X */
X status = cli$present (&cli_overwrite);
X if (status == CLI$_NEGATED)
X *ptr++ = 'n';
X else if (status != CLI$_ABSENT)
X *ptr++ = 'o';
X
X /*
X ** Pipe files to SYS$OUTPUT with no informationals?
X */
X status = cli$present (&cli_pipe);
X if (status != CLI$_ABSENT)
X *ptr++ = 'p';
X
X /*
X ** Quiet
X */
X status = cli$present (&cli_quiet);
X if (status & 1)
X *ptr++ = 'q';
X
X status = cli$present (&cli_super_quiet);
X if (status & 1)
X *ptr++ = 'q';
X
X /*
X ** Test archive integrity
X */
X status = cli$present (&cli_test);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 't';
X
X /*
X ** Match filenames case-insensitively (-C)
X */
X status = cli$present (&cli_case_insensitive);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'C';
X
X /*
X ** Make (some) names lowercase
X */
X status = cli$present (&cli_lowercase);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'L';
X
X /*
X ** Uppercase (don't convert to lower)
X */
X status = cli$present (&cli_uppercase);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'U';
X
X /*
X ** Update (extract only new and newer files)
X */
X status = cli$present (&cli_update);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'u';
X
X /*
X ** Version (retain VMS/DEC-20 file versions)
X */
X status = cli$present (&cli_version);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'V';
X
X /*
X ** Verbose
X */
X status = cli$present (&cli_verbose);
X if (status & 1)
X *ptr++ = 'v';
X
X /*
X ** Restore owner/protection info
X */
X status = cli$present (&cli_restore);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'X';
X
X /*
X ** Display only the archive comment
X */
X status = cli$present (&cli_comment);
X if (status == CLI$_NEGATED)
X *ptr++ = '-';
X if (status != CLI$_ABSENT)
X *ptr++ = 'z';
X
X } /* Zipinfo check way up there.... */
X
X /*
X ** If the user didn't give any DCL qualifier, assume he wants the
X ** Un*x interface.
X if (ptr == &options[1])
X return(SS$_NORMAL);
X */
X
X /*
X ** Now copy the final options string to the_cmd_line.
X */
X x = ptr - &options[0];
X if (x > 1) {
X options[x] = '\0';
X len = strlen(the_cmd_line) + x + 2;
X if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
X return(SS$_INSFMEM);
X strcat (the_cmd_line, " ");
X strcat (the_cmd_line, options);
X }
X
X /*
X ** Now get the specified zip file name.
X */
X status = cli$present (&cli_zipfile);
X if (status & 1) {
X status = cli$get_value (&cli_zipfile, &work_str);
X
X len = strlen(the_cmd_line) + work_str.dsc$w_length + 2;
X if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
X return(SS$_INSFMEM);
X strcat (the_cmd_line, " ");
X x = strlen(the_cmd_line);
X strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,
X work_str.dsc$w_length);
X the_cmd_line[len] = '\0';
X
X }
X
X /*
X ** Run through the list of files to unzip.
X */
X status = cli$present (&cli_infile);
X if (status & 1) {
X len = strlen(the_cmd_line) + 2;
X if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
X return(SS$_INSFMEM);
X strcat (the_cmd_line, " ");
X status = get_list (&cli_infile, &the_cmd_line, &foreign_cmdline, ' ');
X if (!(status & 1)) return (status);
X }
X
X /*
X ** Get the list of files to exclude, if there are any.
X */
X status = cli$present (&cli_exclude);
X if (status & 1) {
X len = strlen(the_cmd_line) + 5;
X if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
X return(SS$_INSFMEM);
X strcat (the_cmd_line, " -x ");
X status = get_list (&cli_exclude, &the_cmd_line, &foreign_cmdline, ' ');
X if (!(status & 1)) return (status);
X }
X
X /*
X ** Get the output directory, for UnZip.
X **/
X if (output_directory.dsc$w_length != 0) {
X len = strlen(the_cmd_line) + output_directory.dsc$w_length + 5;
X if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
X return(SS$_INSFMEM);
X strcat (the_cmd_line, " -d ");
X x = strlen(the_cmd_line);
X strncpy(&the_cmd_line[x], output_directory.dsc$a_pointer,
X output_directory.dsc$w_length);
X the_cmd_line[len] = '\0';
X }
X
X /*
X ** Now that we've built our new UNIX-like command line, count the
X ** number of args and build an argv array.
X */
X
X#if defined(TEST) || defined(DEBUG)
X printf("%s\n",the_cmd_line);
X#endif /* TEST */
X
X new_argc = 1;
X for (ptr = the_cmd_line;
X (ptr = strchr(ptr,' ')) != NULL;
X ptr++, new_argc++);
X
X /*
X ** Allocate memory for the new argv[]. The last element of argv[]
X ** is supposed to be 0, so allocate enough for new_argc+1.
X */
X if ((new_argv = (char **) calloc (new_argc+1, sizeof(char *))) == NULL)
X return(SS$_INSFMEM);
X
X /*
X ** For each option, store the address in new_argv[] and convert the
X ** separating blanks to nulls so each argv[] string is terminated.
X */
X for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {
X new_argv[x] = ptr;
X if ((ptr = strchr (ptr, ' ')) != NULL)
X *ptr++ = '\0';
X }
X new_argv[new_argc] = 0;
X
X#if defined(TEST) || defined(DEBUG)
X printf("new_argc = %d\n", new_argc);
X for (x = 0; x < new_argc; x++)
X printf("new_argv[%d] = %s\n", x, new_argv[x]);
X#endif /* TEST */
X
X /*
X ** All finished. Return the new argc and argv[] addresses to Zip.
X */
X *argc_p = new_argc;
X *argv_p = new_argv;
X
X return(SS$_NORMAL);
X}
X
X
X
Xunsigned long
Xget_list (struct dsc$descriptor_s *qual, char **str,
X struct dsc$descriptor_d *cmdline, char c)
X{
X/*
X** Routine: get_list
X**
X** Function: This routine runs through a comma-separated CLI list
X** and copies the strings to the command line. The
X** specified separation character is used to separate
X** the strings on the command line.
X**
X** All strings are converted to lower-case.
X**
X** Formal parameters:
X**
X** qual - Address of descriptor for the qualifier name
X** str - Address of pointer pointing to string (command line)
X** c - Character to use to separate the list items
X**
X*/
X
X register status;
X struct dsc$descriptor_d work_str;
X
X init_dyndesc(work_str);
X
X status = cli$present (qual);
X if (status & 1) {
X
X unsigned long len, old_len, lower_it, ind, sind;
X
X len = strlen(*str);
X while ((status = cli$get_value (qual, &work_str)) & 1) {
X /*
X ** Just in case the string doesn't exist yet, though it does.
X */
X if (*str == NULL) {
X len = work_str.dsc$w_length + 1;
X if ((*str = (char *) malloc (work_str.dsc$w_length)) == NULL)
X return(SS$_INSFMEM);
X strncpy(*str,work_str.dsc$a_pointer,len);
X } else {
X char *src, *dst; int x;
X old_len = len;
X len += work_str.dsc$w_length + 1;
X if ((*str = (char *) realloc (*str, len)) == NULL)
X return(SS$_INSFMEM);
X
X /*
X ** Look for the filename in the original foreign command
X ** line to see if it was originally quoted. If so, then
X ** don't convert it to lowercase.
X */
X lower_it = 0;
X str$find_first_substring (cmdline, &ind, &sind, &work_str);
X if (*(cmdline->dsc$a_pointer + ind - 2) == '"')
X lower_it = 1;
X
X /*
X ** Copy the string to the buffer, converting to lowercase.
X */
X src = work_str.dsc$a_pointer;
X dst = *str+old_len;
X for (x = 0; x < work_str.dsc$w_length; x++) {
X if (!lower_it && ((*src >= 'A') && (*src <= 'Z')))
X *dst++ = *src++ + 32;
X else
X *dst++ = *src++;
X }
X }
X if (status == CLI$_COMMA)
X (*str)[len-1] = c;
X else
X (*str)[len-1] = '\0';
X }
X }
X
X return (SS$_NORMAL);
X
X}
X
X
Xunsigned long
Xcheck_cli (struct dsc$descriptor_s *qual)
X{
X/*
X** Routine: check_cli
X**
X** Function: Check to see if a CLD was used to invoke the program.
X**
X** Formal parameters:
X**
X** qual - Address of descriptor for qualifier name to check.
X**
X*/
X lib$establish(lib$sig_to_ret); /* Establish condition handler */
X return (cli$present(qual)); /* Just see if something was given */
X}
X
X
X
X#ifndef SFX
X
X#ifdef VMSWILD
X# define ZI_XMPL "*, %, () (e.g., \"(a-j)*pk.%%\")"
X#else
X# define ZI_XMPL "*, ?, [] (e.g., \"[a-j]*pk.??\")"
X#endif
X
Xint usage( int error) /* VMSCLI version; returns PK-type error code */
X{
X FILE *usagefp;
X extern char UnzipUsageLine1[];
X
X
X/*---------------------------------------------------------------------------
X If user requested usage, send it to stdout; else send to stderr.
X ---------------------------------------------------------------------------*/
X
X if (error)
X usagefp = (FILE *)stderr;
X else
X usagefp = (FILE *)stdout;
X
X/*---------------------------------------------------------------------------
X Print either ZipInfo usage or UnZip usage, depending on incantation.
X ---------------------------------------------------------------------------*/
X
X if (zipinfo_mode) {
X
X#ifndef NO_ZIPINFO
X
X fprintf(usagefp, "\
XZipInfo %s, by Newtware and the fine folks at Info-ZIP.\n\n\
XList name, date/time, attribute, size, compression method, etc., about files\n\
Xin list (excluding those in xlist) contained in the specified .zip archive(s).\
X\n\"file[.zip]\" may be a wildcard name containing %s.\n", ZI_VERSION, ZI_XMPL);
X
X fprintf(usagefp, "\n\
X usage: zipinfo file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\n\
X or: unzip /ZIPINFO file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\
X\n\nmain\
X listing-format options: /SHORT short \"ls -l\" format (def.)\n\
X /ONE_LINE just filenames, one/line /MEDIUM medium Unix \"ls -l\" format\n\
X /VERBOSE verbose, multi-page format /LONG long Unix \"ls -l\" format\n\
X ");
X
X fprintf(usagefp, "\n\
Xmiscellaneous options:\n \
X/HEADER print header line /TOTALS totals for listed files or for all\n\
X /COMMENT print zipfile comment /TIMES times in sortable decimal format\n\
X /EXCLUDE=(file-spec1,etc.) exclude file-specs from listing\n");
X
X fprintf(usagefp, "\nRemember that non-lowercase filespecs must be\
X quoted in VMS (e.g., \"Makefile\").\n");
X
X#endif /* !NO_ZIPINFO */
X
X } else { /* UnZip mode */
X
X fprintf(usagefp, UnzipUsageLine1, UZ_VERSION);
X
X#ifdef BETA
X fprintf(usagefp, "\
X THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n",
X "", "");
X#endif
X
X fprintf(usagefp, "\
XUsage: unzip file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options /modifiers\
X\n Default action is to extract files in list, except those in xlist, to exdir\
X;\n file[.zip] may be a wildcard. %s\n\n",
X#ifdef NO_ZIPINFO
X "(ZipInfo mode is disabled in this version.)"
X#else
X "Type \"unzip /ZIPINFO\" for ZipInfo-mode usage."
X#endif
X );
X
X fprintf(usagefp, "\
XMajor options include:\n\
X /[NO]TEST, /LIST, /[NO]SCREEN, /PIPE, /[NO]FRESHEN, /[NO]UPDATE,\n\
X /[NO]COMMENT, /DIRECTORY=directory-spec, /EXCLUDE=(file-spec1,etc.)\n\n\
XModifiers include:\n\
X /BRIEF, /FULL, /[NO]AUTOTEXT, /[NO]TEXT, /[NO]OVERWRITE, /[NO]JUNK,\n\
X /QUIET, /SUPER_QUIET, /[NO]CASE_INSENSITIVE, /[NO]LOWERCASE,\n\
X /[NO]VERSION, /[NO]RESTORE\n\n");
X
X fprintf(usagefp, "\
XExamples (see unzip.doc or \"HELP UNZIP\" for more info):\n \
Xunzip edit1 /EXCL=joe.jou /CASE_INSENSITIVE => extract all files except\n \
X joe.jou (or JOE.JOU, or any combination of case) from zipfile edit1.zip\n \
Xunzip zip201 \"Makefile.VMS\" vms/*.[ch] => extract VMS Makefile and\n\
X *.c and *.h files; must quote uppercase names if /CASE_INSENS not used\n\
X unzip foo /DIR=tmp:[.test] /JUNK /AUTO /OVER => extract all files to temp.\
X\n directory without paths, auto-converting text files and overwriting\n");
X
X } /* end if (zipinfo_mode) */
X
X if (error)
X return PK_PARAM;
X else
X return PK_COOL; /* just wanted usage screen: no error */
X
X} /* end function usage() */
X
X#endif /* !SFX */
END_OF_FILE
if test 20360 -ne `wc -c <'unzip-5.12/vms/cmdline.c'`; then
echo shar: \"'unzip-5.12/vms/cmdline.c'\" unpacked with wrong size!
fi
# end of 'unzip-5.12/vms/cmdline.c'
fi
echo shar: End of archive 6 \(of 20\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 20 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...