home *** CD-ROM | disk | FTP | other *** search
- From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
- Newsgroups: comp.sources.misc
- Subject: v44i077: unzip - Info-ZIP portable UnZip, version 5.12, Part12/20
- Date: 18 Sep 1994 23:16:01 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <35j3a1$qpg@sparky.sterling.com>
- X-Md4-Signature: 84e6e974cc4c02fa0169d55b28be519c
-
- Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
- Posting-number: Volume 44, Issue 77
- Archive-name: unzip/part12
- 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/atari/atari.c unzip-5.12/match.c
- # unzip-5.12/unix/unzip.1
- # Wrapped by kent@sparky on Sat Sep 17 23:33:42 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 12 (of 20)."'
- if test -f 'unzip-5.12/atari/atari.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unzip-5.12/atari/atari.c'\"
- else
- echo shar: Extracting \"'unzip-5.12/atari/atari.c'\" \(26647 characters\)
- sed "s/^X//" >'unzip-5.12/atari/atari.c' <<'END_OF_FILE'
- X/*---------------------------------------------------------------------------
- X
- X atari.c
- X
- X Atari-specific routines for use with Info-ZIP's UnZip 5.1 and later.
- X
- X Contains: readdir()
- X do_wild() <-- generic enough to put in file_io.c?
- X mapattr()
- X mapname()
- X checkdir()
- X mkdir()
- X close_outfile()
- X version()
- X
- X Due to the amazing MiNT library being very, very close to BSD unix's
- X library, I'm using the unix.c as a base for this. Note: If you're not
- X going to compile this with the MiNT libraries (for GNU C, Turbo C, Pure C,
- X Lattice C, or Heat & Serve C), you're going to be in for some nasty work.
- X Most of the modifications in this file were made by Chris Herborth
- X (cherborth@semprini.waterloo-rdp.on.ca) and /should/ be marked with [cjh].
- X
- X ---------------------------------------------------------------------------*/
- X
- X
- X#include "unzip.h"
- X#include <dirent.h> /* MiNTlibs has dirent [cjh] */
- X
- Xstatic int created_dir; /* used in mapname(), checkdir() */
- Xstatic int renamed_fullpath; /* ditto */
- X
- X/**********************/
- X/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */
- X/**********************/
- X
- Xchar *do_wild(wildspec)
- X char *wildspec; /* only used first time on a given dir */
- X{
- X static DIR *dir = NULL;
- X static char *dirname, *wildname, matchname[FILNAMSIZ];
- X static int firstcall=TRUE, have_dirname, dirnamelen;
- X struct dirent *file;
- X
- X
- X /* Even when we're just returning wildspec, we *always* do so in
- X * matchname[]--calling routine is allowed to append four characters
- X * to the returned string, and wildspec may be a pointer to argv[].
- X */
- X if (firstcall) { /* first call: must initialize everything */
- X firstcall = FALSE;
- X
- X /* break the wildspec into a directory part and a wildcard filename */
- X if ((wildname = strrchr(wildspec, '/')) == NULL) {
- X dirname = ".";
- X dirnamelen = 1;
- X have_dirname = FALSE;
- X wildname = wildspec;
- X } else {
- X ++wildname; /* point at character after '/' */
- X dirnamelen = wildname - wildspec;
- X if ((dirname = (char *)malloc(dirnamelen+1)) == NULL) {
- X fprintf(stderr, "warning: can't allocate wildcard buffers\n");
- X strcpy(matchname, wildspec);
- X return matchname; /* but maybe filespec was not a wildcard */
- X }
- X strncpy(dirname, wildspec, dirnamelen);
- X dirname[dirnamelen] = '\0'; /* terminate for strcpy below */
- X have_dirname = TRUE;
- X }
- X
- X if ((dir = opendir(dirname)) != NULL) {
- X while ((file = readdir(dir)) != NULL) {
- X if (file->d_name[0] == '.' && wildname[0] != '.')
- X continue; /* Unix: '*' and '?' do not match leading dot */
- X /* Need something here for TOS filesystem? [cjh] */
- X if (match(file->d_name, wildname, 0)) { /* 0 == case sens. */
- X if (have_dirname) {
- X strcpy(matchname, dirname);
- X strcpy(matchname+dirnamelen, file->d_name);
- X } else
- X strcpy(matchname, file->d_name);
- X return matchname;
- X }
- X }
- X /* if we get to here directory is exhausted, so close it */
- X closedir(dir);
- X dir = NULL;
- X }
- X
- X /* return the raw wildspec in case that works (e.g., directory not
- X * searchable, but filespec was not wild and file is readable) */
- X strcpy(matchname, wildspec);
- X return matchname;
- X }
- X
- X /* last time through, might have failed opendir but returned raw wildspec */
- X if (dir == NULL) {
- X firstcall = TRUE; /* nothing left to try--reset for new wildspec */
- X if (have_dirname)
- X free(dirname);
- X return (char *)NULL;
- X }
- X
- X /* If we've gotten this far, we've read and matched at least one entry
- X * successfully (in a previous call), so dirname has been copied into
- X * matchname already.
- X */
- X while ((file = readdir(dir)) != NULL)
- X /* May need special TOS handling here. [cjh] */
- X if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */
- X if (have_dirname) {
- X /* strcpy(matchname, dirname); */
- X strcpy(matchname+dirnamelen, file->d_name);
- X } else
- X strcpy(matchname, file->d_name);
- X return matchname;
- X }
- X
- X closedir(dir); /* have read at least one dir entry; nothing left */
- X dir = NULL;
- X firstcall = TRUE; /* reset for new wildspec */
- X if (have_dirname)
- X free(dirname);
- X return (char *)NULL;
- X
- X} /* end function do_wild() */
- X
- X
- X
- X
- X
- X/**********************/
- X/* Function mapattr() */
- X/**********************/
- X
- Xint mapattr()
- X{
- X ulg tmp = crec.external_file_attributes;
- X
- X switch (pInfo->hostnum) {
- X case UNIX_:
- X /* minix filesystem under MiNT on Atari [cjh] */
- X case VMS_:
- X pInfo->file_attr = (unsigned)(tmp >> 16);
- X return 0;
- X case AMIGA_:
- X tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */
- X pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
- X break;
- X /* all remaining cases: expand MSDOS read-only bit into write perms */
- X case FS_FAT_:
- X case FS_HPFS_:
- X case FS_NTFS_:
- X case MAC_:
- X case ATARI_: /* (used to set = 0666) */
- X /* TOS filesystem [cjh] */
- X case TOPS20_:
- X default:
- X tmp = !(tmp & 1) << 1; /* read-only bit --> write perms bits */
- X pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
- X break;
- X } /* end switch (host-OS-created-by) */
- X
- X /* for originating systems with no concept of "group," "other," "system": */
- X umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */
- X pInfo->file_attr &= ~tmp;
- X
- X return 0;
- X
- X} /* end function mapattr() */
- X
- X
- X
- X
- X
- X/************************/
- X/* Function mapname() */
- X/************************/
- X
- Xint mapname(renamed) /* return 0 if no error, 1 if caution (filename trunc), */
- X int renamed; /* 2 if warning (skip file because dir doesn't exist), */
- X{ /* 3 if error (skip file), 10 if no memory (skip file) */
- X char pathcomp[FILNAMSIZ]; /* path-component buffer */
- X char *pp, *cp=NULL; /* character pointers */
- X char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */
- X int quote = FALSE; /* flags */
- X int error = 0;
- X register unsigned workch; /* hold the character being tested */
- X
- X
- X/*---------------------------------------------------------------------------
- X Initialize various pointers and counters and stuff.
- X ---------------------------------------------------------------------------*/
- X
- X if (pInfo->vollabel)
- X return IZ_VOL_LABEL; /* can't set disk volume labels in Unix */
- X
- X /* can create path as long as not just freshening, or if user told us */
- X create_dirs = (!fflag || renamed);
- X
- X created_dir = FALSE; /* not yet */
- X
- X /* user gave full pathname: don't prepend rootpath */
- X renamed_fullpath = (renamed && (*filename == '/'));
- X
- X if (checkdir((char *)NULL, INIT) == 10)
- X return 10; /* initialize path buffer, unless no memory */
- X
- X *pathcomp = '\0'; /* initialize translation buffer */
- X pp = pathcomp; /* point to translation buffer */
- X if (jflag) /* junking directories */
- X cp = (char *)strrchr(filename, '/');
- X if (cp == NULL) /* no '/' or not junking dirs */
- X cp = filename; /* point to internal zipfile-member pathname */
- X else
- X ++cp; /* point to start of last component of path */
- X
- X/*---------------------------------------------------------------------------
- X Begin main loop through characters in filename.
- X ---------------------------------------------------------------------------*/
- X
- X while ((workch = (uch)*cp++) != 0) {
- X
- X if (quote) { /* if character quoted, */
- X *pp++ = (char)workch; /* include it literally */
- X quote = FALSE;
- X } else
- X switch (workch) {
- X case '/': /* can assume -j flag not given */
- X *pp = '\0';
- X if ((error = checkdir(pathcomp, APPEND_DIR)) > 1)
- X return error;
- X pp = pathcomp; /* reset conversion buffer for next piece */
- X lastsemi = NULL; /* leave directory semi-colons alone */
- X break;
- X
- X case ';': /* VMS version (or DEC-20 attrib?) */
- X lastsemi = pp; /* keep for now; remove VMS ";##" */
- X *pp++ = (char)workch; /* later, if requested */
- X break;
- X
- X case '\026': /* control-V quote for special chars */
- X quote = TRUE; /* set flag for next character */
- X break;
- X
- X#ifdef MTS
- X case ' ': /* change spaces to underscore under */
- X *pp++ = '_'; /* MTS; leave as spaces under Unix */
- X break;
- X#endif
- X
- X default:
- X /* allow European characters in filenames: */
- X if (isprint(workch) || (128 <= workch && workch <= 254))
- X *pp++ = (char)workch;
- X } /* end switch */
- X
- X } /* end while loop */
- X
- X *pp = '\0'; /* done with pathcomp: terminate it */
- X
- X /* if not saving them, remove VMS version numbers (appended ";###") */
- X if (!V_flag && lastsemi) {
- X pp = lastsemi + 1;
- X while (isdigit((uch)(*pp)))
- X ++pp;
- X if (*pp == '\0') /* only digits between ';' and end: nuke */
- X *lastsemi = '\0';
- X }
- X
- X/*---------------------------------------------------------------------------
- X Report if directory was created (and no file to create: filename ended
- X in '/'), check name to be sure it exists, and combine path and name be-
- X fore exiting.
- X ---------------------------------------------------------------------------*/
- X
- X if (filename[strlen(filename) - 1] == '/') {
- X checkdir(filename, GETPATH);
- X if (created_dir && QCOND2) {
- X fprintf(stdout, " creating: %s\n", filename);
- X return IZ_CREATED_DIR; /* set dir time (note trailing '/') */
- X }
- X return 2; /* dir existed already; don't look for data to extract */
- X }
- X
- X if (*pathcomp == '\0') {
- X fprintf(stderr, "mapname: conversion of %s failed\n", filename);
- X return 3;
- X }
- X
- X checkdir(pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */
- X checkdir(filename, GETPATH);
- X
- X return error;
- X
- X} /* end function mapname() */
- X
- X
- X
- X
- X#if 0 /*========== NOTES ==========*/
- X
- X extract-to dir: a:path/
- X buildpath: path1/path2/ ... (NULL-terminated)
- X pathcomp: filename
- X
- X mapname():
- X loop over chars in zipfile member name
- X checkdir(path component, COMPONENT | CREATEDIR) --> map as required?
- X (d:/tmp/unzip/) (disk:[tmp.unzip.)
- X (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.)
- X (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.)
- X finally add filename itself and check for existence? (could use with rename)
- X (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir)
- X checkdir(name, COPYFREE) --> copy path to name and free space
- X
- X#endif /* 0 */
- X
- X
- X
- X
- X/***********************/
- X/* Function checkdir() */
- X/***********************/
- X
- Xint checkdir(pathcomp, flag)
- X char *pathcomp;
- X int flag;
- X/*
- X * returns: 1 - (on APPEND_NAME) truncated filename
- X * 2 - path doesn't exist, not allowed to create
- X * 3 - path doesn't exist, tried to create and failed; or
- X * path exists and is not a directory, but is supposed to be
- X * 4 - path is too long
- X * 10 - can't allocate memory for filename buffers
- X */
- X{
- X static int rootlen = 0; /* length of rootpath */
- X static char *rootpath; /* user's "extract-to" directory */
- X static char *buildpath; /* full path (so far) to extracted file */
- X static char *end; /* pointer to end of buildpath ('\0') */
- X
- X# define FN_MASK 7
- X# define FUNCTION (flag & FN_MASK)
- X
- X
- X
- X/*---------------------------------------------------------------------------
- X APPEND_DIR: append the path component to the path being built and check
- X for its existence. If doesn't exist and we are creating directories, do
- X so for this one; else signal success or error as appropriate.
- X ---------------------------------------------------------------------------*/
- X
- X if (FUNCTION == APPEND_DIR) {
- X int too_long = FALSE;
- X/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */
- X#ifdef SHORT_NAMES
- X char *old_end = end;
- X#endif
- X
- X Trace((stderr, "appending dir segment [%s]\n", pathcomp));
- X while ((*end = *pathcomp++) != '\0')
- X ++end;
- X/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */
- X#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */
- X if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */
- X *(end = old_end + FILENAME_MAX) = '\0';
- X#endif
- X
- X /* GRR: could do better check, see if overrunning buffer as we go:
- X * check end-buildpath after each append, set warning variable if
- X * within 20 of FILNAMSIZ; then if var set, do careful check when
- X * appending. Clear variable when begin new path. */
- X
- X if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */
- X too_long = TRUE; /* check if extracting directory? */
- X if (stat(buildpath, &statbuf)) { /* path doesn't exist */
- X if (!create_dirs) { /* told not to create (freshening) */
- X free(buildpath);
- X return 2; /* path doesn't exist: nothing to do */
- X }
- X if (too_long) {
- X fprintf(stderr, "checkdir error: path too long: %s\n",
- X buildpath);
- X fflush(stderr);
- X free(buildpath);
- X return 4; /* no room for filenames: fatal */
- X }
- X if (mkdir(buildpath, 0777) == -1) { /* create the directory */
- X fprintf(stderr, "checkdir error: can't create %s\n\
- X unable to process %s.\n", buildpath, filename);
- X fflush(stderr);
- X free(buildpath);
- X return 3; /* path didn't exist, tried to create, failed */
- X }
- X created_dir = TRUE;
- X } else if (!S_ISDIR(statbuf.st_mode)) {
- X fprintf(stderr, "checkdir error: %s exists but is not directory\n\
- X unable to process %s.\n", buildpath, filename);
- X fflush(stderr);
- X free(buildpath);
- X return 3; /* path existed but wasn't dir */
- X }
- X if (too_long) {
- X fprintf(stderr, "checkdir error: path too long: %s\n", buildpath);
- X fflush(stderr);
- X free(buildpath);
- X return 4; /* no room for filenames: fatal */
- X }
- X *end++ = '/';
- X *end = '\0';
- X Trace((stderr, "buildpath now = [%s]\n", buildpath));
- X return 0;
- X
- X } /* end if (FUNCTION == APPEND_DIR) */
- X
- X/*---------------------------------------------------------------------------
- X GETPATH: copy full path to the string pointed at by pathcomp, and free
- X buildpath.
- X ---------------------------------------------------------------------------*/
- X
- X if (FUNCTION == GETPATH) {
- X strcpy(pathcomp, buildpath);
- X Trace((stderr, "getting and freeing path [%s]\n", pathcomp));
- X free(buildpath);
- X buildpath = end = NULL;
- X return 0;
- X }
- X
- X/*---------------------------------------------------------------------------
- X APPEND_NAME: assume the path component is the filename; append it and
- X return without checking for existence.
- X ---------------------------------------------------------------------------*/
- X
- X if (FUNCTION == APPEND_NAME) {
- X/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */
- X#ifdef SHORT_NAMES
- X char *old_end = end;
- X#endif
- X
- X Trace((stderr, "appending filename [%s]\n", pathcomp));
- X while ((*end = *pathcomp++) != '\0') {
- X ++end;
- X/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */
- X#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */
- X if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */
- X *(end = old_end + FILENAME_MAX) = '\0';
- X#endif
- X if ((end-buildpath) >= FILNAMSIZ) {
- X *--end = '\0';
- X fprintf(stderr, "checkdir warning: path too long; truncating\n\
- Xcheckdir warning: path too long; truncating\n\
- X %s\n -> %s\n", filename, buildpath);
- X fflush(stderr);
- X return 1; /* filename truncated */
- X }
- X }
- X Trace((stderr, "buildpath now = [%s]\n", buildpath));
- X return 0; /* could check for existence here, prompt for new name... */
- X }
- X
- X/*---------------------------------------------------------------------------
- X INIT: allocate and initialize buffer space for the file currently being
- X extracted. If file was renamed with an absolute path, don't prepend the
- X extract-to path.
- X ---------------------------------------------------------------------------*/
- X
- X/* GRR: for VMS and TOPS-20, add up to 13 to strlen */
- X
- X if (FUNCTION == INIT) {
- X Trace((stderr, "initializing buildpath to "));
- X if ((buildpath = (char *)malloc(strlen(filename)+rootlen+1)) == NULL)
- X return 10;
- X if ((rootlen > 0) && !renamed_fullpath) {
- X strcpy(buildpath, rootpath);
- X end = buildpath + rootlen;
- X } else {
- X *buildpath = '\0';
- X end = buildpath;
- X }
- X Trace((stderr, "[%s]\n", buildpath));
- X return 0;
- X }
- X
- X/*---------------------------------------------------------------------------
- X ROOT: if appropriate, store the path in rootpath and create it if neces-
- X sary; else assume it's a zipfile member and return. This path segment
- X gets used in extracting all members from every zipfile specified on the
- X command line.
- X ---------------------------------------------------------------------------*/
- X
- X#if (!defined(SFX) || defined(SFX_EXDIR))
- X if (FUNCTION == ROOT) {
- X Trace((stderr, "initializing root path to [%s]\n", pathcomp));
- X if (pathcomp == NULL) {
- X rootlen = 0;
- X return 0;
- X }
- X if ((rootlen = strlen(pathcomp)) > 0) {
- X int had_trailing_pathsep=FALSE;
- X
- X if (pathcomp[rootlen-1] == '/') {
- X pathcomp[--rootlen] = '\0';
- X had_trailing_pathsep = TRUE;
- X }
- X if (rootlen > 0 && (stat(pathcomp, &statbuf) ||
- X !S_ISDIR(statbuf.st_mode))) /* path does not exist */
- X {
- X if (!create_dirs /* || iswild(pathcomp) */
- X#ifdef OLD_EXDIR
- X || !had_trailing_pathsep
- X#endif
- X ) {
- X rootlen = 0;
- X return 2; /* skip (or treat as stored file) */
- X }
- X /* create the directory (could add loop here to scan pathcomp
- X * and create more than one level, but why really necessary?) */
- X if (mkdir(pathcomp, 0777) == -1) {
- X fprintf(stderr,
- X "checkdir: can't create extraction directory: %s\n",
- X pathcomp);
- X fflush(stderr);
- X rootlen = 0; /* path didn't exist, tried to create, and */
- X return 3; /* failed: file exists, or 2+ levels required */
- X }
- X }
- X if ((rootpath = (char *)malloc(rootlen+2)) == NULL) {
- X rootlen = 0;
- X return 10;
- X }
- X strcpy(rootpath, pathcomp);
- X rootpath[rootlen++] = '/';
- X rootpath[rootlen] = '\0';
- X }
- X Trace((stderr, "rootpath now = [%s]\n", rootpath));
- X return 0;
- X }
- X#endif /* !SFX || SFX_EXDIR */
- X
- X/*---------------------------------------------------------------------------
- X END: free rootpath, immediately prior to program exit.
- X ---------------------------------------------------------------------------*/
- X
- X if (FUNCTION == END) {
- X Trace((stderr, "freeing rootpath\n"));
- X if (rootlen > 0)
- X free(rootpath);
- X return 0;
- X }
- X
- X return 99; /* should never reach */
- X
- X} /* end function checkdir() */
- X
- X
- X
- X
- X/****************************/
- X/* Function close_outfile() */
- X/****************************/
- X
- Xvoid close_outfile()
- X{
- X static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- X long m_time;
- X int yr, mo, dy, hh, mm, ss, leap, days;
- X struct utimbuf tp;
- X# define YRBASE 1970
- X extern long timezone; /* seems ok for Atari if undefine __STRICT_ANSI__ */
- X /* [cjh] */
- X
- X/*---------------------------------------------------------------------------
- X If symbolic links are supported, allocate a storage area, put the uncom-
- X pressed "data" in it, and create the link. Since we know it's a symbolic
- X link to start with, we shouldn't have to worry about overflowing unsigned
- X ints with unsigned longs.
- X ---------------------------------------------------------------------------*/
- X
- X /* symlinks allowed on minix filesystems [cjh]
- X * Hopefully this will work properly... We won't bother to try if
- X * MiNT isn't present; the symlink should fail if we're on a TOS
- X * filesystem.
- X * BUG: should we copy the original file to the "symlink" if the
- X * link fails?
- X */
- X if (symlnk) {
- X unsigned ucsize = (unsigned)lrec.ucsize;
- X char *linktarget = (char *)malloc((unsigned)lrec.ucsize+1);
- X
- X fclose(outfile); /* close "data" file... */
- X outfile = fopen(filename, FOPR); /* ...and reopen for reading */
- X if (!linktarget || (fread(linktarget, 1, ucsize, outfile) != ucsize)) {
- X fprintf(stderr, "\nwarning: symbolic link (%s) failed\n",
- X filename);
- X if (linktarget)
- X free(linktarget);
- X fclose(outfile);
- X return;
- X }
- X fclose(outfile); /* close "data" file for good... */
- X unlink(filename); /* ...and delete it */
- X linktarget[ucsize] = '\0';
- X fprintf(stdout, "-> %s ", linktarget);
- X if (symlink(linktarget, filename)) /* create the real link */
- X perror("symlink error");
- X free(linktarget);
- X return; /* can't set time on symlinks */
- X }
- X
- X fclose(outfile);
- X
- X/*---------------------------------------------------------------------------
- X Change the file permissions from default ones to those stored in the
- X zipfile.
- X ---------------------------------------------------------------------------*/
- X
- X#ifndef NO_CHMOD
- X if (chmod(filename, 0xffff & pInfo->file_attr))
- X perror("chmod (file attributes) error");
- X#endif
- X
- X/*---------------------------------------------------------------------------
- X Convert from MSDOS-format local time and date to Unix-format 32-bit GMT
- X time: adjust base year from 1980 to 1970, do usual conversions from
- X yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-
- X light savings time differences.
- X ---------------------------------------------------------------------------*/
- X
- X yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE);
- X mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
- X dy = (lrec.last_mod_file_date & 0x1f) - 1;
- X hh = (lrec.last_mod_file_time >> 11) & 0x1f;
- X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- X ss = (lrec.last_mod_file_time & 0x1f) * 2;
- X
- X /* leap = # of leap yrs from YRBASE up to but not including current year */
- X leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
- X
- X /* how many days from YRBASE to this year? (& add expired days this year) */
- X days = (yr * 365) + (leap - 492) + yday[mo];
- X
- X /* if year is a leap year and month is after February, add another day */
- X if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
- X ++days; /* OK through 2199 */
- X
- X /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
- X m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
- X
- X /* adjust for local timezone */
- X /* This seems ok, if you undefine __STRICT_ANSI__; use tzset(). [cjh] */
- X tzset(); /* get `timezone' */
- X m_time += timezone; /* seconds WEST of GMT: add */
- X
- X /* adjust for daylight savings time (or local equivalent) */
- X if (localtime(&m_time)->tm_isdst)
- X m_time -= 60L * 60L; /* adjust for daylight savings time */
- X
- X /* set the file's access and modification times */
- X tp.actime = tp.modtime = m_time;
- X if (utime(filename, &tp))
- X fprintf(stderr, "warning: can't set the time for %s\n", filename);
- X
- X} /* end function close_outfile() */
- X
- X
- X
- X
- X#ifndef SFX
- X
- X/************************/
- X/* Function version() */
- X/************************/
- X
- Xvoid version()
- X{
- X extern char Far CompiledWith[];
- X#ifdef __TURBOC__
- X char buf[40];
- X#endif
- X
- X printf(LoadFarString(CompiledWith),
- X
- X#ifdef __GNUC__
- X "gcc ", __VERSION__,
- X#else
- X# if 0
- X "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
- X# else
- X# ifdef __TURBOC__
- X "Turbo C", (sprintf(buf, " (0x%04x = %d)", __TURBOC__, __TURBOC__), buf),
- X# else
- X "unknown compiler", "",
- X# endif
- X# endif
- X#endif
- X
- X#ifdef __MINT__
- X "Atari TOS/MiNT",
- X#else
- X "Atari TOS",
- X#endif
- X
- X#if defined(atarist) || defined(ATARIST)
- X " (Atari ST/TT/Falcon030)",
- X#else
- X "",
- X#endif
- X
- X#ifdef __DATE__
- X " on ", __DATE__
- X#else
- X "", ""
- X#endif
- X );
- X
- X} /* end function version() */
- X
- X#endif /* !SFX */
- END_OF_FILE
- if test 26647 -ne `wc -c <'unzip-5.12/atari/atari.c'`; then
- echo shar: \"'unzip-5.12/atari/atari.c'\" unpacked with wrong size!
- fi
- # end of 'unzip-5.12/atari/atari.c'
- fi
- if test -f 'unzip-5.12/match.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unzip-5.12/match.c'\"
- else
- echo shar: Extracting \"'unzip-5.12/match.c'\" \(10263 characters\)
- sed "s/^X//" >'unzip-5.12/match.c' <<'END_OF_FILE'
- X/*---------------------------------------------------------------------------
- X
- X match.c
- X
- X The match() routine recursively compares a string to a "pattern" (regular
- X expression), returning TRUE if a match is found or FALSE if not. This
- X version is specifically for use with unzip.c: as did the previous match()
- X routines from SEA and J. Kercheval, it leaves the case (upper, lower, or
- X mixed) of the string alone, but converts any uppercase characters in the
- X pattern to lowercase if indicated by the global var pInfo->lcflag (which
- X is to say, string is assumed to have been converted to lowercase already,
- X if such was necessary).
- X
- X GRR: reversed order of text, pattern in matche() (now same as match());
- X added ignore_case/ic flags, Case() macro.
- X
- X PaulK: replaced matche() with recmatch() from Zip, modified to have an
- X ignore_case argument; replaced test frame with simpler one.
- X
- X ---------------------------------------------------------------------------
- X
- X Copyright on recmatch() from Zip's util.c (although recmatch() was almost
- X certainly written by Mark Adler...ask me how I can tell :-) ):
- X
- X Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
- X Kai Uwe Rommel and Igor Mandrichenko.
- X
- X Permission is granted to any individual or institution to use, copy,
- X or redistribute this software so long as all of the original files are
- X included unmodified, that it is not sold for profit, and that this copy-
- X right notice is retained.
- X
- X ---------------------------------------------------------------------------
- X
- X Match the pattern (wildcard) against the string (fixed):
- X
- X match(string, pattern, ignore_case);
- X
- X returns TRUE if string matches pattern, FALSE otherwise. In the pattern:
- X
- X `*' matches any sequence of characters (zero or more)
- X `?' matches any single character
- X [SET] matches any character in the specified set,
- X [!SET] or [^SET] matches any character not in the specified set.
- X
- X A set is composed of characters or ranges; a range looks like ``character
- X hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
- X characters allowed in the [..] pattern construct. Other characters are
- X allowed (i.e., 8-bit characters) if your system will support them.
- X
- X To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
- X side or outside a [..] construct and match the character exactly, precede
- X it with a ``\'' (backslash).
- X
- X Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is
- X defined. See the DOSWILD section below for an explanation. Note also
- X that with VMSWILD defined, '%' is used instead of '?', and sets (ranges)
- X are delimited by () instead of [].
- X
- X ---------------------------------------------------------------------------*/
- X
- X
- X
- X/* define ToLower() in here (for Unix, define ToLower to be macro (using
- X * isupper()); otherwise just use tolower() */
- X#include "unzip.h"
- X
- X#if 0 /* this is not useful until it matches Amiga names insensitively */
- X#ifdef AMIGA /* some other platforms might also want to use this */
- X# define ANSI_CHARSET /* MOVE INTO UNZIP.H EVENTUALLY */
- X#endif
- X#endif /* 0 */
- X
- X#ifdef ANSI_CHARSET
- X# ifdef ToLower
- X# undef ToLower
- X# endif
- X /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */
- X# define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A)
- X# define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c)
- X#endif
- X#define Case(x) (ic? ToLower(x) : (x))
- X
- X#ifdef VMSWILD
- X# define WILDCHAR '%'
- X# define BEG_RANGE '('
- X# define END_RANGE ')'
- X#else
- X# define WILDCHAR '?'
- X# define BEG_RANGE '['
- X# define END_RANGE ']'
- X#endif
- X
- X#if 0 /* GRR: add this to unzip.h someday... */
- X#if !(defined(MSDOS) && defined(DOSWILD))
- X#define match(s,p,ic) (recmatch((uch *)p,(uch *)s,ic) == 1)
- Xint recmatch OF((uch *pattern, uch *string, int ignore_case));
- X#endif
- X#endif /* 0 */
- Xstatic int recmatch OF((uch *pattern, uch *string, int ignore_case));
- X
- X
- X
- X/* match() is a shell to recmatch() to return only Boolean values. */
- X
- Xint match(string, pattern, ignore_case)
- X char *string, *pattern;
- X int ignore_case;
- X{
- X#if (defined(MSDOS) && defined(DOSWILD))
- X char *dospattern;
- X int j = strlen(pattern);
- X
- X/*---------------------------------------------------------------------------
- X Optional MS-DOS preprocessing section: compare last three chars of the
- X wildcard to "*.*" and translate to "*" if found; else compare the last
- X two characters to "*." and, if found, scan the non-wild string for dots.
- X If in the latter case a dot is found, return failure; else translate the
- X "*." to "*". In either case, continue with the normal (Unix-like) match
- X procedure after translation. (If not enough memory, default to normal
- X match.) This causes "a*.*" and "a*." to behave as MS-DOS users expect.
- X ---------------------------------------------------------------------------*/
- X
- X if ((dospattern = (char *)malloc(j+1)) != NULL) {
- X strcpy(dospattern, pattern);
- X if (!strcmp(dospattern+j-3, "*.*")) {
- X dospattern[j-2] = '\0'; /* nuke the ".*" */
- X } else if (!strcmp(dospattern+j-2, "*.")) {
- X char *p = strchr(string, '.');
- X
- X if (p) { /* found a dot: match fails */
- X free(dospattern);
- X return 0;
- X }
- X dospattern[j-1] = '\0'; /* nuke the end "." */
- X }
- X j = recmatch((uch *)dospattern, (uch *)string, ignore_case);
- X free(dospattern);
- X return j == 1;
- X } else
- X#endif /* MSDOS && DOSWILD */
- X return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1;
- X}
- X
- X
- X
- Xstatic int recmatch(p, s, ic)
- X uch *p; /* sh pattern to match */
- X uch *s; /* string to which to match it */
- X int ic; /* true for case insensitivity */
- X/* Recursively compare the sh pattern p with the string s and return 1 if
- X * they match, and 0 or 2 if they don't or if there is a syntax error in the
- X * pattern. This routine recurses on itself no more deeply than the number
- X * of characters in the pattern. */
- X{
- X unsigned int c; /* pattern char or start of range in [-] loop */
- X
- X /* Get first character, the pattern for new recmatch calls follows */
- X c = *p++;
- X
- X /* If that was the end of the pattern, match if string empty too */
- X if (c == 0)
- X return *s == 0;
- X
- X /* '?' (or '%') matches any character (but not an empty string) */
- X if (c == WILDCHAR)
- X return *s ? recmatch(p, s + 1, ic) : 0;
- X
- X /* '*' matches any number of characters, including zero */
- X#ifdef AMIGA
- X if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
- X c = '*', p++;
- X#endif /* AMIGA */
- X if (c == '*') {
- X if (*p == 0)
- X return 1;
- X for (; *s; s++)
- X if ((c = recmatch(p, s, ic)) != 0)
- X return (int)c;
- X return 2; /* 2 means give up--match will return false */
- X }
- X
- X /* Parse and process the list of characters and ranges in brackets */
- X if (c == BEG_RANGE) {
- X int e; /* flag true if next char to be taken literally */
- X uch *q; /* pointer to end of [-] group */
- X int r; /* flag true to match anything but the range */
- X
- X if (*s == 0) /* need a character to match */
- X return 0;
- X p += (r = (*p == '!' || *p == '^')); /* see if reverse */
- X for (q = p, e = 0; *q; q++) /* find closing bracket */
- X if (e)
- X e = 0;
- X else
- X if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */
- X e = 1;
- X else if (*q == END_RANGE)
- X break;
- X if (*q != END_RANGE) /* nothing matches if bad syntax */
- X return 0;
- X for (c = 0, e = *p == '-'; p < q; p++) { /* go through the list */
- X if (e == 0 && *p == '\\') /* set escape flag if \ */
- X e = 1;
- X else if (e == 0 && *p == '-') /* set start of range if - */
- X c = *(p-1);
- X else {
- X unsigned int cc = Case(*s);
- X
- X if (*(p+1) != '-')
- X for (c = c ? c : *p; c <= *p; c++) /* compare range */
- X if ((unsigned)Case(c) == cc) /* typecast for MSC bug */
- X return r ? 0 : recmatch(q + 1, s + 1, ic);
- X c = e = 0; /* clear range, escape flags */
- X }
- X }
- X return r ? recmatch(q + 1, s + 1, ic) : 0; /* bracket match failed */
- X }
- X
- X /* if escape ('\'), just compare next character */
- X if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */
- X return 0;
- X
- X /* just a character--compare it */
- X return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0;
- X
- X} /* end function recmatch() */
- X
- X
- X
- X
- X
- Xint iswild(p) /* originally only used for stat()-bug workaround in */
- X char *p; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */
- X{ /* now used in process_zipfiles() as well */
- X for (; *p; ++p)
- X if (*p == '\\' && *(p+1))
- X ++p;
- X#ifdef VMS
- X else if (*p == '%' || *p == '*')
- X#else /* !VMS */
- X#ifdef AMIGA
- X else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[')
- X#else /* !AMIGA */
- X else if (*p == '?' || *p == '*' || *p == '[')
- X#endif /* ?AMIGA */
- X#endif /* ?VMS */
- X return TRUE;
- X
- X return FALSE;
- X
- X} /* end function iswild() */
- X
- X
- X
- X
- X
- X#ifdef TEST_MATCH
- X
- X#define put(s) {fputs(s,stdout); fflush(stdout);}
- X
- Xvoid main()
- X{
- X char pat[256], str[256];
- X
- X for (;;) {
- X put("Pattern (return to exit): ");
- X gets(pat);
- X if (!pat[0])
- X break;
- X for (;;) {
- X put("String (return for new pattern): ");
- X gets(str);
- X if (!str[0])
- X break;
- X printf("Case sensitive: %s insensitive: %s\n",
- X match(str, pat, 0) ? "YES" : "NO",
- X match(str, pat, 1) ? "YES" : "NO");
- X }
- X }
- X exit(0);
- X}
- X
- X#endif /* TEST_MATCH */
- END_OF_FILE
- if test 10263 -ne `wc -c <'unzip-5.12/match.c'`; then
- echo shar: \"'unzip-5.12/match.c'\" unpacked with wrong size!
- fi
- # end of 'unzip-5.12/match.c'
- fi
- if test -f 'unzip-5.12/unix/unzip.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unzip-5.12/unix/unzip.1'\"
- else
- echo shar: Extracting \"'unzip-5.12/unix/unzip.1'\" \(30113 characters\)
- sed "s/^X//" >'unzip-5.12/unix/unzip.1' <<'END_OF_FILE'
- X.\" Info-ZIP grants permission to any individual or institution to use, copy,
- X.\" or redistribute this software, so long as: (1) all of the original files
- X.\" are included; (2) it is not sold for profit; and (3) this notice is re-
- X.\" tained.
- X.\"
- X.\" unzip.1 by Greg Roelofs, Fulvio Marino, Jim van Zandt and others.
- X.\"
- X.\" =========================================================================
- X.\" define .Y macro (for user-command examples; normal Courier font):
- X.de Y
- X.ft CW
- X.in +4n
- X.nf
- X\&\\$1
- X.ft
- X.in
- X.fi
- X..
- X.\" =========================================================================
- X.TH UNZIP 1L "28 Aug 94 (v5.12)"
- X.SH NAME
- Xunzip \- list, test and extract compressed files in a ZIP archive
- X.PD
- X.\" =========================================================================
- X.SH SYNOPSIS
- X\fBunzip\fP [\fB\-Z\fP] [\fB\-cflptuvz\fP[\fBabjnoqsCLV$\fP]]
- X\fIfile\fP[\fI.zip\fP] [\fIfile(s)\fP\ .\|.\|.]
- X[\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] [\fB\-d\fP\ \fIexdir\fP]
- X.PD
- X.\" =========================================================================
- X.SH DESCRIPTION
- X\fIunzip\fP will list, test, or extract files from a ZIP archive, commonly
- Xfound on MS-DOS systems. The default behavior (with no options) is to extract
- Xinto the current directory (and subdirectories below it) all files from the
- Xspecified ZIP archive. A companion program, \fIzip\fP(1L), creates ZIP
- Xarchives; both programs are compatible with archives created by PKWARE's
- X\fIPKZIP\fP and \fIPKUNZIP\fP for MS-DOS, but in many cases the program
- Xoptions or default behaviors differ.
- X.PD
- X.\" =========================================================================
- X.SH ARGUMENTS
- X.TP
- X.IR file [ .zip ]
- XPath of the ZIP archive(s). If the file specification is a wildcard,
- Xeach matching file is processed in an order determined by the operating
- Xsystem (or file system). Only the filename can be a wildcard; the path
- Xitself cannot. Wildcard expressions are similar to Unix \fIegrep\fP(1)
- X(regular) expressions and may contain:
- X.RS
- X.IP *
- Xmatches a sequence of 0 or more characters
- X.IP ?
- Xmatches exactly 1 character
- X.IP [.\|.\|.]
- Xmatches any single character found inside the brackets; ranges are specified
- Xby a beginning character, a hyphen, and an ending character. If an exclamation
- Xpoint or a caret (`!' or `^') follows the left bracket, then the range of
- Xcharacters within the brackets is complemented (that is, anything \fIexcept\fP
- Xthe characters inside the brackets is considered a match).
- X.RE
- X.IP
- X(Be sure to quote any character which might otherwise be interpreted or
- Xmodified by the operating system, particularly under Unix and VMS.) If no
- Xmatches are found, the specification is assumed to be a literal filename;
- Xand if that also fails, the suffix \fC.zip\fP is appended. Note that
- Xself-extracting ZIP files are supported, as with any other ZIP archive;
- Xjust specify the \fC.exe\fP suffix (if any) explicitly.
- X.IP [\fIfile(s)\fP]
- XAn optional list of archive members to be processed, separated by spaces.
- X(VMS versions compiled with VMSCLI defined must delimit files with commas
- Xinstead. See \fB\-v\fP in \fBOPTIONS\fP below.)
- XRegular expressions (wildcards) may be used to match multiple members; see
- Xabove. Again, be sure to quote expressions that would otherwise be expanded
- Xor modified by the operating system.
- X.IP [\fB\-x\fP\ \fIxfile(s)\fP]
- XAn optional list of archive members to be excluded from processing.
- XSince wildcard characters match directory separators (`/'), this option
- Xmay be used to exclude any files which are in subdirectories. For
- Xexample, ``\fCunzip foo *.[ch] -x */*\fR'' would extract all C source files
- Xin the main directory, but none in any subdirectories. Without the \fB\-x\fP
- Xoption, all C source files in all directories within the zipfile would be
- Xextracted.
- X.IP [\fB\-d\fP\ \fIexdir\fP]
- XAn optional directory to which to extract files. By default, all files
- Xand subdirectories are recreated in the current directory; the \fB\-d\fP
- Xoption allows extraction in an arbitrary directory (always assuming one
- Xhas permission to write to the directory). This option need not appear
- Xat the end of the command line; it is also accepted immediately after the
- Xzipfile specification, or between the \fIfile(s)\fP and the \fB\-x\fP
- Xoption. The option and directory may
- Xbe concatenated without any white space between them, but note that this
- Xmay cause normal shell behavior to be suppressed. In particular,
- X``\fC\-d\ ~\fR'' (tilde) is expanded by Unix C shells into the name
- Xof the user's home directory, but ``\fC\-d~\fR'' is treated as a
- Xliteral subdirectory ``\fB~\fP'' of the current directory.
- X.\" =========================================================================
- X.SH OPTIONS
- XNote that, in order to support obsolescent hardware, \fIunzip\fP's usage
- Xscreen is limited to 22 or 23 lines and should therefore be considered a
- Xreminder of the basic \fIunzip\fP syntax rather than an exhaustive list
- Xof all possible flags.
- X.TP
- X.B \-Z
- X\fIzipinfo\fP(1L) mode. If the first option on the command line is \fB\-Z\fP,
- Xthe remaining options are taken to be \fIzipinfo\fP(1L) options. See the
- Xappropriate manual page for a description of these options.
- X.TP
- X.B \-c
- Xextract files to stdout/screen (``CRT''). This option is similar to the
- X\fB\-p\fP option except that the name of each file is printed as it is
- Xextracted, the \fB\-a\fP option is allowed, and ASCII-EBCDIC conversion
- Xis automatically performed if appropriate. This option is not listed in
- Xthe \fIunzip\fP usage screen.
- X.TP
- X.B \-f
- Xfreshen existing files, i.e., extract only those files which
- Xalready exist on disk and which are newer than the disk copies. By
- Xdefault \fIunzip\fP queries before overwriting, but the \fB\-o\fP option
- Xmay be used to suppress the queries. Note that under many operating systems,
- Xthe TZ (timezone) environment variable must be set correctly in order for
- X\fB\-f\fP and \fB\-u\fP to work properly (under Unix the variable is usually
- Xset automatically). The reasons for this are somewhat subtle but
- Xhave to do with the differences between DOS-format file times (always local
- Xtime) and Unix-format times (always in GMT) and the necessity to compare the
- Xtwo. A typical TZ value is ``PST8PDT'' (US Pacific time with automatic
- Xadjustment for Daylight Savings Time or ``summer time'').
- X.TP
- X.B \-l
- Xlist archive files (short format). The names, uncompressed file sizes and
- Xmodification dates and times of the specified files are printed, along
- Xwith totals for all files specified. In addition, the zipfile comment and
- Xindividual file comments (if any) are displayed. If a file was archived
- Xfrom a single-case file system (for example, the old MS-DOS FAT file system)
- Xand the \fB\-L\fP option was given, the filename is converted to lowercase
- Xand is prefixed with a caret (^).
- X.TP
- X.B \-p
- Xextract files to pipe (stdout). Nothing but the file data is sent to
- Xstdout, and the files are always extracted in binary format, just as they
- Xare stored (no conversions).
- X.TP
- X.B \-t
- Xtest archive files. This option extracts each specified file in memory
- Xand compares the CRC (cyclic redundancy check, an enhanced checksum) of
- Xthe expanded file with the original file's stored CRC value.
- X.TP
- X.B \-u
- Xupdate existing files and create new ones if needed. This option performs
- Xthe same function as the \fB\-f\fP option, extracting (with query) files
- Xwhich are newer than those with the same name on disk, and in addition it
- Xextracts those files which do not already exist on disk. See \fB\-f\fP
- Xabove for information on setting the timezone properly.
- X.TP
- X.B \-v
- Xbe verbose or print diagnostic version info. This option has evolved and
- Xnow behaves as both an option and a modifier. As an option it has two
- Xpurposes: when a zipfile is specified with no other options, \fB\-v\fP
- Xlists archive files verbosely, adding to the \fB\-l\fP info the compression
- Xmethod, compressed size, compression ratio and 32-bit CRC. When no zipfile
- Xis specified (that is, the complete command is simply ``\fCunzip -v\fR''), a
- Xdiagnostic screen is printed. In addition to the normal header with release
- Xdate and version, \fIunzip\fP lists the home Info-ZIP ftp site and where to
- Xfind a list of other ftp and non-ftp sites; the target operating system for
- Xwhich it was compiled, as well as (possibly) the hardware on which it was
- Xcompiled, the compiler and version used, and the compilation date; any special
- Xcompilation options which might affect the program's operation (see also
- X\fBDECRYPTION\fP below); and any options stored in environment variables
- Xwhich might do the same (see \fBENVIRONMENT OPTIONS\fP below). As a
- Xmodifier it works in conjunction with other options (e.g., \fB\-t\fP) to
- Xproduce more verbose or debugging output; this is not yet fully implemented
- Xbut will be in future releases.
- X.TP
- X.B \-z
- Xdisplay only the archive comment.
- X.PD
- X.\" =========================================================================
- X.SH MODIFIERS
- X.TP
- X.B \-a
- Xconvert text files. Ordinarily all files are extracted exactly as they
- Xare stored (as ``binary'' files). The \fB\-a\fP option causes files identified
- Xby \fIzip\fP as text files (those with the `t' label in \fIzipinfo\fP
- Xlistings, rather than `b') to be automatically extracted as such, converting
- Xline endings, end-of-file characters and the character set itself as necessary.
- X(For example, Unix files use line feeds (LFs) for end-of-line (EOL) and
- Xhave no end-of-file (EOF) marker; Macintoshes use carriage returns (CRs)
- Xfor EOLs; and most PC operating systems use CR+LF for EOLs and control-Z for
- XEOF. In addition, IBM mainframes and the Michigan Terminal System use EBCDIC
- Xrather than the more common ASCII character set, and NT supports Unicode.)
- XNote that \fIzip\fP's identification of text files is by no means perfect; some
- X``text'' files may actually be binary and vice versa. \fIunzip\fP therefore
- Xprints ``\fC[text]\fR'' or ``\fC[binary]\fR'' as a visual check for each file
- Xit extracts when using the \fB\-a\fP option. The \fB\-aa\fP option forces
- Xall files to be extracted as text, regardless of the supposed file type.
- X.TP
- X.B \-b
- Xtreat all files as binary (no text conversions). This is a shortcut for
- X\fB\-\-\-a\fP.
- X.TP
- X.B \-C
- Xmatch filenames case-insensitively. \fIunzip\fP's philosophy is ``you get
- Xwhat you ask for'' (this is also responsible for the \fB\-L\fP/\fB\-U\fP
- Xchange; see the relevant options below). Because some filesystems are fully
- Xcase-sensitive (notably those under the Unix operating system) and because
- Xboth ZIP archives and \fIunzip\fP itself are portable across platforms,
- X\fIunzip\fP's default behavior is to match both wildcard and literal filenames
- Xcase-sensitively. That is, specifying ``\fCmakefile\fR'' on the command line
- Xwill \fIonly\fP match ``makefile'' in the archive, not ``Makefile'' or
- X``MAKEFILE'' (and similarly for wildcard specifications). Since this does
- Xnot correspond to the behavior of many other operating/file systems (for
- Xexample, OS/2 HPFS which preserves mixed case but is not sensitive to it),
- Xthe \fB\-C\fP option may be used to force all filename matches to be
- Xcase-insensitive. In the example above, all three files would then match
- X``\fCmakefile\fR'' (or ``\fCmake*\fR'', or similar). The \fB\-C\fP option
- Xaffects files in both the normal file list and the excluded-file list (xlist).
- X.TP
- X.B \-j
- Xjunk paths. The archive's directory structure is not recreated; all files
- Xare deposited in the extraction directory (by default, the current one).
- X.TP
- X.B \-L
- Xconvert to lowercase any filename originating on an uppercase-only operating
- Xsystem or filesystem. (This was \fIunzip\fP's default behavior in releases
- Xprior to 5.11; the new default behavior is identical to the old behavior with
- Xthe \fB\-U\fP option, which is now obsolete and will be removed in a future
- Xrelease.) Depending on the archiver, files archived under single-case
- Xfilesystems (VMS, old MS-DOS FAT, etc.) may be stored as all-uppercase names;
- Xthis can be ugly or inconvenient when extracting to a case-preserving
- Xfilesystem such as OS/2 HPFS or a case-sensitive one such as under
- XUnix. By default \fIunzip\fP lists and extracts such filenames exactly as
- Xthey're stored (excepting truncation, conversion of unsupported characters,
- Xetc.); this option causes the names of all files from certain systems to be
- Xconverted to lowercase.
- X.TP
- X.B \-n
- Xnever overwrite existing files. If a file already exists, skip the extraction
- Xof that file without prompting. By default \fIunzip\fP queries before
- Xextracting any file which already exists; the user may choose to overwrite
- Xonly the current file, overwrite all files, skip extraction of the current
- Xfile, skip extraction of all existing files, or rename the current file.
- X.TP
- X.B \-o
- Xoverwrite existing files without prompting. This is a dangerous option, so
- Xuse it with care. (It is often used with \fB\-f\fP, however.)
- X.TP
- X.B \-q
- Xperform operations quietly (\fB\-qq\fP = even quieter). Ordinarily \fIunzip\fP
- Xprints the names of the files it's extracting or testing, the extraction
- Xmethods, any file or zipfile comments which may be stored in the archive,
- Xand possibly a summary when finished with each archive. The \fB\-q\fP[\fBq\fP]
- Xoptions suppress the printing of some or all of these messages.
- X.TP
- X.B \-s
- X[OS/2, NT, MS-DOS] convert spaces in filenames to underscores. Since all PC
- Xoperating systems allow spaces in filenames, \fIunzip\fP by default extracts
- Xfilenames with spaces intact (e.g., ``\fCEA\ DATA.\ SF\fR''). This can be
- Xawkward, however, since MS-DOS in particular does not gracefully support
- Xspaces in filenames. Conversion of spaces to underscores can eliminate the
- Xawkwardness in some cases.
- X.TP
- X.B \-U
- X(obsolete; to be removed in a future release) leave filenames uppercase if
- Xcreated under MS-DOS, VMS, etc. See \fB\-L\fP above.
- X.TP
- X.B \-V
- Xretain (VMS) file version numbers. VMS files can be stored with a version
- Xnumber, in the format \fCfile.ext;##\fP. By default the ``\fC;##\fR'' version
- Xnumbers are stripped, but this option allows them to be retained. (On
- Xfilesystems which limit filenames to particularly short lengths, the version
- Xnumbers may be truncated or stripped regardless of this option.)
- X.TP
- X.B \-X
- X[VMS] restore owner/protection info (may require system privileges). Ordinary
- Xfile attributes are always restored, but this option allows UICs to be restored
- Xas well. [The next version of \fIunzip\fP will support Unix UID/GID info as
- Xwell, and possibly NT permissions.]
- X.TP
- X.B \-$
- X[MS-DOS, OS/2, NT, Amiga] restore the volume label if the extraction medium is
- Xremovable (e.g., a diskette). Doubling the option (\fB\-$$\fP) allows fixed
- Xmedia (hard disks) to be labelled as well. By default, volume labels are
- Xignored.
- X.PD
- X.\" =========================================================================
- X.SH ENVIRONMENT OPTIONS
- X\fIunzip\fP's default behavior may be modified via options placed in
- Xan environment variable. This can be done with any option, but it
- Xis probably most useful with the \fB\-a\fP, \fB\-L\fP, \fB\-C\fP, \fB\-q\fP,
- X\fB\-o\fP, or \fB\-n\fP modifiers: make \fIunzip\fP auto-convert text
- Xfiles by default, make it convert filenames from uppercase systems to
- Xlowercase, make it match names case-insensitively, make it quieter,
- Xor make it always overwrite or never overwrite files as it extracts
- Xthem. For example, to make \fIunzip\fP act as quietly as possible, only
- Xreporting errors, one would use one of the following commands:
- X.LP
- X.DT
- X.ft CW
- X.in +4n
- X.ta \w'UNZIP=\-qq; export UNZIP'u+4n
- X.in
- X.ft
- X.PD 0
- X.Y "UNZIP=\-qq; export UNZIP\t\fRUnix Bourne shell"
- X.Y "setenv UNZIP \-qq\t\fRUnix C shell"
- X.Y "set UNZIP=\-qq\t\fROS/2 or MS-DOS"
- X.Y "define UNZIP_OPTS ""\-qq""\t\fRVMS (quotes for \fIlowercase\fP)"
- X.PD
- X.LP
- XEnvironment options are, in effect, considered to be just like any other
- Xcommand-line options, except that they are effectively the first options
- Xon the command line. To override an environment option, one may use the
- X``minus operator'' to remove it. For instance, to override one of the
- Xquiet-flags in the example above, use the command
- X.LP
- X.Y "unzip \-\-q[\fIother options\fC] zipfile"
- X.LP
- XThe first hyphen is the normal
- Xswitch character, and the second is a minus sign, acting on the q option.
- XThus the effect here is to cancel one quantum of quietness. To cancel
- Xboth quiet flags, two (or more) minuses may be used:
- X.LP
- X.PD 0
- X.Y "unzip \-t\-\-q zipfile"
- X.Y "unzip \-\-\-qt zipfile"
- X.PD
- X.LP
- X(the two are equivalent). This may seem awkward
- Xor confusing, but it is reasonably intuitive: just ignore the first
- Xhyphen and go from there. It is also consistent with the behavior of
- XUnix \fInice\fP(1).
- X.LP
- XAs suggested by the examples above, the default variable names are UNZIP_OPTS
- Xfor VMS (where the symbol used to install \fIunzip\fP as a foreign command
- Xwould otherwise be confused with the environment variable), and UNZIP
- Xfor all other operating systems. For compatibility with \fIzip\fP(1L),
- XUNZIPOPT is also accepted (don't ask). If both UNZIP and UNZIPOPT
- Xare defined, however, UNZIP takes precedence. \fIunzip\fP's diagnostic
- Xoption (\fB\-v\fP with no zipfile name) can be used to check the values
- Xof all four possible \fIunzip\fP and \fIzipinfo\fP environment variables.
- X.LP
- XThe timezone variable (TZ) should be set according to the local timezone
- Xin order for the \fB\-f\fP and \fB\-u\fP to operate correctly. See the
- Xdescription of \fB\-f\fP above for details. This variable may also be
- Xnecessary in order for timestamps on extracted files to be set correctly.
- X.PD
- X.\" =========================================================================
- X.SH DECRYPTION
- XEncrypted archives are fully supported by Info-ZIP software, but due to
- XUnited States export restrictions, the encryption and decryption sources
- Xare not packaged with the regular \fIunzip\fP and \fIzip\fP distributions.
- XSince the crypt sources were written by Europeans, however, they are
- Xfreely available at sites throughout the world; see the file ``Where'' in
- Xany Info-ZIP source or binary distribution for locations both inside and
- Xoutside the US.
- X.LP
- XBecause of the separate distribution, not all compiled versions of \fIunzip\fP
- Xsupport decryption. To check a version for crypt support, either attempt to
- Xtest or extract an encrypted archive, or else check \fIunzip\fP's diagnostic
- Xscreen (see the \fB\-v\fP option above) for ``\fC[decryption]\fR'' as one of
- Xthe special compilation options.
- X.LP
- XThere are no runtime options for decryption; if a zipfile member is encrypted,
- X\fIunzip\fP will prompt for the password without echoing what is typed.
- X\fIunzip\fP continues to use the same password as long as it appears to be
- Xvalid; it does this by testing a 12-byte header. The correct password will
- Xalways check out against the header, but there is a 1-in-256 chance that an
- Xincorrect password will as well. (This is a security feature of the PKWARE
- Xzipfile format; it helps prevent brute-force attacks which might otherwise
- Xgain a large speed advantage by testing only the header.) In the case that
- Xan incorrect password is
- Xgiven but it passes the header test anyway, either an incorrect CRC will be
- Xgenerated for the extracted data or else \fIunzip\fP will fail during the
- Xextraction because the ``decrypted'' bytes do not constitute a valid
- Xcompressed data stream.
- X.LP
- XIf the first password fails the header check on some file, \fIunzip\fP will
- Xprompt for another password, and so on until all files are extracted. If
- Xa password is not known, entering a null password (that is, just a carriage
- Xreturn) is taken as a signal to skip all further prompting. Only unencrypted
- Xfiles in the archive(s) will thereafter be extracted. (Actually that's not
- Xquite true; older versions of \fIzip\fP(1L) and \fIzipcloak\fP(1L) allowed
- Xnull passwords, so \fIunzip\fP checks each encrypted file to see if the null
- Xpassword works. This may result in ``false positives'' and extraction
- Xerrors, as noted above.)
- X.LP
- XNote that there is presently no way to avoid interactive decryption. This
- Xis another security feature: plaintext passwords given on the command line
- Xor stored in files constitute a risk because they may be seen by others.
- XFuture releases may (under protest, with great disapproval) support such
- Xshenanigans.
- X.PD
- X.\" =========================================================================
- X.SH EXAMPLES
- XTo use \fIunzip\fP to extract all members of the archive \fIletters.zip\fP
- Xinto the current directory and subdirectories below it, creating any
- Xsubdirectories as necessary:
- X.LP
- X.Y "unzip letters"
- X.LP
- XTo extract all members of \fIletters.zip\fP into the current directory only:
- X.LP
- X.Y "unzip -j letters"
- X.LP
- XTo test \fIletters.zip\fP, printing only a summary message indicating
- Xwhether the archive is OK or not:
- X.LP
- X.Y "unzip -tq letters"
- X.LP
- XTo test \fIall\fP zipfiles in the current directory, printing only the
- Xsummaries:
- X.LP
- X.Y "unzip -tq \e*.zip"
- X.LP
- X(The backslash before the asterisk is only required if the shell expands
- Xwildcards, as in Unix; double quotes could have been used instead, as in
- Xthe source examples below.)\ \ To extract to standard output all members of
- X\fIletters.zip\fP whose names end in \fI.tex\fP, auto-converting to the
- Xlocal end-of-line convention and piping the output into \fImore\fP(1):
- X.LP
- X.Y "unzip \-ca letters \e*.tex | more"
- X.LP
- XTo extract the binary file \fIpaper1.dvi\fP to standard output and pipe it
- Xto a printing program:
- X.LP
- X.Y "unzip \-p articles paper1.dvi | dvips"
- X.LP
- XTo extract all FORTRAN and C source files--*.f, *.c, *.h, and Makefile--into
- Xthe /tmp directory:
- X.LP
- X.Y "unzip source.zip ""*.[fch]"" Makefile -d /tmp"
- X.LP
- X(the double quotes are necessary only in Unix and only if globbing is turned
- Xon). To extract all FORTRAN and C source files, regardless of case (e.g.,
- Xboth *.c and *.C, and any makefile, Makefile, MAKEFILE or similar):
- X.LP
- X.Y "unzip \-C source.zip ""*.[fch]"" makefile -d /tmp"
- X.LP
- XTo extract any such files but convert any uppercase MS-DOS or VMS names to
- Xlowercase and convert the line-endings of all of the files to the local
- Xstandard (without respect to any files which might be marked ``binary''):
- X.LP
- X.Y "unzip \-aaCL source.zip ""*.[fch]"" makefile -d /tmp"
- X.LP
- XTo extract only newer versions of the files already in the current
- Xdirectory, without querying (NOTE: be careful of unzipping in one timezone a
- Xzipfile created in another--ZIP archives to date contain no timezone
- Xinformation, and a ``newer'' file from an eastern timezone may, in fact, be
- Xolder):
- X.LP
- X.Y "unzip \-fo sources"
- X.LP
- XTo extract newer versions of the files already in the current directory and
- Xto create any files not already there (same caveat as previous example):
- X.LP
- X.Y "unzip \-uo sources"
- X.LP
- XTo display a diagnostic screen showing which \fIunzip\fP and \fIzipinfo\fP
- Xoptions are stored in environment variables, whether decryption support was
- Xcompiled in, the compiler with which \fIunzip\fP was compiled, etc.:
- X.LP
- X.Y "unzip \-v"
- X.LP
- XIn the last five examples, assume that UNZIP or UNZIP_OPTS is set to -q.
- XTo do a singly quiet listing:
- X.LP
- X.Y "unzip \-l file.zip"
- X.LP
- XTo do a doubly quiet listing:
- X.LP
- X.Y "unzip \-ql file.zip"
- X.LP
- X(Note that the ``\fC.zip\fR'' is generally not necessary.) To do a standard
- Xlisting:
- X.LP
- X.PD 0
- X.Y "unzip \-\-ql file.zip"
- X.LP
- Xor
- X.Y "unzip \-l\-q file.zip"
- X.LP
- Xor
- X.Y "unzip \-l\-\-q file.zip\t\fR(extra minuses don't hurt)"
- X.PD
- X.\" =========================================================================
- X.SH TIPS
- XThe current maintainer, being a lazy sort, finds it very useful to define
- Xa pair of aliases: \fCtt\fP for ``\fCunzip \-tq\fR'' and \fCii\fP for
- X``\fCunzip \-Z\fR'' (or ``\fCzipinfo\fR''). One may then simply type
- X``\fCtt zipfile\fR'' to test an archive, something which is worth making a
- Xhabit of doing. With luck \fIunzip\fP will report ``\fCNo errors detected
- Xin zipfile.zip\fP,'' after which one may breathe a sigh of relief.
- X.LP
- XThe maintainer also finds it useful to set the UNZIP environment variable
- Xto ``\fC\-aL\fR'' and is tempted to add ``\fC\-C\fR'' as well. His ZIPINFO
- Xvariable is set to ``\fC\-z\fR''.
- X.PD
- X.\" =========================================================================
- X.SH DIAGNOSTICS
- XThe exit status (or error level) approximates the exit codes defined by PKWARE
- Xand takes on the following values, except under VMS:
- X.RS
- X.IP 0
- Xnormal; no errors or warnings detected.
- X.IP 1
- Xone or more warning errors were encountered, but processing completed
- Xsuccessfully anyway. This includes zipfiles where one or more files
- Xwas skipped due to unsupported compression method or encryption with an
- Xunknown password.
- X.IP 2
- Xa generic error in the zipfile format was detected. Processing may have
- Xcompleted successfully anyway; some broken zipfiles created by other
- Xarchivers have simple work-arounds.
- X.IP 3
- Xa severe error in the zipfile format was detected. Processing probably
- Xfailed immediately.
- X.IP 4-8
- X\fIunzip\fP was unable to allocate memory for one or more buffers.
- X.IP 9
- Xthe specified zipfiles were not found.
- X.IP 10
- Xinvalid options were specified on the command line.
- X.IP 11
- Xno matching files were found.
- X.IP 50
- Xthe disk is (or was) full during extraction.
- X.IP 51
- Xthe end of the ZIP archive was encountered prematurely.
- X.RE
- X.LP
- XVMS interprets standard Unix (or PC) return values as other, scarier-looking
- Xthings, so by default \fIunzip\fP always returns 0 (which reportedly gets
- Xconverted into a VMS status of 1--i.e., success). There are two compilation
- Xoptions available to modify or expand upon this behavior: defining
- XRETURN_CODES results in a human-readable explanation of what the real
- Xerror status was (but still with a faked ``success'' exit value), while
- Xdefining RETURN_SEVERITY causes \fIunzip\fP to exit with a ``real'' VMS
- Xstatus. The latter behavior will become the default in future
- Xversions unless it is found to conflict with officially defined VMS codes.
- XThe current mapping is as follows: 1 (success) for normal exit, 0x7fff0001
- Xfor warning errors, and (0x7fff000? + 16*normal_unzip_exit_status) for all
- Xother errors, where the `?' is 2 (error) for \fIunzip\fP values 2 and 9-11,
- Xand 4 (fatal error) for the remaining ones (3-8, 50, 51). Check the
- X``\fCunzip \-v\fR'' output to see whether RETURN_SEVERITY was defined at
- Xcompilation time.
- X.PD
- X.\" =========================================================================
- X.SH BUGS
- XWhen attempting to extract a corrupted archive, \fIunzip\fP may go into
- Xan infinite loop and, if not stopped quickly enough, fill all available disk
- Xspace. Compiling with CHECK_EOF should fix this problem for all zipfiles,
- Xbut the option was introduced too late in the testing process to be made
- Xthe default behavior. Future versions will be robust enough to fail
- Xgracefully on damaged archives. Check the ``\fCunzip \-v\fR'' output to
- Xsee whether CHECK_EOF was defined during compilation.
- X.LP
- X[MS-DOS] When extracting or testing files from an archive on a defective
- Xfloppy diskette, if the ``Fail'' option is chosen from DOS's ``Abort, Retry,
- XFail?'' message, \fIunzip\fP may hang the system, requiring a reboot. Instead,
- Xpress control-C (or control-Break) to terminate \fIunzip\fP.
- X.LP
- XUnder DEC Ultrix, \fIunzip\fP will sometimes fail on long zipfiles (bad CRC,
- Xnot always reproducible). This is apparently due either to a hardware bug
- X(cache memory) or an operating system bug (improper handling of page faults?).
- X.LP
- XDates and times of stored directories are not restored.
- X.LP
- X[OS/2] Extended attributes for existing directories are never updated. This
- Xis a limitation of the operating system; \fIunzip\fP has no way to determine
- Xwhether the stored attributes are newer or older than the existing ones.
- X.LP
- X[VMS] When extracting to another directory, only the \fI[.foo]\fP syntax is
- Xaccepted for the \fB\-d\fP option; the simple Unix \fIfoo\fP syntax is
- Xsilently ignored (as is the less common VMS \fIfoo.dir\fP syntax).
- X.LP
- X[VMS] When the file being extracted already exists, \fIunzip\fP's query only
- Xallows skipping, overwriting or renaming; there should additionally be a
- Xchoice for creating a new version of the file. In fact, the ``overwrite''
- Xchoice does create a new version; the old version is not overwritten or
- Xdeleted.
- X.PD
- X.\" =========================================================================
- X.SH SEE ALSO
- X\fIfunzip\fP(1L), \fIzip\fP(1L), \fIzipcloak\fP(1L), \fIzipgrep\fP(1L),
- X\fIzipinfo\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L)
- X.PD
- X.\" =========================================================================
- X.SH AUTHORS
- XThe primary Info-ZIP authors (current zip-bugs workgroup) are: Jean-loup
- XGailly (Zip); Greg R. Roelofs (UnZip); Mark Adler (decompression, fUnZip);
- XKai Uwe Rommel (OS/2); Igor Mandrichenko and Hunter Goatley (VMS); John Bush
- Xand Paul Kienitz (Amiga); Antoine Verheijen (Macintosh); Chris Herborth
- X(Atari); Henry Gessau (NT); Karl Davis, Sergio Monesi and Evan Shattock
- X(Acorn Archimedes); and Robert Heath (Windows). The author of the original
- Xunzip code upon which Info-ZIP's is based was Samuel H. Smith; Carl Mascott
- Xdid the first Unix port; and David P. Kirschbaum organized and led Info-ZIP
- Xin its early days. The full list of contributors to UnZip has grown quite
- Xlarge; please refer to the CONTRIBS file in the UnZip source distribution
- Xfor a relatively complete version.
- X.PD
- X.\" =========================================================================
- X.SH VERSIONS
- X.ta \w'vx.xxnn'u +\w'fall 1989'u+3n
- X.PD 0
- X.IP "v1.2\t15 Mar 89" \w'\t\t'u
- XSamuel H. Smith
- X.IP "v2.0\t\ 9 Sep 89"
- XSamuel H. Smith
- X.IP "v2.x\tfall 1989"
- Xmany Usenet contributors
- X.IP "v3.0\t\ 1 May 90"
- XInfo-ZIP (DPK, consolidator)
- X.IP "v3.1\t15 Aug 90"
- XInfo-ZIP (DPK, consolidator)
- X.IP "v4.0\t\ 1 Dec 90"
- XInfo-ZIP (GRR, maintainer)
- X.IP "v4.1\t12 May 91"
- XInfo-ZIP
- X.IP "v4.2\t20 Mar 92"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.IP "v5.0\t21 Aug 92"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.IP "v5.01\t15 Jan 93"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.IP "v5.1\t\ 7 Feb 94"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.IP "v5.11\t\ 2 Aug 94"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.IP "v5.12\t28 Aug 94"
- XInfo-ZIP (zip-bugs subgroup, GRR)
- X.PD
- END_OF_FILE
- if test 30113 -ne `wc -c <'unzip-5.12/unix/unzip.1'`; then
- echo shar: \"'unzip-5.12/unix/unzip.1'\" unpacked with wrong size!
- fi
- # end of 'unzip-5.12/unix/unzip.1'
- fi
- echo shar: End of archive 12 \(of 20\).
- cp /dev/null ark12isdone
- 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...
-