michaele@vice.ICO.TEK.COM (Michael Enkelis) (05/30/89)
Do to requests, I am reposting unzipbsd at patch level 4. This has been tested on a BSD 4.3 system (VAX 8xxx cpu) and the IFDEF's are in place for MSDOS or XENIX (? SYS-V ?). Patchlevel 4: This release has a "patchlevel.h" file to help keep track of versions, and will display the patchlevel in the long help screen. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # patchlevel.h # unzipbsd.c # crc32.c # This archive created: Tue May 30 09:32:46 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile'" '(917 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else sed 's/^ X//' << \SHAR_EOF > 'Makefile' X# Makefile for unzipbsd X X X# "make unzip" -- makes unzip in current directory X# "make install" -- makes unzip, then moves it into DESTDIR defined below X# "make clean" -- deletes object files and executable unzip from current dir X# "make shar" -- make a SHell ARchive X# "make arc" -- make a DOS archive X X# Directory where we want to move executable unzip on "make install" XDESTDIR=/usr/public X X# CFLAGS are flags for the C compiler. LDFLAGS are flags for the loader. XCFLAGS= -O X# This is used for DBX X#CFLAGS= -g X XLDFLAGS= -s X XCC=cc X X.c.o: X $(CC) -c $(CFLAGS) $*.c X XOBJS = unzipbsd.o crc32.o X Xunzip: $(OBJS) X cc $(LDFLAGS) -o unzip $(OBJS) X Xunzip.o: unzip.c X Xcrc32.o: crc32.c X Xinstall: unzip X mv unzip $(DESTDIR)/unzip X Xclean: X /bin/rm -f $(OBJS) core unzip X Xshar: X @shar -a Makefile patchlevel.h unzipbsd.c crc32.c > unzipbsd.shar X Xarc: X @arc -a unzipbsd.arc Makefile patchlevel.h unzipbsd.c crc32.c X SHAR_EOF if test 917 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 917 characters)' fi fi # end of overwriting check echo shar: extracting "'patchlevel.h'" '(16 characters)' if test -f 'patchlevel.h' then echo shar: will not over-write existing file "'patchlevel.h'" else sed 's/^ X//' << \SHAR_EOF > 'patchlevel.h' X#define PATCH 4 SHAR_EOF if test 16 -ne "`wc -c < 'patchlevel.h'`" then echo shar: error transmitting "'patchlevel.h'" '(should have been 16 characters)' fi fi # end of overwriting check echo shar: extracting "'unzipbsd.c'" '(30392 characters)' if test -f 'unzipbsd.c' then echo shar: will not over-write existing file "'unzipbsd.c'" else sed 's/^ X//' << \SHAR_EOF > 'unzipbsd.c' X X/* X * Copyright 1989 Samuel H. Smith; All rights reserved X * X * Do not distribute modified versions without my permission. X * Do not remove or alter this notice or any other copyright notice. X * If you use this in your own program you must distribute source code. X * Do not use any of this in a commercial product. X * X */ X X/* X * UnZip - A simple zipfile extract utility X * X * To compile: X * tcc -B -O -Z -G -mc unzip.c ;turbo C 2.0, compact model X * X */ X X#include "patchlevel.h" X#define VERSION "1.2" X Xtypedef unsigned char byte; /* code assumes UNSIGNED bytes */ Xtypedef long longint; Xtypedef unsigned word; Xtypedef char boolean; X X#define STRSIZ 256 X X#include <stdio.h> X /* this is your standard header for all C compiles */ X X#ifdef MSDOS || M_XENIX X#include <stdlib.h> X /* this include defines various standard library prototypes */ X#endif X X X/* X * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180 X * X */ X X X/* ----------------------------------------------------------- */ X/* X * Zipfile layout declarations X * X */ X X Xchar local_file_header_signature[] = {0x50,0x4b,0x03,0x04}; X X Xtypedef struct local_file_header { X word version_needed_to_extract; X word general_purpose_bit_flag; X word compression_method; X word last_mod_file_time; X word last_mod_file_date; X longint crc32; X longint compressed_size; X longint uncompressed_size; X word filename_length; X word extra_field_length; X} local_file_header; X X Xchar central_file_header_signature[] = {0x50,0x4b,0x01,0x02}; X X Xtypedef struct central_directory_file_header { X word version_made_by; X word version_needed_to_extract; X word general_purpose_bit_flag; X word compression_method; X word last_mod_file_time; X word last_mod_file_date; X longint crc32; X longint compressed_size; X longint uncompressed_size; X word filename_length; X word extra_field_length; X word file_comment_length; X word disk_number_start; X word internal_file_attributes; X longint external_file_attributes; X longint relative_offset_local_header; X} central_directory_file_header; X X Xchar end_central_dir_signature[] = {0x50,0x4b,0x05,0x06}; X X Xtypedef struct end_central_dir_record { X word number_this_disk; X word number_disk_with_start_central_directory; X word total_entries_central_dir_on_this_disk; X word total_entries_central_dir; X longint size_central_directory; X longint offset_start_central_directory; X word zipfile_comment_length; X} end_central_dir_record; X X X X/* ----------------------------------------------------------- */ X/* X * input file variables X * X */ X X#define INBUFSIZ 0x2000 Xbyte *inbuf; /* input file buffer - any size is legal */ Xbyte *inptr; Xbyte *comment; X Xint incnt; Xunsigned bitbuf; Xint bits_left; Xboolean zipeof; X Xint zipfd; Xchar zipfn[STRSIZ]; Xlocal_file_header lrec; X X X/* ----------------------------------------------------------- */ X/* X * output stream variables X * X */ X X#define OUTBUFSIZ 0x6000 Xbyte *outbuf; /* buffer for rle look-back */ Xbyte *outptr; X Xlongint outpos; /* absolute position in outfile */ Xint outcnt; /* current position in outbuf */ X Xint outfd; Xchar filename[STRSIZ]; Xchar extra[STRSIZ]; X X#define DLE 144 X X X/* ----------------------------------------------------------- */ X/* X * shrink/reduce working storage X * X */ X Xint factor; Xbyte followers[256][64]; Xbyte Slen[256]; X X#define max_bits 13 X#define init_bits 9 X#define hsize 8192 X#define first_ent 257 X#define clear 256 X Xtypedef int hsize_array_integer[hsize+1]; Xtypedef byte hsize_array_byte[hsize+1]; X Xhsize_array_integer prefix_of; Xhsize_array_byte suffix_of; Xhsize_array_byte stack; X Xint codesize; Xint maxcode; Xint free_ent; Xint maxcodemax; Xint offset; Xint sizex; X X X X/* ============================================================= */ X/* X * Host operating system details X * X */ X X#include <string.h> X /* this include defines strcpy, strcmp, etc. */ X X#ifdef MSDOS || M_XENIX X#include <io.h> X /* X * this include file defines X * struct ftime ... (* file time/date stamp info *) X * int setftime (int handle, struct ftime *ftimep); X * #define SEEK_CUR 1 (* lseek() modes *) X * #define SEEK_END 2 X * #define SEEK_SET 0 X */ X#else X#include <sys/file.h> X /* X * this include file defines X * #define L_SET 0 (* Seek to absolute record *) X */ X#define SEEK_SET L_SET X#endif X X X X#ifdef MSDOS || M_XENIX X#include <fcntl.h> X /* X * this include file defines X * #define O_BINARY 0x8000 (* no cr-lf translation *) X * as used in the open() standard function X */ X#ifndef L_SET X#define L_SET 1 X#endif X#endif X X#ifndef O_BINARY X#define O_BINARY 0 /* BSD don't have a Open_BINARY mode */ X#endif X X#include <sys/types.h> X#include <sys/stat.h> X /* X * this include file defines X * #define S_IREAD 0x0100 (* owner may read *) X * #define S_IWRITE 0x0080 (* owner may write *) X * as used in the creat() standard function X */ X Xvoid set_file_time() X /* X * set the output file date/time stamp according to information from the X * zipfile directory record for this file X */ X{ X/* X * On a BSD system, You can't change the creation date/time X * (at least i think so) so for now, skip this code. X */ X#ifdef MSDOS || M_XENIX X union { X struct ftime ft; /* system file time record */ X struct { X word ztime; /* date and time words */ X word zdate; /* .. same format as in .ZIP file */ X } zt; X } td; X X /* X * set output file date and time - this is optional and can be X * deleted if your compiler does not easily support setftime() X */ X X td.zt.ztime = lrec.last_mod_file_time; X td.zt.zdate = lrec.last_mod_file_date; X X setftime(outfd, &td.ft); X#endif X} X X/* X * Some defines to use the GETOPT functions X * that are on most systems, even TURBO-C has these. X */ X#define USE_GETOPT /* Use the GETOPT package */ Xint extract = 1; /* Extract contents */ Xint debugging = 0; /* debug enable */ Xint verbose = 0; /* be verbose */ Xint list_zip = 0; /* list contents only */ Xint test_zip = 0; /* test CRC's only */ X Xlong crc32val; /* The CRC value we calculate */ Xint numbad =0; Xint Total_files =0; Xlong Total_bytes =0; Xlong Total_length =0; X X/* ============================================================= */ X Xint create_output_file() X /* return non-0 if creat failed */ X{ X if (!extract) X return 0; X X /* create the output file with READ and WRITE permissions */ X outfd = creat(filename, S_IWRITE | S_IREAD); X if (outfd < 1) { X printf("Can't create output: %s\n", filename); X return 1; X } X X /* X * close the newly created file and reopen it in BINARY mode to X * disable all CR/LF translations X */ X close(outfd); X outfd = open(filename, O_RDWR | O_BINARY); X X /* write a single byte at EOF to pre-allocate the file */ X lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET); X write(outfd, "?", 1); X lseek(outfd, 0L, SEEK_SET); X return 0; X} X X Xint open_input_file() X /* return non-0 if creat failed */ X{ X /* X * open the zipfile for reading and in BINARY mode to prevent cr/lf X * translation, which would corrupt the bitstreams X */ X X zipfd = open(zipfn, O_RDONLY | O_BINARY); X if (zipfd < 1) { X printf("Can't open input file: %s\n", zipfn); X return (1); X } X return 0; X} X X Xint FillBuffer() X /* fill input buffer if possible */ X{ X int readsize; X X if (lrec.compressed_size <= 0) X return incnt = 0; X X if (lrec.compressed_size > INBUFSIZ) X readsize = INBUFSIZ; X else X readsize = (int) lrec.compressed_size; X incnt = read(zipfd, inbuf, readsize); X X lrec.compressed_size -= incnt; X inptr = inbuf; X return incnt--; X} X Xint ReadByte(x) Xunsigned *x; X /* read a byte; return 8 if byte available, 0 if not */ X{ X if (incnt-- == 0) X if (FillBuffer() == 0) X return 0; X X *x = *inptr++; X return 8; X} X X X/* ------------------------------------------------------------- */ Xstatic unsigned mask_bits[] = X {0, 0x0001, 0x0003, 0x0007, 0x000f, X 0x001f, 0x003f, 0x007f, 0x00ff, X 0x01ff, 0x03ff, 0x07ff, 0x0fff, X 0x1fff, 0x3fff, 0x7fff, 0xffff X }; X X Xint FillBitBuffer(bits) Xregister int bits; X{ X /* get the bits that are left and read the next word */ X unsigned temp; X register int result = bitbuf; X int sbits = bits_left; X bits -= bits_left; X X /* read next word of input */ X bits_left = ReadByte(&bitbuf); X bits_left += ReadByte(&temp); X bitbuf |= (temp << 8); X if (bits_left == 0) X zipeof = 1; X X /* get the remaining bits */ X result = result | (int) ((bitbuf & mask_bits[bits]) << sbits); X bitbuf >>= bits; X bits_left -= bits; X return result; X} X X#define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);} X X/* X * macro READBIT(nbits,zdest) X * { X * if (nbits <= bits_left) { X * zdest = (int)(bitbuf & mask_bits[nbits]); X * bitbuf >>= nbits; X * bits_left -= nbits; X * } else X * zdest = FillBitBuffer(nbits); X * } X * X */ X X X/* ------------------------------------------------------------- */ X Xvoid Write_file() X{ X if (extract) X write(outfd, outbuf, outcnt); X} X X/* ------------------------------------------------------------- */ X Xvoid FlushOutput() X /* flush contents of output buffer */ X{ X UpdateCRC(outbuf, outcnt); X Write_file(); X outpos += outcnt; X outcnt = 0; X outptr = outbuf; X} X X#define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); } X X/* X * macro OUTB(intc) X * { X * *outptr++=intc; X * if (++outcnt==OUTBUFSIZ) X * FlushOutput(); X * } X * X */ X X X/* ----------------------------------------------------------- */ X Xvoid LoadFollowers() X{ X register int x; X register int i; X X for (x = 255; x >= 0; x--) { X READBIT(6,Slen[x]); X for (i = 0; i < Slen[x]; i++) { X READBIT(8,followers[x][i]); X } X } X} X X X/* ----------------------------------------------------------- */ X/* X * The Reducing algorithm is actually a combination of two X * distinct algorithms. The first algorithm compresses repeated X * byte sequences, and the second algorithm takes the compressed X * stream from the first algorithm and applies a probabilistic X * compression method. X */ X Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f}; X Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04}; Xint D_mask[] = {0, 0x01, 0x03, 0x07, 0x0f}; X Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, X 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, X 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, X 8, 8, 8, 8}; X X/* ----------------------------------------------------------- */ X Xvoid unReduce() X /* expand probablisticly reduced data */ X{ X register int lchar; X int nchar; X int ExState; X int V; X int Len; X X factor = lrec.compression_method - 1; X ExState = 0; X lchar = 0; X LoadFollowers(); X X while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) { X if (Slen[lchar] == 0) X READBIT(8,nchar) /* ; */ X else X { X READBIT(1,nchar); X if (nchar != 0) X READBIT(8,nchar) /* ; */ X else X { X int follower; X int bitsneeded = B_table[Slen[lchar]]; X READBIT(bitsneeded,follower); X nchar = followers[lchar][follower]; X } X } X X /* expand the resulting byte */ X switch (ExState) { X X case 0: X if (nchar != DLE) X OUTB(nchar) /*;*/ X else X ExState = 1; X break; X X case 1: X if (nchar != 0) { X V = nchar; X Len = V & L_table[factor]; X if (Len == L_table[factor]) X ExState = 2; X else X ExState = 3; X } X else { X OUTB(DLE); X ExState = 0; X } X break; X X case 2: { X Len += nchar; X ExState = 3; X } X break; X X case 3: { X register int i = Len + 3; X int offset = (((V >> D_shift[factor]) & X D_mask[factor]) << 8) + nchar + 1; X longint op = outpos + outcnt - offset; X X /* special case- before start of file */ X while ((op < 0L) && (i > 0)) { X OUTB(0); X op++; X i--; X } X X /* normal copy of data from output buffer */ X { X register int ix = (int) (op % OUTBUFSIZ); X X /* do a block memory copy if possible */ X if ( ((ix +i) < OUTBUFSIZ) && X ((outcnt+i) < OUTBUFSIZ) ) { X memcpy(outptr,&outbuf[ix],i); X outptr += i; X outcnt += i; X } X X /* otherwise copy byte by byte */ X else while (i--) { X OUTB(outbuf[ix]); X if (++ix >= OUTBUFSIZ) X ix = 0; X } X } X X ExState = 0; X } X break; X } X X /* store character for next iteration */ X lchar = nchar; X } X} X X X/* ------------------------------------------------------------- */ X/* X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm X * with partial clearing. X * X */ X Xvoid partial_clear() X{ X register int pr; X register int cd; X X /* mark all nodes as potentially unused */ X for (cd = first_ent; cd < free_ent; cd++) X prefix_of[cd] |= 0x8000; X X /* unmark those that are used by other nodes */ X for (cd = first_ent; cd < free_ent; cd++) { X pr = prefix_of[cd] & 0x7fff; /* reference to another node? */ X if (pr >= first_ent) /* flag node as referenced */ X prefix_of[pr] &= 0x7fff; X } X X /* clear the ones that are still marked */ X for (cd = first_ent; cd < free_ent; cd++) X if ((prefix_of[cd] & 0x8000) != 0) X prefix_of[cd] = -1; X X /* find first cleared node as next free_ent */ X cd = first_ent; X while ((cd < maxcodemax) && (prefix_of[cd] != -1)) X cd++; X free_ent = cd; X} X X X/* ------------------------------------------------------------- */ X Xvoid unShrink() X{ X#define GetCode(dest) READBIT(codesize,dest) X X register int code; X register int stackp; X int finchar; X int oldcode; X int incode; X X X /* decompress the file */ X maxcodemax = 1 << max_bits; X codesize = init_bits; X maxcode = (1 << codesize) - 1; X free_ent = first_ent; X offset = 0; X sizex = 0; X X for (code = maxcodemax; code > 255; code--) X prefix_of[code] = -1; X X for (code = 255; code >= 0; code--) { X prefix_of[code] = 0; X suffix_of[code] = code; X } X X GetCode(oldcode); X if (zipeof) X return; X finchar = oldcode; X X OUTB(finchar); X X stackp = hsize; X X while (!zipeof) { X GetCode(code); X if (zipeof) X return; X X while (code == clear) { X GetCode(code); X switch (code) { X X case 1:{ X codesize++; X if (codesize == max_bits) X maxcode = maxcodemax; X else X maxcode = (1 << codesize) - 1; X } X break; X X case 2: X partial_clear(); X break; X } X X GetCode(code); X if (zipeof) X return; X } X X X /* special case for KwKwK string */ X incode = code; X if (prefix_of[code] == -1) { X stack[--stackp] = finchar; X code = oldcode; X } X X X /* generate output characters in reverse order */ X while (code >= first_ent) { X stack[--stackp] = suffix_of[code]; X code = prefix_of[code]; X } X X finchar = suffix_of[code]; X stack[--stackp] = finchar; X X X /* and put them out in forward order, block copy */ X if ((hsize-stackp+outcnt) < OUTBUFSIZ) { X memcpy(outptr,&stack[stackp],hsize-stackp); X outptr += hsize-stackp; X outcnt += hsize-stackp; X stackp = hsize; X } X X /* output byte by byte if we can't go by blocks */ X else while (stackp < hsize) X OUTB(stack[stackp++]); X X X /* generate new entry */ X code = free_ent; X if (code < maxcodemax) { X prefix_of[code] = oldcode; X suffix_of[code] = finchar; X X do X code++; X while ((code < maxcodemax) && (prefix_of[code] != -1)); X X free_ent = code; X } X X /* remember previous code */ X oldcode = incode; X } X X} X X X/* ---------------------------------------------------------- */ X Xvoid extract_member() X{ X unsigned b; X X bits_left = 0; X bitbuf = 0; X incnt = 0; X outpos = 0L; X outcnt = 0; X outptr = outbuf; X zipeof = 0; X crc32val = 0xFFFFFFFFL; X X X /* create the output file with READ and WRITE permissions */ X if (create_output_file()) X exit(1); X X switch (lrec.compression_method) { X X case 0: /* stored */ X { X if (test_zip) X printf("Testing: %-12s ", filename); X if (extract) X printf(" Extracting: %-12s ", filename); X while (ReadByte(&b)) X OUTB(b); X } X break; X X case 1: { X if (test_zip) X printf("Testing: %-12s ", filename); X if (extract) X printf("UnShrinking: %-12s ", filename); X unShrink(); X } X break; X X case 2: X case 3: X case 4: X case 5: { X if (test_zip) X printf("Testing: %-12s ", filename); X if (extract) X printf(" Expanding: %-12s ", filename); X unReduce(); X } X break; X X default: X printf("Unknown compression method."); X } X X X /* write the last partial buffer, if any */ X if (outcnt > 0) { X UpdateCRC(outbuf, outcnt); X Write_file(); X } X X /* set output file date and time */ X set_file_time(); X X close(outfd); X X crc32val = -1 - crc32val; X if (!list_zip) { X if (crc32val != lrec.crc32) { X numbad++; X printf(" Bad"); X if(verbose) X printf(", CRC %08lx (should be %08lx)", lrec.crc32, crc32val); X } else { X printf(" Ok"); X if (verbose) X printf(", CRC = %08lx", lrec.crc32); X } X printf("\n"); X } X} X X X/* ---------------------------------------------------------- */ X Xvoid get_string(len, s) Xint len; Xchar *s; X{ X read(zipfd, s, len); X s[len] = 0; X} X X/* UNIX support routines: Michael Enkelis */ Xget_byte() X{ X byte nibble; X read(zipfd,&nibble,1); X return (byte) (nibble & 0xff); X} X Xget_word() X{ X byte nibble[2]; X nibble[0] = get_byte(); X nibble[1] = get_byte(); X return (word) (nibble[0] | nibble[1] << 8); X} X Xget_long() X{ X byte nibble[4]; X nibble[0] = get_byte(); X nibble[1] = get_byte(); X nibble[2] = get_byte(); X nibble[3] = get_byte(); X return (longint) ((unsigned long) nibble[0] | X ((unsigned long) nibble[1] << 8) | X ((unsigned long) nibble[2] << 16) | X ((unsigned long) nibble[3] << 24)); X} X/** End of added support routines **/ X X X/* ---------------------------------------------------------- */ X Xvoid process_local_file_header() X{ X byte yr, mo, dy; /* parts of a date */ X byte hh, mm, ss; /* parts of a time */ X X static char *mon[] = /* month abbreviations */ X { X "Jan", "Feb", "Mar", "Apr", X "May", "Jun", "Jul", "Aug", X "Sep", "Oct", "Nov", "Dec" X }; X X lrec.version_needed_to_extract = get_word(); X lrec.general_purpose_bit_flag = get_word(); X lrec.compression_method = get_word(); X lrec.last_mod_file_time = get_word(); X lrec.last_mod_file_date = get_word(); X lrec.crc32 = get_long(); X lrec.compressed_size = get_long(); X lrec.uncompressed_size = get_long(); X lrec.filename_length = get_word(); X lrec.extra_field_length = get_word(); X X get_string(lrec.filename_length,filename); X get_string(lrec.extra_field_length,extra); X X yr = (lrec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */ X mo = (lrec.last_mod_file_date >> 5) & 0x0f; X dy = lrec.last_mod_file_date & 0x1f; X X hh = (lrec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */ X mm = (lrec.last_mod_file_time >> 5) & 0x3f; X ss = (lrec.last_mod_file_time & 0x1f) * 2; X X if (debugging) { X printf("\n\nProcess LOCAL file header.\n"); X printf("Version used : %d\n",lrec.version_needed_to_extract); X printf("Bit flags : %d\n",lrec.general_purpose_bit_flag); X printf("Compression : %d\n",lrec.compression_method); X printf("Mod time :"); X printf("%2d:%02d%c\n", X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a')); X printf("Mod date :"); X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100); X printf("Crc32 : %d\n",~lrec.crc32); X printf("Compressed size : %d\n",lrec.compressed_size); X printf("Normal file size: %d\n",lrec.uncompressed_size); X printf("File name : %s.%s\n",filename,extra); X } X X extract_member(); X} X X X/* ---------------------------------------------------------- */ X Xvoid process_central_file_header() X{ X central_directory_file_header rec; X char filename[STRSIZ]; X char extra[STRSIZ]; X X byte yr, mo, dy; /* parts of a date */ X byte hh, mm, ss; /* parts of a time */ X X static char *mon[] = /* month abbreviations */ X { X "Jan", "Feb", "Mar", "Apr", X "May", "Jun", "Jul", "Aug", X "Sep", "Oct", "Nov", "Dec" X }; X X rec.version_made_by = get_word(); X rec.version_needed_to_extract = get_word(); X rec.general_purpose_bit_flag = get_word(); X rec.compression_method = get_word(); X rec.last_mod_file_time = get_word(); X rec.last_mod_file_date = get_word(); X rec.crc32 = get_long(); X rec.compressed_size = get_long(); X rec.uncompressed_size = get_long(); X rec.filename_length = get_word(); X rec.extra_field_length = get_word(); X rec.file_comment_length = get_word(); X rec.disk_number_start = get_word(); X rec.internal_file_attributes = get_word(); X rec.external_file_attributes = get_long(); X rec.relative_offset_local_header = get_long(); X X get_string(rec.filename_length,filename); X get_string(rec.extra_field_length,extra); X X comment = (byte *) (realloc(comment, rec.file_comment_length)); X get_string(rec.file_comment_length,comment); X X yr = (rec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */ X mo = (rec.last_mod_file_date >> 5) & 0x0f; X dy = rec.last_mod_file_date & 0x1f; X X hh = (rec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */ X mm = (rec.last_mod_file_time >> 5) & 0x3f; X ss = (rec.last_mod_file_time & 0x1f) * 2; X X if (debugging) { X printf("\n\nProcess CENTRAL file header.\n"); X printf("Version made by : %d\n",rec.version_made_by); X printf("Version used : %d\n",rec.version_needed_to_extract); X printf("Bit flags : %d\n",rec.general_purpose_bit_flag); X printf("Compression : %d\n",rec.compression_method); X printf("Mod time :"); X printf("%2d:%02d%c\n", X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a')); X printf("Mod date :"); X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100); X printf("Crc32 : %d\n",~rec.crc32); X printf("Compressed size : %d\n",rec.compressed_size); X printf("Normal file size: %d\n",rec.uncompressed_size); X printf("File name : %s.%s\n",filename,extra); X printf("Comment size : %d\n",rec.file_comment_length); X printf("Disk start # : %d\n",rec.disk_number_start); X printf("File attributes : %d\n",rec.internal_file_attributes); X printf("Os attributes : %d\n",rec.external_file_attributes); X printf("Offset to header: %d\n",rec.relative_offset_local_header); X printf("Comment : %s\n",comment); X } X X if (list_zip) { X Total_files++; X Total_bytes += rec.uncompressed_size; X Total_length += rec.compressed_size; X X printf("%-12s %8d ", filename,rec.uncompressed_size); X if (verbose) { X printf("%8d ",rec.compressed_size); X if (rec.compressed_size) X printf("%3d%% ",100L - (100L * rec.compressed_size)/ X rec.uncompressed_size); X else X printf("--- "); X } X X printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100); X X if (verbose) X printf(" %2d:%02d%c", X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a')); X printf("\n"); X } X X} X X X/* ---------------------------------------------------------- */ X Xvoid process_end_central_dir() X{ X end_central_dir_record rec; X X rec.number_this_disk = get_word(); X rec.number_disk_with_start_central_directory = get_word(); X rec.total_entries_central_dir_on_this_disk = get_word(); X rec.total_entries_central_dir = get_word(); X rec.size_central_directory = get_long(); X rec.offset_start_central_directory = get_long(); X rec.zipfile_comment_length = get_word(); X X comment = (byte *) (realloc(comment, rec.zipfile_comment_length)); X get_string(rec.zipfile_comment_length,comment); X X if (debugging) { X printf("\n\nProcess END_CENTRAL directory header.\n"); X printf("This disk : %d\n",rec.number_this_disk); X printf("Starting disk : %d\n", X rec.number_disk_with_start_central_directory); X printf("Total this disk : %d\n", X rec.total_entries_central_dir_on_this_disk); X printf("Total entries : %d\n",rec.total_entries_central_dir); X printf("Central dir size: %d\n",rec.size_central_directory); X printf("Offset to dir : %d\n",rec.offset_start_central_directory); X printf("Comment size : %d\n",rec.zipfile_comment_length); X printf("Comment : %s\n",comment); X } X} X X X/* ---------------------------------------------------------- */ X Xvoid process_headers() X{ X int i; X char sig[4]; X X if (list_zip) { X if (verbose) { X printf("\nName Length Size now SF Date Time"); X printf("\n============ ======== ======== ==== ========= ========\n"); X } else { X printf("\nName Length Date"); X printf("\n============ ======== =========\n"); X } X } X X while (1) X { X for (i=0; i<4; i++) /* Read the ZIP file sig */ X sig[i] = get_byte(); X X if (strncmp(sig,local_file_header_signature,4) == 0) X process_local_file_header(); X else X if (strncmp(sig,central_file_header_signature,4) == 0) X process_central_file_header(); X else X if (strncmp(sig,end_central_dir_signature,4) == 0) X { X process_end_central_dir(); X if (test_zip) { X if (numbad < 1) X printf("No errors detected\n"); X else X if (numbad == 1) X printf("One error detected\n"); X else X printf("%d errors detected\n",numbad); X } X if (list_zip) { X if (verbose) { X printf(" ==== ======== ======== ==== \n"); X printf("Total: %4d %8d %8d ", X Total_files,Total_bytes,Total_length); X if (Total_length) X printf("%3d%%\n", 100 - (100 * Total_length)/ X Total_bytes); X else X printf("---\n"); X } else { X printf(" ==== ========\n"); X printf("Total: %4d %8d\n", X Total_files,Total_bytes); X } X } X if (strlen(comment)) X printf("%s\n",comment); X return; X } X else X { X printf("Invalid Zipfile Header\n"); X return; X } X } X} X X X X/* ---------------------------------------------------------- */ X Xvoid extract_zipfile() X{ X /* X * open the zipfile for reading and in BINARY mode to prevent cr/lf X * translation, which would corrupt the bitstreams X */ X X if (open_input_file()) X exit(1); X X process_headers(); X X close(zipfd); X} X X X/* ---------------------------------------------------------- */ X/* X * main program X * X */ X Xvoid main(argc, argv) Xint argc; Xchar **argv; X{ X X#ifdef USE_GETOPT X int c; /* next option letter */ X int count = 0; /* count of required options seen */ X X extern int optind; /* from getopt: next arg to process */ X extern int opterr; /* used by getopt */ X extern char *optarg; X X opterr = 0; /* so getopt won't print err msg */ X X while ((c = getopt (argc, argv, "dltv")) != EOF) X { X switch (c) { X case 'd': debugging++; break; X case 'l': list_zip =1;extract =0; break; X case 't': test_zip =1;extract =0; break; X case 'v': verbose++; break; X default: short_help(); X } X } X X strcpy(zipfn,argv[optind]); X if (strlen(zipfn) == 0) X long_help(); X X /* .ZIP default if none provided by user */ X if (strchr(zipfn,'.') == NULL) X strcat(zipfn,".zip"); X#else X if (argc != 2) X long_help(); X X /* .ZIP default if none provided by user */ X strcpy(zipfn, argv[1]); X if (strchr(zipfn, '.') == NULL) X strcat(zipfn, ".zip"); X#endif X X /* allocate i/o buffers */ X inbuf = (byte *) (malloc(INBUFSIZ)); X outbuf = (byte *) (malloc(OUTBUFSIZ)); X comment = (byte *) (malloc(STRSIZ)); X if ((inbuf == NULL) || (outbuf == NULL) || (comment == NULL)) { X printf("Can't allocate buffers!\n"); X exit(1); X } X X /* do the job... */ X extract_zipfile(); X exit(0); X} X Xlong_help() X{ Xprintf("\nUnZip: Zipfile Extract Version:%s Patchlevel:%d",VERSION,PATCH); Xprintf("; (C) 1989 Samuel H. Smith\n"); Xprintf("Courtesy of: S.H.Smith and The Tool Shop BBS, (602) 279-2673."); Xprintf("\n\n"); Xprintf("UNIX mods by: Michael Enkelis\n\n"); Xprintf("You may copy and distribute this program freely, provided that:\n"); Xprintf(" 1) No fee is charged for such copying and distribution, and\n"); Xprintf(" 2) It is distributed ONLY in its original, unmodified state."); Xprintf("\n\n"); Xprintf("If you wish to distribute a modified version of this program, you MUST\n"); Xprintf("include the source code.\n\n"); Xprintf("If you modify this program, I would appreciate a copy of the new source\n"); Xprintf("code. I am holding the copyright on the source code, so please don't\n"); Xprintf("delete my name from the program files or from the documentation.\n\n"); Xprintf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n"); Xprintf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n"); Xprintf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n"); Xprintf("CLAIM BY ANY OTHER PARTY.\n\n"); Xshort_help(); Xexit(1); X} X Xshort_help() X{ X printf("Usage: UnZip -hltv FILE[.zip]\n\n"); X printf(" -h This help listing.\n"); X printf(" -l List zip archive.\n"); X printf(" -t Test zip archive.\n"); X printf(" -v Verbose output.\n\n"); X exit(1); X} SHAR_EOF if test 30392 -ne "`wc -c < 'unzipbsd.c'`" then echo shar: error transmitting "'unzipbsd.c'" '(should have been 30392 characters)' fi fi # end of overwriting check echo shar: extracting "'crc32.c'" '(7120 characters)' if test -f 'crc32.c' then echo shar: will not over-write existing file "'crc32.c'" else sed 's/^ X//' << \SHAR_EOF > 'crc32.c' X X /* ============================================================= */ X /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ X /* code or tables extracted from it, as desired without restriction. */ X /* */ X /* First, the polynomial itself and its table of feedback terms. The */ X /* polynomial is */ 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^0 */ X /* */ X /* Note that we take it "backwards" and put the highest-order term in */ X /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ X /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ X /* the MSB being 1. */ X /* */ X /* Note that the usual hardware shift register implementation, which */ X /* is what we're using (we're merely optimizing it by doing eight-bit */ X /* chunks at a time) shifts bits into the lowest-order term. In our */ X /* implementation, that means shifting towards the right. Why do we */ X /* do it this way? Because the calculated CRC must be transmitted in */ X /* order from highest-order term to lowest-order term. UARTs transmit */ X /* characters in order from LSB to MSB. By storing the CRC this way, */ X /* we hand it to the UART in the order low-byte to high-byte; the UART */ X /* sends each low-bit to hight-bit; and the result is transmission bit */ X /* by bit from highest- to lowest-order term without requiring any bit */ X /* shuffling on our part. Reception works similarly. */ X /* */ X /* The feedback terms table consists of 256, 32-bit entries. Notes: */ X /* */ X /* The table can be generated at runtime if desired; code to do so */ X /* is shown later. It might not be obvious, but the feedback */ X /* terms simply represent the results of eight shift/xor opera- */ X /* tions for all combinations of data and CRC register values. */ X /* */ X /* The values must be right-shifted by eight bits by the "updcrc" */ X /* logic; the shift must be unsigned (bring in zeroes). On some */ X /* hardware you could probably optimize the shift in assembler by */ X /* using byte-swap instructions. */ X /* polynomial $edb88320 */ X /* */ X /* -------------------------------------------------------------------- */ X Xlong crc_32_tab[] = { X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, X 0x2d02ef8dL X }; X X/* ------------------------------------------------------------- */ X Xextern long crc32val; X Xvoid UpdateCRC(s, len) Xregister char *s; Xregister int len; X /* update running CRC calculation with contents of a buffer */ X{ X int i; X for (i = 0; i < len; i ++) { X crc32val = crc_32_tab[(int) ((crc32val) ^ (s[i])) & 0xff] ^ X (((crc32val) >> 8) & 0x00FFFFFFL); X } X} SHAR_EOF if test 7120 -ne "`wc -c < 'crc32.c'`" then echo shar: error transmitting "'crc32.c'" '(should have been 7120 characters)' fi fi # end of overwriting check # End of shell archive exit 0 -- _ _ _ __ ' ) ) ) / /) / ` / /) Michael Enkelis / / / o _. /_ __. _ // /-- __ /_ _ // o _ tektronix!vice!michaele / ' (_(_(__/ /_(_(_(<_(/_ (___, /) )_/ <_(<_(/_(_/_)_ (503) 627-4099