[alt.sources] A unix version of unzip11 that was posted a few days ago.

michaele@vice.ICO.TEK.COM (Michael Enkelis) (04/06/89)

This version of UNZIP, includes the CRC-32 checking of the ZIP
archive on extract, and a -t option to test a archive only.
It should work on any system.  I used getopt to handle the
option processing.

#! /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
#	unzipbsd.c
#	addbfcrc.c
# This archive created: Wed Apr  5 07:32:55 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Makefile'" '(771 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
	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
	XLDFLAGS= -s
	X
	XCC=cc
	X
	X.c.o :
	X	$(CC) -c $(CFLAGS) $*.c
	X
	XOBJS = unzipbsd.o addbfcrc.o
	X
	Xunzip: $(OBJS)
	X	cc $(LDFLAGS) -o unzip $(OBJS)
	X
	Xunzip.o: unzip.c
	X
	Xaddbfcrc.o: addbfcrc.c
	X
	Xinstall: unzip
	X	mv unzip $(DESTDIR)/unzip
	X
	Xclean:
	X	/bin/rm -f $(OBJS) core unzip
	X
	Xshar:
	X	@shar -a Makefile unzipbsd.c addbfcrc.c > unzipbsd.shar
SHAR_EOF
if test 771 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 771 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'unzipbsd.c'" '(19022 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 * Quick hack to use on BSD, on a DEC VAX
	X * By Michael Enkelis @ tektronix 04/03/89
	X *
	X */
	X
	X/*
	X * Copyright 1987, 1989 Samuel H. Smith;  All rights reserved
	X *
	X * This is a component of the ProDoor System.
	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 */ 
	X
	X#define version  "UnZip:  Zipfile Extract v1.1b of 04-03-89; (C) 1989 S.H.Smith"
	X
	Xtypedef unsigned char byte;
	Xtypedef unsigned int word;
	Xtypedef unsigned long longint;
	Xtypedef unsigned char boolean;
	X#define STRSIZ  256
	X
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <sys/file.h>
	X#include <sys/stat.h>
	X
	X
	Xint errcount = 0;		/* count of errors */
	Xint debugging = 0;		/* debug enable flag */
	Xint verbose = 0;		/* be verbose */
	Xint test_zip = 0;		/* test CRC's only */
	X
	X/*
	XInitializing the CRC to all one bits avoids failure of detection
	Xshould entire data stream get cyclically bit-shifted by one position.
	XThe calculation of the probability of this happening is left as
	Xan exercise for the reader.
	X*/
	X#define INITCRC	0xFFFFFFFFL;
	Xextern long crccode;
	X
	X/* ----------------------------------------------------------- */ 
	X/*
	X * Zipfile layout declarations
	X *
	X */ 
	X
	Xtypedef longint	signature_type;
	X
	X
	X#define local_file_header_signature  0x04034b50L
	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#define central_file_header_signature  0x02014b50L
	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#define end_central_dir_signature  0x06054b50L
	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 * input file variables
	X *
	X */ 
	X
	X
	X#define  uinbufsize	512L	/* input buffer size */
	X	byte	inbuf[uinbufsize];
	X
	X	boolean  zipeof;
	X	longint  csize;
	X	longint  cusize;
	X	int	cmethod;
	X	int	inpos;
	X	int	incnt;
	X	int	pc;
	X	int	pcbits;
	X	int	pcbitv;
	X	
	X	int	zipfd;
	X	char	zipfn[STRSIZ];
	X	local_file_header lrec;
	X
	X
	X
	X
	X/* ----------------------------------------------------------- */ 
	X/*
	X * output stream variables
	X *
	X */ 
	X
	X
	X	byte	outbuf[4096];	/* for rle look-back */
	X	longint  outpos;	  /* absolute position in outfile */
	X	int	outcnt;
	X
	X	int	outfd;
	X	char	filename[STRSIZ];
	X	char	extra[STRSIZ];
	X
	X
	X
	X/* ----------------------------------------------------------- */ 
	X/*
	X * shrink/reduce working storage
	X *
	X */ 
	X
	X
	X	int	factor;
	X	byte	followers[256][64];
	X	byte	Slen[256];
	X	int	ExState;
	X	int	C;
	X	int	V;
	X	int	Len;
	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
	X	typedef int  hsize_array_integer[hsize+1];
	X	typedef byte hsize_array_byte[hsize+1];
	X
	X	hsize_array_integer prefix_of;
	X	hsize_array_byte	suffix_of;
	X	hsize_array_byte	stack;
	X
	X	int	cbits;
	X	int	maxcode;
	X	int	free_ent;
	X	int	maxcodemax;
	X	int	offset;
	X	int	sizex;
	X
	X
	X/* ------------------------------------------------------------- */ 
	X
	Xskip_csize()
	X{ 
	X	lseek(zipfd,csize,L_SET);
	X	zipeof = 1;
	X	csize = 0L; 
	X	incnt = 0; 
	X} 
	X
	X
	X/* ------------------------------------------------------------- */ 
	X
	XReadByte(x)
	Xint *x;
	X{ 
	X	if (incnt == 0) 
	X	{ 
	X	if (csize == 0L) 
	X	{ 
	X	  zipeof = 1;
	X	  return;
	X	} 
	X
	X	inpos = sizeof(inbuf);
	X	if (inpos > csize) 
	X	  inpos = (int)csize;
	X	incnt = read(zipfd,inbuf,inpos);
	X
	X	inpos = 1; 
	X	csize -= incnt; 
	X	} 
	X
	X	*x = inbuf[inpos-1]; 
	X	inpos++; 
	X	incnt--; 
	X} 
	X
	X
	X/* ------------------------------------------------------------- */ 
	X
	XReadBits(bits,x)
	Xint bits,*x;
	X	/* read the specified number of bits */ 
	X{ 
	X	int	bit;
	X	int	bitv;
	X
	X	*x = 0;
	X	bitv = 1;
	X
	X	for (bit = 0; bit <= bits-1; bit++)
	X	{ 
	X
	X	if (pcbits > 0) 
	X	{ 
	X	  pcbits--; 
	X	  pcbitv = pcbitv << 1; 
	X	} 
	X	else 
	X
	X	{ 
	X	  ReadByte(&pc); 
	X	  pcbits = 7; 
	X	  pcbitv = 1; 
	X	} 
	X
	X	if ((pc & pcbitv) != 0) 
	X	  *x = *x | bitv; 
	X
	X	bitv = (int) (bitv << 1);
	X	} 
	X
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xget_string(len, s)
	Xint len;
	Xchar *s[];
	X{ 
	X	read(zipfd,s,len);
	X	s[len] = 0;
	X} 
	X
	X
	X/* ------------------------------------------------------------- */ 
	X
	XOutByte(c)
	Xint c;
	X	/* output each character from archive to screen */ 
	X{ 
	X	outbuf[outcnt /* outpos % sizeof(outbuf) */] = c;
	X	outpos++; 
	X	outcnt++;
	X 
	X	if (outcnt == sizeof(outbuf)) 
	X	{ 
	X	if (test_zip == 0)
	X		write(outfd,outbuf,outcnt);
	X	addbfcrc (outbuf, outcnt);
	X	outcnt = 0; 
	X	printf("."); 
	X	} 
	X} 
	X
	X
	X/* ----------------------------------------------------------- */
	X	
	Xreduce_L(x)
	Xint x;
	X	{ 
	X	switch (factor) {
	X	  case 1:	return x & 0x7f; 
	X	  case 2:	return x & 0x3f; 
	X	  case 3:	return x & 0x1f; 
	X	  case 4:	return x & 0x0f; 
	X	} 
	X	return 0; /* error */
	X	} 
	X
	X	
	Xreduce_F(x)
	Xint x;
	X	{ 
	X	switch (factor) {
	X	  case 1:	if (x == 127) return 2;  else return 3;
	X	  case 2:	if (x == 63) return 2;	else return 3;
	X	  case 3:	if (x == 31) return 2;	else return 3;
	X	  case 4:	if (x == 15) return 2;	else return 3;
	X	} 
	X	return 0; /* error */
	X	} 
	X
	X	
	Xreduce_D(x,y)
	Xint x,y;
	X	{ 
	X	switch (factor) {
	X	  case 1:	return ((x >> 7) & 0x01) * 256 + y + 1; 
	X	  case 2:	return ((x >> 6) & 0x03) * 256 + y + 1; 
	X	  case 3:	return ((x >> 5) & 0x07) * 256 + y + 1; 
	X	  case 4:	return ((x >> 4) & 0x0f) * 256 + y + 1; 
	X	} 
	X	return 0; /* error */
	X	} 
	X
	X
	Xreduce_B(x)
	Xint x;
	X	 /* number of bits needed to encode the specified number */ 
	X	{ 
	X	switch (x - 1) {
	X	  
	X	  case 0:	
	X	  case 1:	return 1; 
	X	  
	X	  case 2:	
	X	  case 3:	return 2; 
	X	  
	X	  case 4:
	X	  case 5:	
	X	  case 6:	
	X	  case 7:	return 3; 
	X	  
	X	  case 8:	
	X	  case 9:	
	X	  case 10:	
	X	  case 11:	
	X	  case 12:	
	X	  case 13:	
	X	  case 14:	
	X	  case 15:	return 4; 
	X	 
	X	  case 16:
	X	  case 17:
	X	  case 18:
	X	  case 19:
	X	  case 20:
	X	  case 21:
	X	  case 22:
	X	  case 23:
	X	  case 24:
	X	  case 25:
	X	  case 26:
	X	  case 27:
	X	  case 28:
	X	  case 29:
	X	  case 30:
	X	  case 31:	return 5;
	X	 
	X	  case 32:
	X	  case 33:
	X	  case 34:
	X	  case 35:
	X	  case 36:
	X	  case 37:
	X	  case 38:
	X	  case 39:
	X	  case 40:
	X	  case 41:
	X	  case 42:
	X	  case 43:
	X	  case 44:
	X	  case 45:
	X	  case 46:
	X	  case 47:
	X	  case 48:
	X	  case 49:
	X	  case 50:
	X	  case 51:
	X	  case 52:
	X	  case 53:
	X	  case 54:
	X	  case 55:
	X	  case 56:
	X	  case 57:
	X	  case 58:
	X	  case 59:
	X	  case 60:
	X	  case 61:
	X	  case 62:
	X	  case 63:	return 6;
	X
	X	  case 64:
	X	  case 65:
	X	  case 66:
	X	  case 67:
	X	  case 68:
	X	  case 69:
	X	  case 70:
	X	  case 71:
	X	  case 72:
	X	  case 73:
	X	  case 74:
	X	  case 75:
	X	  case 76:
	X	  case 77:
	X	  case 78:
	X	  case 79:
	X	  case 80:
	X	  case 81:
	X	  case 82:
	X	  case 83:
	X	  case 84:
	X	  case 85:
	X	  case 86:
	X	  case 87:
	X	  case 88:
	X	  case 89:
	X	  case 90:
	X	  case 91:
	X	  case 92:
	X	  case 93:
	X	  case 94:
	X	  case 95:
	X	  case 96:
	X	  case 97:
	X	  case 98:
	X	  case 99:
	X	  case 100:
	X	  case 101:
	X	  case 102:
	X	  case 103:
	X	  case 104:
	X	  case 105:
	X	  case 106:
	X	  case 107:
	X	  case 108:
	X	  case 109:
	X	  case 110:
	X	  case 111:
	X	  case 112:
	X	  case 113:
	X	  case 114:
	X	  case 115:
	X	  case 116:
	X	  case 117:
	X	  case 118:
	X	  case 119:
	X	  case 120:
	X	  case 121:
	X	  case 122:
	X	  case 123:
	X	  case 124:
	X	  case 125:
	X	  case 126:
	X	  case 127:	return 7;
	X	
	X	default:	return 8;
	X	} 
	X	} 
	X
	X
	X
	X/* ----------------------------------------------------------- */
	X
	XExpand(c)
	Xint c;
	X	{ 
	X#define DLE		144
	X	
	X	switch (ExState) {
	X		
	X		case 0:
	X		 if (c != DLE)
	X			OutByte(c);
	X		 else 
	X			ExState = 1; 
	X		break; 
	X		
	X		case 1:
	X		 if (c != 0)
	X		 { 
	X			V = c; 
	X			Len = reduce_L(V);
	X			ExState = reduce_F(Len);
	X		 } 
	X		 else 
	X		 { 
	X			OutByte(DLE); 
	X			ExState = 0; 
	X		 } 
	X		break; 
	X		
	X		case 2:	{ 
	X			Len = Len + c; 
	X			ExState = 3; 
	X		 } 
	X		break; 
	X		
	X		case 3:	{ 
	X			int i;
	X			longint offset = reduce_D(V,c);
	X			longint op = outpos - offset;
	X
	X			for (i = 0; i <= Len + 2; i++) 
	X			{ 
	X			if (op < 0L) 
	X				OutByte(0);
	X			else 
	X				OutByte(outbuf[(int)(op % sizeof(outbuf))]);
	X			op++; 
	X			} 
	X
	X			ExState = 0; 
	X		 } 
	X	  break;
	X	} 
	X	} 
	X
	X
	X/* ----------------------------------------------------------- */
	X	
	XLoadFollowers()
	X	{ 
	X	int	x;
	X	int	i;
	X	int	b;
	X
	X	for (x = 255; x >= 0; x--) 
	X	{ 
	X	  ReadBits(6,&b); 
	X	  Slen[x] = b;
	X
	X	  for (i = 0; i < Slen[x]; i++)
	X	  { 
	X		ReadBits(8,&b); 
	X		followers[x][i] = b;
	X	  } 
	X	} 
	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 */ 
	X
	XunReduce()
	X	/* expand probablisticly reduced data */ 
	X
	X	{ 
	X
	X	int	lchar;
	X	int	lout;
	X	int	I;
	X
	X	factor = cmethod - 1; 
	X	if ((factor < 1) || (factor > 4)) 
	X	{ 
	X	skip_csize(); 
	X	return;
	X	} 
	X
	X	ExState = 0; 
	X	LoadFollowers(); 
	X	lchar =  0;
	X
	X	while ((!zipeof) && (outpos < cusize))
	X	{ 
	X
	X	if (Slen[lchar] == 0)
	X	  ReadBits(8,&lout);
	X	else 
	X
	X	{ 
	X	  ReadBits(1,&lout); 
	X	  if (lout != 0) 
	X		ReadBits(8,&lout);
	X	  else 
	X	  { 
	X		ReadBits(reduce_B(Slen[lchar]),&I);
	X		lout = followers[lchar][I];
	X	  } 
	X	} 
	X
	X	Expand(lout); 
	X	lchar = lout; 
	X	} 
	X} 
	X
	X
	X/* ------------------------------------------------------------- */
	X/*
	X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
	X * with partial clearing.
	X *
	X */ 
	X
	Xpartial_clear()
	X{ 
	X	int	pr;
	X	int	cd;
	X
	X
	X	/* mark all nodes as potentially unused */
	X	for (cd = first_ent; cd < free_ent; cd++)
	X	prefix_of[cd] |= 0x8000;
	X
	X
	X	/* unmark those that are used by other nodes */
	X	for (cd = first_ent; cd < free_ent; cd++)
	X	{ 
	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
	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
	X	/* find first cleared node as next free_ent */ 
	X	free_ent = first_ent; 
	X	while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1)) 
	X	free_ent++; 
	X} 
	X
	X
	X/* ------------------------------------------------------------- */
	X
	XunShrink()
	X
	X{ 
	X	int	stackp;
	X	int	finchar;
	X	int	code;
	X	int	oldcode;
	X	int	incode;
	X
	X
	X	/* decompress the file */ 
	X	maxcodemax = 1 << max_bits; 
	X	cbits = init_bits; 
	X	maxcode = (1 << cbits) - 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	{ 
	X	prefix_of[code] = 0;
	X	suffix_of[code] = code;
	X	} 
	X
	X	ReadBits(cbits,&oldcode); 
	X	if (zipeof) return;
	X	finchar = oldcode; 
	X
	X	OutByte(finchar); 
	X
	X	stackp = 0; 
	X
	X	while ((!zipeof)) 
	X	{ 
	X	ReadBits(cbits,&code); 
	X	if (zipeof) return;
	X
	X	while (code == clear)
	X	{ 
	X	  ReadBits(cbits,&code); 
	X
	X	  switch (code) {
	X		
	X		case 1:	{ 
	X			cbits++; 
	X			if (cbits == max_bits) 
	X			maxcode = maxcodemax;
	X			else 
	X			maxcode = (1 << cbits) - 1; 
	X		 } 
	X		break;
	X
	X		case 2:
	X			partial_clear();
	X		break;
	X	  } 
	X
	X	  ReadBits(cbits,&code); 
	X	  if (zipeof) return;
	X	} 
	X
	X	
	X	/* special case for KwKwK string */
	X	incode = code;
	X	if (prefix_of[code] == -1)
	X	{ 
	X	  stack[stackp] = finchar;
	X	  stackp++; 
	X	  code = oldcode; 
	X	} 
	X
	X
	X	/* generate output characters in reverse order */
	X	while (code >= first_ent)
	X	{ 
	X	  stack[stackp] = suffix_of[code];
	X	  stackp++; 
	X	  code = prefix_of[code];
	X	} 
	X
	X	finchar = suffix_of[code];
	X	stack[stackp] = finchar;
	X	stackp++; 
	X
	X
	X	/* and put them out in forward order */
	X	while (stackp > 0)
	X	{ 
	X	  stackp--; 
	X	  OutByte(stack[stackp]);
	X	} 
	X
	X
	X	/* generate new entry */
	X	code = free_ent;
	X	if (code < maxcodemax) 
	X	{ 
	X	  prefix_of[code] = oldcode;
	X	  suffix_of[code] = finchar;
	X	  while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1))
	X		free_ent++;
	X	} 
	X
	X
	X	/* remember previous code */
	X	oldcode = incode; 
	X	} 
	X
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xextract_member()
	X{ 
	X	int	b;
	X
	Xfor (b=0; b<sizeof(outbuf); b++) outbuf[b]=0;
	X	pcbits = 0; 
	X	incnt = 0; 
	X	outpos = 0L; 
	X	outcnt = 0; 
	X	zipeof = 0;
	X
	X
	X	if (test_zip == 0) {
	X		outfd = creat(filename,S_IWRITE|S_IREAD);
	X		if (outfd < 1)
	X		{ 
	X			printf("Can't create output: %s\n",filename); 
	X			exit(1);
	X		} 
	X		close(outfd);
	X		outfd = open(filename,O_RDWR);
	X	}
	X
	X	if (test_zip)
	X		printf(" Testing: %s ...",filename);
	X
	X	switch (cmethod) {
	X	
	X	case 0:	/* stored */ 
	X		{ 
	X		 if (test_zip == 0)
	X		 	printf(" Extract: %s ...",filename); 
	X		 while ((!zipeof)) 
	X		 { 
	X			ReadByte(&b); 
	X			OutByte(b); 
	X		 } 
	X		} 
	X	break; 
	X	
	X	case 1:	{ 
	X		 if (test_zip == 0)
	X		 	printf("UnShrink: %s ...",filename); 
	X		 unShrink(); 
	X		} 
	X	break; 
	X	
	X	case 2:	
	X	case 3:	
	X	case 4:	
	X	case 5:	{ 
	X		 if (test_zip == 0)
	X		 	printf("  Expand: %s ...",filename); 
	X		 unReduce(); 
	X		} 
	X	break; 
	X	
	X	default: printf("Unknown compression method."); 
	X	} 
	X
	X	if (outcnt > 0) {
	X		if (test_zip == 0)
	X			write(outfd,outbuf,outcnt);
	X		addbfcrc (outbuf, outcnt);
	X	}
	X
	X	if (test_zip == 0)
	X		close(outfd);
	X
	X	if ((crccode + lrec.crc32) == -1)
	X		printf("  Ok");
	X	else
	X		printf("  Bad");
	X
	X	if (verbose)
	X		printf(" [%d]\n",crccode);
	X	else
	X		printf("\n");
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	X/* UNIX support routines: Michael Enkelis */
	Xget_byte()
	X{
	X	unsigned int nibble;
	X	read(zipfd,&nibble,1);
	X	return (nibble & 0xff);
	X}
	X
	Xget_word()
	X{
	X	unsigned int nibble[2];
	X		nibble[0] = get_byte();
	X		nibble[1] = get_byte();
	X	return (int) (nibble[0] | nibble[1] << 8);
	X}
	X
	Xget_long()
	X{
	X	unsigned int nibble[4];
	X		nibble[0] = get_byte();
	X		nibble[1] = get_byte();
	X		nibble[2] = get_byte();
	X		nibble[3] = get_byte();
	X	return (long)	((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
	Xprocess_local_file_header()
	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	if (debugging) {
	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	: %d\n",lrec.last_mod_file_time);
	X	printf("Mod date	: %d\n",lrec.last_mod_file_date);
	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	csize = lrec.compressed_size;
	X	cusize = lrec.uncompressed_size;
	X	cmethod = lrec.compression_method;
	X
	X 	crccode = INITCRC;
	X	extract_member(); 
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xprocess_central_file_header()
	X{ 
	X	central_directory_file_header rec; 
	X	char filename[STRSIZ];
	X	char extra[STRSIZ];
	X	char comment[STRSIZ];
	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	get_string(rec.file_comment_length,comment); 
	X
	X	crccode = INITCRC;
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xprocess_end_central_dir()
	X{ 
	X	end_central_dir_record rec; 
	X	char comment[STRSIZ];
	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	get_string(rec.zipfile_comment_length,comment); 
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xprocess_headers()
	X{ 
	X	longint sig;
	X
	X	while (1)
	X	{ 
	X	if (read(zipfd,&sig,sizeof(sig)) != sizeof(sig))
	X	  return;
	X	else 
	X
	X	if (sig == local_file_header_signature) 
	X	  process_local_file_header();
	X	else 
	X
	X	if (sig == central_file_header_signature) 
	X	  process_central_file_header();
	X	else 
	X
	X	if (sig == end_central_dir_signature) 
	X	{ 
	X	  process_end_central_dir(); 
	X	  return;
	X	} 
	X
	X	else 
	X	{ 
	X	  printf("Invalid Zipfile Header\n"); 
	X	  return;
	X	} 
	X	} 
	X
	X} 
	X
	X
	X/* ---------------------------------------------------------- */ 
	X
	Xextract_zipfile()
	X{ 
	X	zipfd = open(zipfn,O_RDONLY);
	X	if (zipfd < 1) {
	X	printf("Can't open input file: %s\n",zipfn);
	X	return;
	X	}
	X
	X	process_headers();
	X 
	X	close(zipfd);
	X} 
	X
	X
	X/* ---------------------------------------------------------- */
	X/*
	X * main program
	X *
	X */ 
	X
	Xmain(argc, argv)
	Xint argc;
	Xchar **argv;
	X{
	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	printf("\n"); 
	X	printf("%s\n",version); 
	X	printf("Courtesy of: S.H.Smith and The Tool Shop BBS,(602) 279-2673.");
	X	printf("\n\n");
	X
	X	while ((c = getopt (argc, argv, "dtv")) != EOF)
	X	{
	X	switch (c) {
	X		case 'd':	debugging++; break;
	X		case 't':	test_zip++; break;
	X		case 'v':	verbose++; break;
	X		default:	short_help();
	X		}
	X	}
	X
	X	strcpy(zipfn,argv[optind]);
	X	if (strlen(zipfn) == 0)
	X		short_help();
	X
	X	if (strchr(zipfn,'.') == NULL)
	X	strcat(zipfn,".zip");
	X
	X	extract_zipfile(); 
	X
	X	exit(0);
	X}
	X
	Xshort_help()
	X{
	X	printf("Usage:	UnZip -tv file[.zip]\n");
	X	exit(1);
	X}
SHAR_EOF
if test 19022 -ne "`wc -c < 'unzipbsd.c'`"
then
	echo shar: error transmitting "'unzipbsd.c'" '(should have been 19022 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'addbfcrc.c'" '(6391 characters)'
if test -f 'addbfcrc.c'
then
	echo shar: will not over-write existing file "'addbfcrc.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'addbfcrc.c'
	X/* @(#) addbfcrc.c 1.5 89/03/08 14:58:35 */
	X/* Most of following CRC-32 stuff is from zmodem source code */
	X
	X#ifndef LINT
	Xstatic char sccsid[]="::[[ @(#) addbfcrc.c 1.6 89/03/10 19:08:47 ]]::";
	X#endif
	X
	X/* I claim no copyright over the contents of this file.  -- Rahul Dhesi */
	X
	X/*
	XChecksum:  951252172      (check or update this with "brik")
	X*/
	X
	X
	Xlong crccode;
	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
	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/* 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
	Xlong crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
	X      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
	X      0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
	X      0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
	X      0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
	X      0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
	X      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
	X      0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
	X      0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
	X      0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
	X      0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
	X      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
	X      0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
	X      0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
	X      0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
	X      0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
	X      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
	X      0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
	X      0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
	X      0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
	X      0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
	X      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
	X      0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
	X      0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
	X      0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
	X      0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
	X      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
	X      0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
	X      0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
	X      0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
	X      0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
	X      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
	X      0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
	X      0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
	X      0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
	X      0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
	X      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
	X      0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
	X      0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
	X      0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
	X      0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
	X      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
	X      0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
	X      0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
	X      0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
	X      0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
	X      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
	X      0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
	X      0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
	X      0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
	X      0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
	X      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
	X      0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
	X      0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
	X      0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
	X      0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
	X      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
	X      0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
	X      0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
	X      0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
	X      0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
	X      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
	X      0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
	X      0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
	X      0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
	X};
	X
	Xaddbfcrc (buf, size)
	Xregister char *buf;
	Xregister int size;
	X{
	X   int i;
	X   for (i = 0;  i < size;  i ++) {
	X      crccode = crc_32_tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^
	X         (((crccode) >> 8) & 0x00FFFFFFL);
	X   }
	X}
SHAR_EOF
if test 6391 -ne "`wc -c < 'addbfcrc.c'`"
then
	echo shar: error transmitting "'addbfcrc.c'" '(should have been 6391 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
 _ _ _                          __
' ) ) )      /          /)     /  `       /      /)	Michael Enkelis
 / / / o _. /_  __. _  //     /--   __   /_  _  // o _ 	tektronix!vice!michaele
/ ' (_(_(__/ /_(_(_(<_(/_    (___, /) )_/ <_(<_(/_(_/_)_    (503) 627-4099

bob@conexch.UUCP (Bob Best) (04/10/89)

The following patch fixes a bug that was causing an extra (null) byte to be
appended to some files on extraction.  The type declaration of parameter
's' in get_string() has also been fixed.

*** unzipbsd.c~	Sun Apr  9 10:33:47 1989
--- unzipbsd.c	Sun Apr  9 10:39:40 1989
***************
*** 267,273 ****
  
  get_string(len, s)
  int len;
! char *s[];
  { 
  	read(zipfd,s,len);
  	s[len] = 0;
--- 267,273 ----
  
  get_string(len, s)
  int len;
! char *s;
  { 
  	read(zipfd,s,len);
  	s[len] = 0;
***************
*** 811,817 ****
  		 while ((!zipeof)) 
  		 { 
  			ReadByte(&b); 
! 			OutByte(b); 
  		 } 
  		} 
  	break; 
--- 811,818 ----
  		 while ((!zipeof)) 
  		 { 
  			ReadByte(&b); 
! 			if (!zipeof) /* bob@dhw68k.cts.com */
! 				OutByte(b); 
  		 } 
  		} 
  	break; 
-- 
Bob Best
bob@dhw68k.cts.com