[comp.sources.mac] AufsTools

np@doc.imperial.ac.uk (Nigel Perry) (02/21/91)

[AufsTools - part 1 of 4]

This package contains programs for use by users of the CAP aufs system.
Programs are provided to convert downloads direct into aufs files,
handle StuffIt archives and manage aufs files. Most programs are
modified versions of exisiting public domain utilites. To build just
run make:

Enjoy.

--
Nigel Perry                                  Department of Computing
                                             Imperial College
Janet: np@uk.ac.ic.doc                       London
ARPA:  np%uk.ac.ic.doc@ucl-cs                SW7
Uucp:  np@icdoc.UUCP, ukc!icdoc!np           England


---
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 4)."
# Contents:  MANIFEST Makefile ReadMe aufslib binhex binhex/8to6.c
#   binhex/Makefile binhex/aufs.h binhex/binhex.1 binhex/binhex.c
#   binhex/crc.c binhex/gethead.c binhex/run.c capit capit/Makefile
#   capit/capit.1 formatted formatted/makeman man man/cleanup.1
#   man/drag.1 man/dup.1 man/m2u.1 man/macp.1 man/newfolder.1
#   man/toaufs.1 man/trash.1 mcvert mcvert/Makefile shell
#   shell/cleanup shell/drag shell/dup shell/m2u shell/macp
#   shell/newfolder shell/toaufs shell/trash shell/u2m stuffit
#   stuffit/Makefile stuffit/sit.1 stuffit/sit.h unstuffit
#   unstuffit/Makefile unstuffit/getopt.c unstuffit/stuffit.h
#   unstuffit/unsit.1 unstuffit/unstuffit.1
# Wrapped by np@asun5 on Mon Dec  3 13:15:53 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(1943 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile                   1	
X ReadMe                     1	
X aufslib                    1	
X binhex                     1	
X binhex/8to6.c              1	
X binhex/Makefile            1	
X binhex/aufs.h              1	
X binhex/binhex.1            1	
X binhex/binhex.c            1	
X binhex/crc.c               1	
X binhex/gethead.c           1	
X binhex/run.c               1	
X capit                      1	
X capit/Makefile             1	
X capit/capit.1              1	
X capit/capit.c              2	
X formatted                  1	
X formatted/makeman          1	
X man                        1	
X man/cleanup.1              1	
X man/drag.1                 1	
X man/dup.1                  1	
X man/m2u.1                  1	
X man/macp.1                 1	
X man/newfolder.1            1	
X man/toaufs.1               1	
X man/trash.1                1	
X mcvert                     1	
X mcvert/Makefile            1	
X mcvert/hqxify.c            3	
X mcvert/mactypes.h          2	
X mcvert/mcvert.1            2	
X mcvert/mcvert.c            3	
X mcvert/unpack.c            2	
X shell                      1	
X shell/cleanup              1	
X shell/drag                 1	
X shell/dup                  1	
X shell/m2u                  1	
X shell/macp                 1	
X shell/newfolder            1	
X shell/toaufs               1	
X shell/trash                1	
X shell/u2m                  1	
X stuffit                    1	
X stuffit/Makefile           1	
X stuffit/sit.1              1	
X stuffit/sit.c              3	
X stuffit/sit.h              1	
X stuffit/updcrc.c           2	
X unstuffit                  1	
X unstuffit/Makefile         1	
X unstuffit/getopt.c         1	
X unstuffit/stuffit.h        1	
X unstuffit/unsit.1          1	
X unstuffit/unsit.c          4	
X unstuffit/unstuffit.1      1	
X unstuffit/updcrc.c         2	
END_OF_FILE
if test 1943 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(746 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XBIN = aufslib
X
Xbin:
X	(cd stuffit; make)
X	(cd unstuffit; make)
X	(cd binhex; make)
X	(cd mcvert; make)
X	(cd capit; make)
X
Xinstall: bin
X	mv stuffit/stuffit $(BIN); strip $(BIN)/stuffit
X	mv stuffit/sit $(BIN); strip $(BIN)/sit
X	mv unstuffit/unstuffit $(BIN); strip $(BIN)/unstuffit
X	mv unstuffit/unsit $(BIN); strip $(BIN)/unsit
X	mv mcvert/mcvert $(BIN); strip $(BIN)/mcvert
X	mv capit/capit $(BIN); strip $(BIN)/capit
X	mv  binhex/binhex $(BIN); strip $(BIN)/binhex
X	mv binhex/unxbin $(BIN); strip $(BIN)/unxbin
X	cp shell/* $(BIN)
X
Xclean:
X	(cd stuffit; make clean)
X	(cd unstuffit; make clean)
X	(cd binhex; make clean)
X	(cd mcvert; make clean)
X	(cd capit; make clean)
X
Xreallyclean: clean
X	rm -f formatted/*.1 aufslib/*
X
Xformat:
X	(cd formatted; makeman)
END_OF_FILE
if test 746 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'ReadMe' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ReadMe'\"
else
echo shar: Extracting \"'ReadMe'\" \(734 characters\)
sed "s/^X//" >'ReadMe' <<'END_OF_FILE'
XPublic Domain Aufs Tools Package
X================================
X
XNigel Perry, Dec 90.
X
XThis package contains programs for use by users of the CAP aufs system.
XPrograms are provided to convert downloads direct into aufs files, handle
XStuffIt archives and manage aufs files. Most programs are modified versions
Xof exisiting public domain utilites. To build just run make:
X
X	make
X		builds binaries in their own directories
X	make install
X		builds binaries & moves them to $(BIN), default
X		./aufslib. Also copies shell scripts to $(BIN).
X	make format
X		builds formatted versions of all the manual pages
X		in the directory formatted.
X	make clean
X		cleans up .o files etc.
X	make reallyclean
X		as clean + wipes aufslib & formatted
X
XEnjoy.
END_OF_FILE
if test 734 -ne `wc -c <'ReadMe'`; then
    echo shar: \"'ReadMe'\" unpacked with wrong size!
fi
# end of 'ReadMe'
fi
if test ! -d 'aufslib' ; then
    echo shar: Creating directory \"'aufslib'\"
    mkdir 'aufslib'
fi
if test ! -d 'binhex' ; then
    echo shar: Creating directory \"'binhex'\"
    mkdir 'binhex'
fi
if test -f 'binhex/8to6.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/8to6.c'\"
else
echo shar: Extracting \"'binhex/8to6.c'\" \(1248 characters\)
sed "s/^X//" >'binhex/8to6.c' <<'END_OF_FILE'
X/*
X * convert 8 bit data stream into 6 bit data stream
X *
X * David Gentzel, Lexeme Corporation
X */
X
X#include <stdio.h>
X
X#define MAXLINELEN	62
X
Xstatic
Xchar tr[]="!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
X
X/*
X * Output a character to the current output file converting from 8 bit to 6 bit
X * representation.  When called with EOF, flush all pending output.
X */
Xvoid putchar_6(c)
Xint c;
X{
X    static unsigned char buf[3];
X    static unsigned int num_bytes = 0;
X    static count = 1;	/* # of characters on current line */
X			    /* start at 1 to include colon */
X
X    if (c == EOF)	/* flush buffer on EOF */
X    {
X	while (num_bytes != 0)
X	    putchar_6(0);
X	count = 1; /* for next file */
X	return;
X    }
X
X    buf[num_bytes++] = c;
X    if (num_bytes == 3)
X    {
X
X	num_bytes = 0;
X	putchar(tr[buf[0] >> 2]);
X	if (count++ > MAXLINELEN)
X	{
X	    count = 0;
X	    putchar('\n');
X	}
X	putchar(tr[((buf[0] & 0x03) << 4) | (buf[1] >> 4)]);
X	if (count++ > MAXLINELEN)
X	{
X	    count = 0;
X	    putchar('\n');
X	}
X	putchar(tr[((buf[1] & 0x0F) << 2) | (buf[2] >> 6)]);
X	if (count++ > MAXLINELEN)
X	{
X	    count = 0;
X	    putchar('\n');
X	}
X	putchar(tr[buf[2] & 0x3F]);
X	if (count++ > MAXLINELEN)
X	{
X	    count = 0;
X	    putchar('\n');
X	}
X    }
X}
END_OF_FILE
if test 1248 -ne `wc -c <'binhex/8to6.c'`; then
    echo shar: \"'binhex/8to6.c'\" unpacked with wrong size!
fi
# end of 'binhex/8to6.c'
fi
if test -f 'binhex/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/Makefile'\"
else
echo shar: Extracting \"'binhex/Makefile'\" \(368 characters\)
sed "s/^X//" >'binhex/Makefile' <<'END_OF_FILE'
XCFLAGS=	-O -Dstrrchr=rindex
XLFLAGS=
XCFILES=	binhex.c gethead.c crc.c run.c 8to6.c
XOFILES=	binhex.o gethead.o crc.o run.o 8to6.o
X
Xunxbin : binhex
X	rm -f unxbin
X	ln binhex unxbin
X
Xbinhex:	$(OFILES)
X	cc -o binhex $(OFILES)
X
Xbinhex.o:	Makefile
Xgethead.o:	Makefile
X
Xdebug:
X	cc -o binhexd -g $(CFILES)
X
Xlint:
X	lint $(LFLAGS) $(CFILES)
X
Xclean:
X	rm -f binhex unxbin $(OFILES)
END_OF_FILE
if test 368 -ne `wc -c <'binhex/Makefile'`; then
    echo shar: \"'binhex/Makefile'\" unpacked with wrong size!
fi
# end of 'binhex/Makefile'
fi
if test -f 'binhex/aufs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/aufs.h'\"
else
echo shar: Extracting \"'binhex/aufs.h'\" \(4134 characters\)
sed "s/^X//" >'binhex/aufs.h' <<'END_OF_FILE'
X/********************************************************************************/
X/* added for aufs, nicked from various places... */
X
X/* following from mcvert program */
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte;     /* one byte, obviously */
Xtypedef unsigned short word;    /* must be 2 bytes */
Xtypedef unsigned long ulong;    /* 4 bytes */
X
X#define NAMELEN 63              /* maximum legal Mac file name length */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks.  The first block is the
Xinfo_header (see below).  Then comes the data fork, null padded to fill the
Xlast block.  Then comes the resource fork, padded to fill the last block.  A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/ 
Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
X                        longs don't align to word boundaries */
X            byte version;           /* there is only a version 0 at this time */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;             /* Locked, Invisible,Bundle, System */
X                                    /* Bozo, Busy, Changed, Init */
X            byte icon_vert[2];      /* Vertical icon position within window */
X            byte icon_horiz[2];     /* Horizontal icon postion in window */
X            byte window_id[2];      /* Window or folder ID. */
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
X            byte rflen[4];          /* Resource Fork length         byte first */
X            byte cdate[4];          /* File's creation date. */
X            byte mdate[4];          /* File's "last modified" date. */
X            byte ilen[2];           /* GetInfo message length */
X	    byte flags2;            /* Finder flags, bits 0-7 */
X	    byte unused[14];       
X	    byte packlen[4];        /* length of total files when unpacked */
X	    byte headlen[2];        /* length of secondary header */
X	    byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
X	    byte readvers;          /* Minimum MacBinary II version needed to read this file */
X            byte crc[2];            /* CRC of the previous 124 bytes */
X	    byte padding[2];        /* two trailing unused bytes */
X            } info_header;
X
X/* end of mcvert stuff */
X/* from CAP aufs documentation */
X
X#define FINFOLEN 32
X#define MAXCLEN 199
Xtypedef struct
X{  /* byte fi_fndr[FINFOLEN]; */	/* finder info */
X   /* what I think the above is... */
X   ulong fndr_type, fndr_creator;
X   word fndr_flags;
X   ulong fndr_loc;
X   word fndr_fldr;
X   word fndr_icon;
X   byte fndr_unused[8];
X   word fndr_comment;
X   ulong fndr_putaway;
X   /* end of fi_fndr */
X
X   word fi_attr;			/* attributes */
X#define FI_MAGIC1 255
X   byte fi_magic1;		/* was: length of comment */
X#define FI_VERSION 0x10		/* version major 1, minor 0 */
X				/* if more than 8 versions then */
X				/* something wrong anyway */
X   byte fi_version;		/* version number */
X#define FI_MAGIC 0xda
X   byte fi_magic;		/* magic word check */
X   byte fi_bitmap;		/* bitmap of included info */
X#define FI_BM_SHORTFILENAME 0x1	/* is this included? */
X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
X   byte fi_shortfilename[12+1];	/* possible short file name */
X   byte fi_macfilename[32+1];	/* possible macintosh file name */
X   byte fi_comln;		/* comment length */
X   byte fi_comnt[MAXCLEN+1];	/* comment string */
X} FinderInfo;
X
X/* end aufs */
X/********************************************************************************/
END_OF_FILE
if test 4134 -ne `wc -c <'binhex/aufs.h'`; then
    echo shar: \"'binhex/aufs.h'\" unpacked with wrong size!
fi
# end of 'binhex/aufs.h'
fi
if test -f 'binhex/binhex.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/binhex.1'\"
else
echo shar: Extracting \"'binhex/binhex.1'\" \(524 characters\)
sed "s/^X//" >'binhex/binhex.1' <<'END_OF_FILE'
X.TH BINHEX L "December 1990"
X.UC
X.SH NAME
Xbinhex \- convert CAP aufs file(s) to Binhex 4.0 Unix file(s)
Xunxbin \- ditto but for *.{rsrc,data,info} format files
X.SH SYNOPSIS
X.B binhex
Xfile(s)
X.br
X.B unxbin
Xfile(s)
X.br
X.SH DESCRIPTION
X.I Binhex
Xconverts CAP aufs file(s) to BinHex 4.0 format and stores them
Xas Unix text (i.e. using Unix LF not Mac CR).
X.I Unxbin
Xdoes the same but for *.{rsrc,data,info} format files.
X.SH AUTHORS
Xbinhex: Nigel Perry (np@doc.ic.ac.uk), based on
X.br
Xunxbin: David Gentzel, Lexeme Corporation
X
END_OF_FILE
if test 524 -ne `wc -c <'binhex/binhex.1'`; then
    echo shar: \"'binhex/binhex.1'\" unpacked with wrong size!
fi
# end of 'binhex/binhex.1'
fi
if test -f 'binhex/binhex.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/binhex.c'\"
else
echo shar: Extracting \"'binhex/binhex.c'\" \(4441 characters\)
sed "s/^X//" >'binhex/binhex.c' <<'END_OF_FILE'
X/*
X * binhex -- binhex aufs files
X *
X * if called binhex handles aufs files, if called unxbin handles *.{rsrc,data,info} files
X * will process multiple files
X *
X * Nigel Perry, Aug 90, np@doc.ic.ac.uk
X *
X * This is a hacked version of...
X *
X * unxbin -- convert files generated by xbin or macget into BinHex 4.0 format.
X *
X * David Gentzel, Lexeme Corporation
X *
X * (c) 1985 David Gentzel
X * may be used but not sold without permission
X *
X * This is based on a Unix(tm) program with the same name and function written
X * by ????.  Original was a series of small programs (8to6, crc, etc.) piped
X * together and run by a shell script.  I completely rewrote the system as a
X * C program (speeding it up considerably, needless to say), added run-length
X * compression, and bullet-proofed (at least partly) the thing.  Unfortunately,
X * I have lost the name of the original poster (to net.sources.mac) without
X * whom this would never have appeared.
X *
X * created dbg 09/10/85 -- Version 1.0
X */
X
X#include <stdio.h>
X#include "aufs.h"
X
X#ifdef VMS
X# define PROGRAMNAME	"unxbin"
X# define EXIT_ERROR	((1 << 28) | 2)
X# ifndef MAXNAMLEN
X#  define MAXNAMLEN	127
X#  define MAXBASENAME	63
X# endif
X#else
X# include <sys/types.h>
X# include <sys/dir.h>
X# define PROGRAMNAME	(argv[0])
X# define AUFSNAME	"binhex"
X# define EXIT_ERROR	1
X# ifndef MAXNAMLEN
X#  ifdef DIRSIZ
X#   define MAXNAMLEN	DIRSIZ
X#  else
X#   define MAXNAMLEN	14
X#  endif
X# endif
X# define MAXBASENAME	(MAXNAMLEN - 2)
X#endif
X
Xextern char *sprintf(), *strrchr();
Xextern void aufs_gethead(), gethead(), fakehead(), make_buffer_crc(), make_file_crc(),
X	    putchar_run();
X
Xmain(argc, argv)
Xint argc;
Xregister char *argv[];
X{
X    register FILE *rsrc, *data, *info;
X    char fbuf[256], infobuf[128];
X    register char *file;
X    int aufs;
X    int i;
X    FinderInfo fndr_info;
X
X    aufs = strcmp(PROGRAMNAME, AUFSNAME) == 0;
X
X    if (argc < 2)
X    {
X	fprintf(stderr, "Usage: %s file(s)\n", PROGRAMNAME);
X	exit(EXIT_ERROR);
X    }
X
X    for(i = 1; i < argc; i++)
X    {
X#ifdef VMS
X	if ((file = strrchr(argv[i], ']')) == NULL)
X	    file = strrchr(argv[i], ':');
X#else
X	file = strrchr(argv[i], '/');
X#endif
X	if (file)
X	    file++;
X	else
X	    file = argv[i];
X	if (strlen(file) > MAXBASENAME)
X	    file[MAXBASENAME] = '\0';
X	file = argv[i];
X	(void) sprintf(fbuf, aufs ? ".resource/%s" : "%s.rsrc", file);
X	fbuf[MAXNAMLEN] = '\0';
X	rsrc = fopen(fbuf, "r");
X	(void) sprintf(fbuf, aufs ? "%s" : "%s.data", file);
X	fbuf[MAXNAMLEN] = '\0';
X	data = fopen(fbuf, "r");
X	if (rsrc == NULL && data == NULL)
X	{
X	    fprintf(stderr, "No resource or data forks for %s\n", argv[i]);
X	    exit(EXIT_ERROR);
X	}
X	if (rsrc == NULL)
X	    fprintf(stderr, "Warning: no resource file %s\n", fbuf);
X	if (data == NULL)
X	    fprintf(stderr, "Warning: no data file %s\n", fbuf);
X	(void) sprintf(fbuf, aufs ? ".finderinfo/%s" : "%s.info", file);
X	fbuf[MAXNAMLEN] = '\0';
X	info = fopen(fbuf, "r");
X	if (info == NULL)
X	    fprintf(stderr, "Warning: no info file %s\n", fbuf);
X
X	if(aufs)
X	{    /* make the .finderinfo file */
X	    FILE *oinfo;
X
X	    sprintf(fbuf, ".finderinfo/%s.Hqx", file);
X	    if((oinfo = fopen(fbuf, "w")) == NULL)
X	    {   perror(fbuf);
X		exit(1);
X	    }
X	    bzero(&fndr_info, sizeof(FinderInfo));
X	    bcopy("TEXT", &fndr_info.fndr_type, 4);
X	    bcopy("BnHq", &fndr_info.fndr_creator, 4);
X	    fndr_info.fi_magic1 = FI_MAGIC1;
X	    fndr_info.fi_version = FI_VERSION;
X	    fndr_info.fi_magic = FI_MAGIC;
X	    fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
X	    strcpy(fndr_info.fi_macfilename, file);
X	    fwrite(&fndr_info, sizeof(FinderInfo), 1, oinfo);
X	    fclose(oinfo);
X	}
X
X	(void) sprintf(fbuf, "%s.Hqx", file);
X	fbuf[MAXNAMLEN] = '\0';
X	if (freopen(fbuf, "w", stdout) == NULL)
X	{
X	    fputs("Couldn't open output file.\n", stderr);
X	    exit(EXIT_ERROR);
X	}
X	fputs("(This file must be converted with BinHex 4.0)\n:", stdout);
X	if (info != NULL)
X	{   if(aufs)
X	    {   (void) fread(&fndr_info, sizeof(FinderInfo), 1, info);
X		(void) fclose(info);
X		aufs_gethead(&fndr_info, data, rsrc, infobuf);
X	    }
X	    else
X	    {   (void) fread(fbuf, 128, 1, info);
X		(void) fclose(info);
X		gethead(fbuf, infobuf);
X	    }
X	}
X	else
X	    fakehead(file, rsrc, data, infobuf);
X	make_buffer_crc(infobuf, 20 + infobuf[0]);
X	make_file_crc(data);
X	if (data != NULL)
X	    (void) fclose(data);
X	make_file_crc(rsrc);
X	if (rsrc != NULL)
X	    (void) fclose(rsrc);
X	putchar_run(EOF);
X	puts(":");
X    }
X    (void) fclose(stdout);
X}
END_OF_FILE
if test 4441 -ne `wc -c <'binhex/binhex.c'`; then
    echo shar: \"'binhex/binhex.c'\" unpacked with wrong size!
fi
# end of 'binhex/binhex.c'
fi
if test -f 'binhex/crc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/crc.c'\"
else
echo shar: Extracting \"'binhex/crc.c'\" \(1488 characters\)
sed "s/^X//" >'binhex/crc.c' <<'END_OF_FILE'
X/*
X * compute the crc used in .hqx files for unxbin
X *
X * David Gentzel, Lexeme Corporation
X *
X * Based on crc code in xbin.c by Darin Adler of TMQ Software.
X */
X
X#include <stdio.h>
X
X#define BYTEMASK	0xFF
X#define WORDMASK	0xFFFF
X#define WORDBIT		0x10000
X
X#define CRCCONSTANT	0x1021
X
Xstatic unsigned int crc;
X
Xextern void putchar_run();
X
X/*
X * Update the crc.
X */
Xstatic void docrc(c)
Xregister unsigned int c;
X{
X    register int i;
X    register unsigned long temp = crc;
X
X    for (i = 0; i < 8; i++)
X    {
X	c <<= 1;
X	if ((temp <<= 1) & WORDBIT)
X	    temp = (temp & WORDMASK) ^ CRCCONSTANT;
X	temp ^= (c >> 8);
X	c &= BYTEMASK;
X    }
X    crc = temp;
X}
X
X/*
X * Copy all characters from file in to the current output file computing a crc
X * as we go.  Append 2 byte crc to the output.  in may be NULL (empty file).
X */
Xvoid make_file_crc(in)
Xregister FILE *in;
X{
X    register int c;
X
X    crc = 0;
X    if (in != NULL)
X	while ((c = getc(in)) != EOF)
X	{
X	    putchar_run(c);
X	    docrc(c);
X	}
X    docrc(0);
X    docrc(0);
X    putchar_run((crc >> 8) & BYTEMASK);
X    putchar_run(crc & BYTEMASK);
X}
X
X/*
X * Copy count characters from buffer in to the current output file computing a
X * crc as we go.  Append 2 byte crc to the output.
X */
Xvoid make_buffer_crc(in, count)
Xregister unsigned char *in;
Xregister int count;
X{
X    crc = 0;
X    while (count--)
X    {
X	putchar_run(*in);
X	docrc(*in++);
X    }
X    docrc(0);
X    docrc(0);
X    putchar_run((crc >> 8) & BYTEMASK);
X    putchar_run(crc & BYTEMASK);
X}
END_OF_FILE
if test 1488 -ne `wc -c <'binhex/crc.c'`; then
    echo shar: \"'binhex/crc.c'\" unpacked with wrong size!
fi
# end of 'binhex/crc.c'
fi
if test -f 'binhex/gethead.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/gethead.c'\"
else
echo shar: Extracting \"'binhex/gethead.c'\" \(4043 characters\)
sed "s/^X//" >'binhex/gethead.c' <<'END_OF_FILE'
X/*
X * Change a .info file into a proper header for a .hqx file
X *
X * David Gentzel, Lexeme Corporation
X *
X * Based on code written by ????.
X */
X
X#include <stdio.h>
X#ifdef VMS
X# include <types.h>
X# include <stat.h>
X#else
X# include <sys/types.h>
X# include <sys/stat.h>
X#endif
X
X#include "aufs.h"
X
X#define NAMEBYTES 63
X#define H_NLENOFF 1
X#define H_NAMEOFF 2
X
X/* 65 <-> 80 is the FInfo structure */
X#define H_TYPEOFF 65
X#define H_AUTHOFF 69
X#define H_FLAGOFF 73
X
X#define H_LOCKOFF 81
X#define H_DLENOFF 83
X#define H_RLENOFF 87
X#define H_CTIMOFF 91
X#define H_MTIMOFF 95
X
X/* Append cnt bytes to the output buffer starting at head[offset]. */
X#define put(cnt, offset) \
X{ \
X    register char *a = &head[(int) offset]; \
X    register int b = (int) (cnt); \
X \
X    while (b--) \
X	*out++ = *a++; \
X}
X
X/* Append cnt bytes to the output buffer starting at string. */
X#define put2(cnt, string) \
X{ \
X    register int b = (int) (cnt); \
X    register char *a = (char *) (string); \
X \
X    while (b--) \
X	*out++ = *a++; \
X}
X
X/* Append cnt bytes to the output buffer starting at string + (cnt - 1) and
X   working backwards. */
X#define put2rev(cnt, string) \
X{ \
X    register int b = (int) (cnt); \
X    register char *a = (char *) (string) + b; \
X \
X    while (b--) \
X	*out++ = *--a; \
X}
X
X/* Build a usable header out of the .info information.  head is the text from
X   the .info file, out is an output buffer. */
Xvoid gethead(head, out)
Xregister char *head, *out;
X{
X    put(1, H_NLENOFF);		/* Name length */
X    put(head[1], H_NAMEOFF);	/* Name */
X    put(1, 0);			/* NULL */
X    put(4, H_TYPEOFF);		/* Type */
X    put(4, H_AUTHOFF);		/* Author */
X    put(2, H_FLAGOFF);		/* Flags */
X    put(4, H_DLENOFF);		/* Data length */
X    put(4, H_RLENOFF);		/* Resource length */
X}
X
X/* Build a usable header out of the .finderinfo information.
X   out is an output buffer. */
Xvoid aufs_gethead(info, data, rsrc, out)
Xregister char *out;
Xregister FinderInfo *info;
XFILE *data, *rsrc;
X{   register int len;
X    long rlen, dlen;
X    struct stat st;
X
X    if(info->fi_bitmap & FI_BM_MACINTOSHFILENAME)
X    {   len = strlen(info->fi_macfilename);
X	*out++ = (char)len;
X	put2(len+1, info->fi_macfilename);
X    }
X    else
X    {   len = strlen(info->fi_shortfilename);
X	*out++ = (char)len;
X	put2(len+1, info->fi_shortfilename);
X    }
X    put2(4, &info->fndr_type);		/* Type */
X    put2(4, &info->fndr_creator);	/* Author */
X    put2(2, &info->fndr_flags);		/* Flags */
X
X    if (rsrc != NULL)
X    {
X	(void) fstat(fileno(rsrc), &st);
X	rlen = (long) st.st_size;
X    }
X    else
X	rlen = 0L;
X    if (data != NULL)
X    {
X	(void) fstat(fileno(data), &st);
X	dlen = (long) st.st_size;
X    }
X    else
X	dlen = 0L;
X    put2(4, &dlen);		/* Data length */
X    put2(4, &rlen);		/* Resource length */
X}
X
X/* Fake a usable header (there was no .info file). */
X/* VMS NOTE:
X	It is possible that the use of fstat to figure the sizes of the
X	.data and .rsrc files will not work correctly if they are not
X	Stream_LF files.  Not easy to get around, but not very common either
X	(will only cause problem if .info file is missing and either .data
X	or .rsrc is not Stream_LF, and xbin creates Stream_LF files).
X*/
Xvoid fakehead(file, rsrc, data, out)
Xchar *file;
XFILE *rsrc, *data;
Xregister char *out;
X{
X    unsigned char flen;
X    long rlen, dlen;
X    char flags[2];
X    struct stat st;
X
X    flen = (unsigned char) strlen(file);
X    if (rsrc != NULL)
X    {
X	(void) fstat(fileno(rsrc), &st);
X	rlen = (long) st.st_size;
X    }
X    else
X	rlen = 0L;
X    if (data != NULL)
X    {
X	(void) fstat(fileno(data), &st);
X	dlen = (long) st.st_size;
X    }
X    else
X	dlen = 0L;
X    flags[0] = '\0';
X    flags[1] = '\0';
X
X    put2(1, &flen);		/* Name length */
X    put2(flen, file);		/* Name */
X    put2(1, "");		/* NULL */
X    put2(4, "TEXT");		/* Type */
X    put2(4, "????");		/* Author */
X    put2(2, flags);		/* Flags */
X#ifdef DONTSWAPINT
X    put2(4, dlen);		/* Data length */
X    put2(4, rlen);		/* Resource length */
X#else
X    put2rev(4, dlen);		/* Data length */
X    put2rev(4, rlen);		/* Resource length */
X#endif
X}
END_OF_FILE
if test 4043 -ne `wc -c <'binhex/gethead.c'`; then
    echo shar: \"'binhex/gethead.c'\" unpacked with wrong size!
fi
# end of 'binhex/gethead.c'
fi
if test -f 'binhex/run.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'binhex/run.c'\"
else
echo shar: Extracting \"'binhex/run.c'\" \(1175 characters\)
sed "s/^X//" >'binhex/run.c' <<'END_OF_FILE'
X/*
X * do run length compression for unxbin
X *
X * David Gentzel, Lexeme Corporation
X */
X
X#include <stdio.h>
X
X#define RUNCHAR	0x90
X#define MAXREP	255
X
Xextern void putchar_6();
X
X/*
X * Output a character to the current output file generating run length
X * compression on the fly.  All output goes through putchar_6 to do conversion
X * from 8 bit to 6 bit format.  When c == EOF, call putchar_6 with EOF to flush
X * pending output.
X */
Xvoid putchar_run(c)
Xregister int c;
X{
X    static unsigned int rep = 1;	/* # of repititions of lastc seen */
X    static int lastc = EOF;		/* last character passed to us */
X
X    if (c == lastc)	/* increment rep */
X    {
X	/* repetition count limited to MAXREP */
X	if (++rep == MAXREP)
X	{
X	    putchar_6(RUNCHAR);
X	    putchar_6(MAXREP);
X	    rep = 1;
X	    lastc = EOF;
X	}
X    }
X    else
X    {
X	switch (rep)
X	{
X	    case 2:	/* not worth running for only 2 reps... */
X		putchar_6(lastc);
X		if (lastc == RUNCHAR)
X		    putchar_6(0);
X		break;
X	    case 1:
X		break;
X	    default:
X		putchar_6(RUNCHAR);
X		putchar_6(rep);
X		break;
X	}
X	putchar_6(c);	/* output character (EOF flushes) */
X	rep = 1;
X	if (c == RUNCHAR)
X	    putchar_6(0);
X	lastc = c;
X    }
X}
END_OF_FILE
if test 1175 -ne `wc -c <'binhex/run.c'`; then
    echo shar: \"'binhex/run.c'\" unpacked with wrong size!
fi
# end of 'binhex/run.c'
fi
if test ! -d 'capit' ; then
    echo shar: Creating directory \"'capit'\"
    mkdir 'capit'
fi
if test -f 'capit/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'capit/Makefile'\"
else
echo shar: Extracting \"'capit/Makefile'\" \(54 characters\)
sed "s/^X//" >'capit/Makefile' <<'END_OF_FILE'
Xcapit: capit.c
X	cc -o capit -O capit.c
Xclean:
X	# nowt
END_OF_FILE
if test 54 -ne `wc -c <'capit/Makefile'`; then
    echo shar: \"'capit/Makefile'\" unpacked with wrong size!
fi
# end of 'capit/Makefile'
fi
if test -f 'capit/capit.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'capit/capit.1'\"
else
echo shar: Extracting \"'capit/capit.1'\" \(498 characters\)
sed "s/^X//" >'capit/capit.1' <<'END_OF_FILE'
X.TH CAPIT L "Decemeber 1990"
X.UC
X.SH NAME
Xcapit \- convert a MacBinary file into a CAP aufs one.
X.SH SYNOPSIS
X.B capit
X[
X.B \-v
X] file(s)
X.br
X.SH DESCRIPTION
X.I Capit
Xconverts files from MacBinary to CAP aufs format and writes them to the current directory,
Xwhich should be a CAP aufs folder.
X.SH OPTION
X.TP
X.B \-v
XVerbose option.  Causes 
X.I capit
Xto list name of each file converted.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk) based on macbin by John M. Sellens (jmsellens@watdragon.uwaterloo.ca).
END_OF_FILE
if test 498 -ne `wc -c <'capit/capit.1'`; then
    echo shar: \"'capit/capit.1'\" unpacked with wrong size!
fi
# end of 'capit/capit.1'
fi
if test ! -d 'formatted' ; then
    echo shar: Creating directory \"'formatted'\"
    mkdir 'formatted'
fi
if test -f 'formatted/makeman' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'formatted/makeman'\"
else
echo shar: Extracting \"'formatted/makeman'\" \(100 characters\)
sed "s/^X//" >'formatted/makeman' <<'END_OF_FILE'
X#!/bin/csh
Xforeach i (../{stuffit,unstuffit,binhex,capit,mcvert,man}/*.1)
X	nroff -man <$i >$i:t
Xend
END_OF_FILE
if test 100 -ne `wc -c <'formatted/makeman'`; then
    echo shar: \"'formatted/makeman'\" unpacked with wrong size!
fi
# end of 'formatted/makeman'
fi
if test ! -d 'man' ; then
    echo shar: Creating directory \"'man'\"
    mkdir 'man'
fi
if test -f 'man/cleanup.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/cleanup.1'\"
else
echo shar: Extracting \"'man/cleanup.1'\" \(335 characters\)
sed "s/^X//" >'man/cleanup.1' <<'END_OF_FILE'
X.TH CLEANUP L "December 1990"
X.UC
X.SH NAME
Xcleanup \- cleanup the current CAP aufs folder
X.SH SYNOPSIS
X.B cleanup
X.SH DESCRIPTION
X.I Cleanup
Xremoves orphaned files stored in the hidden directories of a CAP aufs folder.
XThese occur when Unix commands such as mv & rm are used on CAp aufs files.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 335 -ne `wc -c <'man/cleanup.1'`; then
    echo shar: \"'man/cleanup.1'\" unpacked with wrong size!
fi
# end of 'man/cleanup.1'
fi
if test -f 'man/drag.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/drag.1'\"
else
echo shar: Extracting \"'man/drag.1'\" \(398 characters\)
sed "s/^X//" >'man/drag.1' <<'END_OF_FILE'
X.TH DRAG L "December 1990"
X.UC
X.SH NAME
Xdrag \- rename/move CAP aufs file(s)
X.SH SYNOPSIS
X.B drag
Xfile file
X.br
X.B drag
Xfile(s) folder
X.SH DESCRIPTION
X.I Drag
Xrenames a CAP aufs file, or if there are multiple arguments moves CAP aufs files from one folder to another.
XDo not use
X.I mv
Xto rename/move files as this does not handle the hidden CAP aufs files.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 398 -ne `wc -c <'man/drag.1'`; then
    echo shar: \"'man/drag.1'\" unpacked with wrong size!
fi
# end of 'man/drag.1'
fi
if test -f 'man/dup.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/dup.1'\"
else
echo shar: Extracting \"'man/dup.1'\" \(399 characters\)
sed "s/^X//" >'man/dup.1' <<'END_OF_FILE'
X.TH DUP L "December 1990"
X.UC
X.SH NAME
Xdup \- copy CAP aufs file(s)
X.SH SYNOPSIS
X.B dup
Xfile file
X.br
X.B dup
Xfile(s) folder
X.br
X.SH DESCRIPTION
X.I Dup
Xduplicates a CAP aufs file, if given multiple arguments the last must be
Xa folder and each file will be copied into it.
XDo not use
X.I cp
Xto duplicate files as this does not handle the hidden CAP aufs files.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 399 -ne `wc -c <'man/dup.1'`; then
    echo shar: \"'man/dup.1'\" unpacked with wrong size!
fi
# end of 'man/dup.1'
fi
if test -f 'man/m2u.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/m2u.1'\"
else
echo shar: Extracting \"'man/m2u.1'\" \(338 characters\)
sed "s/^X//" >'man/m2u.1' <<'END_OF_FILE'
X.TH M2U L "December 1990"
X.UC
X.SH NAME
Xm2u \- convert file from Mac to Unix text
X.br
Xu2m \- convert file from Unix to Mac text
X.SH SYNOPSIS
X.B m2u
Xfile(s)
X.br
X.B u2m
Xfile(s)
X.SH DESCRIPTION
XThese commands convert files between Mac & Unix text formats i.e.
Xthe convert CR's to LF's and vice versa.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 338 -ne `wc -c <'man/m2u.1'`; then
    echo shar: \"'man/m2u.1'\" unpacked with wrong size!
fi
# end of 'man/m2u.1'
fi
if test -f 'man/macp.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/macp.1'\"
else
echo shar: Extracting \"'man/macp.1'\" \(361 characters\)
sed "s/^X//" >'man/macp.1' <<'END_OF_FILE'
X.TH MACP L "December 1990"
X.UC
X.SH NAME
Xmacp \- list an CAP aufs file
X.SH SYNOPSIS
X.B macp
Xfile(s)
X.SH DESCRIPTION
X.I Macp
Xlists the given files using your standard pager, obtained from $PAGER, which is usually
X.I more
Xor
X.I less .
XDo not use the Unix pagers directly as CAP aufs files use CR and not LF as end of line.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 361 -ne `wc -c <'man/macp.1'`; then
    echo shar: \"'man/macp.1'\" unpacked with wrong size!
fi
# end of 'man/macp.1'
fi
if test -f 'man/newfolder.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/newfolder.1'\"
else
echo shar: Extracting \"'man/newfolder.1'\" \(296 characters\)
sed "s/^X//" >'man/newfolder.1' <<'END_OF_FILE'
X.TH NEWFOLDER L "December 1990"
X.UC
X.SH NAME
Xnewfolder \- create CAP aufs folder(s)
X.SH SYNOPSIS
X.B newfolder
Xfolder(s)
X.SH DESCRIPTION
X.I Newfolder
Xcreates CAP aufs folders.
XDo not use
X.I mkdir
Xto do this as it does not handle the hidden CAP aufs files.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 296 -ne `wc -c <'man/newfolder.1'`; then
    echo shar: \"'man/newfolder.1'\" unpacked with wrong size!
fi
# end of 'man/newfolder.1'
fi
if test -f 'man/toaufs.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/toaufs.1'\"
else
echo shar: Extracting \"'man/toaufs.1'\" \(656 characters\)
sed "s/^X//" >'man/toaufs.1' <<'END_OF_FILE'
X.TH TOAUFS L "December 1990"
X.UC
X.SH NAME
Xtoaufs \- decode Binhex 4.0 files to CAP aufs format
X.SH SYNOPSIS
X.B toaufs
Xfile(s)
X.SH DESCRIPTION
X.I Toaufs
Xtakes a collection of files, joins them as appropriate, discards gumph
Xsuch as news headers at top & bottom, unbinhexes them and stores them
Xas CAP aufs files in the current directory, which should be a CAP aufs folder.
XTo use 
X.I toaufs
Xto convert files sent as news articles save each part in a file using
Xan ascending alphanumeric sequence of names e.g. file.1, file.2 etc.,
Xand then pass them all to
X.I toaufs ,
Xe.g. toaufs file.*.
X.SH SEE ALSO
Xmcvert, capit
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 656 -ne `wc -c <'man/toaufs.1'`; then
    echo shar: \"'man/toaufs.1'\" unpacked with wrong size!
fi
# end of 'man/toaufs.1'
fi
if test -f 'man/trash.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'man/trash.1'\"
else
echo shar: Extracting \"'man/trash.1'\" \(347 characters\)
sed "s/^X//" >'man/trash.1' <<'END_OF_FILE'
X.TH TRASH L "December 1990"
X.UC
X.SH NAME
Xtrash \- delete a CAP aufs file
X.SH SYNOPSIS
X.B trash
Xfile(s)
X.SH DESCRIPTION
X.I Trash
Xsimply deletes the given CAP aufs files. Don't use
X.I rm
Xto delete CAP aufs files as it will not handle the multiple forks
Xcorrectly, leaving hidden unwanted files on your disc.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk)
END_OF_FILE
if test 347 -ne `wc -c <'man/trash.1'`; then
    echo shar: \"'man/trash.1'\" unpacked with wrong size!
fi
# end of 'man/trash.1'
fi
if test ! -d 'mcvert' ; then
    echo shar: Creating directory \"'mcvert'\"
    mkdir 'mcvert'
fi
if test -f 'mcvert/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/Makefile'\"
else
echo shar: Extracting \"'mcvert/Makefile'\" \(362 characters\)
sed "s/^X//" >'mcvert/Makefile' <<'END_OF_FILE'
XCSOURCES = mcvert.c hqxify.c unpack.c
XSOURCES = mcvert.c hqxify.c unpack.c mactypes.h Makefile
XOBJECTS = mcvert.o hqxify.o unpack.o
XBIN = .
XCFLAGS = -O -DBSD
X
Xmcvert: $(OBJECTS)
X	cc $(CFLAGS) $(OBJECTS) -s -o $(BIN)/mcvert
X
X$(OBJECTS): mactypes.h
X
Xprint: 
X	lpr -p -Pvmslp $(SOURCES)
X
Xshar:
X	shar $(SOURCES) mcvert.1 >mcvert.shar
X
Xclean:
X	rm -f mcvert $(OBJECTS)
END_OF_FILE
if test 362 -ne `wc -c <'mcvert/Makefile'`; then
    echo shar: \"'mcvert/Makefile'\" unpacked with wrong size!
fi
# end of 'mcvert/Makefile'
fi
if test ! -d 'shell' ; then
    echo shar: Creating directory \"'shell'\"
    mkdir 'shell'
fi
if test -f 'shell/cleanup' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/cleanup'\"
else
echo shar: Extracting \"'shell/cleanup'\" \(120 characters\)
sed "s/^X//" >'shell/cleanup' <<'END_OF_FILE'
X# clean up an Aufs folder
Xforeach i ({.resource,.finderinfo}/*)
X	if(! -e "$i:t") then
X		ls -l "$i"
X		rm "$i"
X	endif
Xend
END_OF_FILE
if test 120 -ne `wc -c <'shell/cleanup'`; then
    echo shar: \"'shell/cleanup'\" unpacked with wrong size!
fi
chmod +x 'shell/cleanup'
# end of 'shell/cleanup'
fi
if test -f 'shell/drag' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/drag'\"
else
echo shar: Extracting \"'shell/drag'\" \(513 characters\)
sed "s/^X//" >'shell/drag' <<'END_OF_FILE'
X#
Xset echo
Xset argc = $#argv
Xif( $argc > 2 ) then
X	set dest = $argv[argc]
X	foreach i ( $argv[-(argc-1)] )
X		set h1 = $i:h
X		if( $h1 == $i ) set h1 = "."
X		mv $i $dest
X		mv h1/.finderinfo/$i:t $dest/.finderinfo
X		mv h1/.resource/$i:t $dest/.resource
X	end
Xelse
X	set h1 = $argv[1]:h
X	if( $h1 == $argv[1] ) set h1 = "."
X	set h2 = $argv[2]:h
X	if( $h2 == $argv[2] ) set h2 = "."
X	mv $argv[1] $argv[2]
X	mv $h1/.finderinfo/$argv[1]:t $h2/.finderinfo/$argv[2]:t
X	mv $h1/.resource/$argv[1]:t $h2/.resource/$argv[2]:t
Xendif
END_OF_FILE
if test 513 -ne `wc -c <'shell/drag'`; then
    echo shar: \"'shell/drag'\" unpacked with wrong size!
fi
chmod +x 'shell/drag'
# end of 'shell/drag'
fi
if test -f 'shell/dup' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/dup'\"
else
echo shar: Extracting \"'shell/dup'\" \(513 characters\)
sed "s/^X//" >'shell/dup' <<'END_OF_FILE'
X#
Xset echo
Xset argc = $#argv
Xif( $argc > 2 ) then
X	set dest = $argv[argc]
X	foreach i ( $argv[-(argc-1)] )
X		set h1 = $i:h
X		if( $h1 == $i ) set h1 = "."
X		cp $i $dest
X		cp h1/.finderinfo/$i:t $dest/.finderinfo
X		cp h1/.resource/$i:t $dest/.resource
X	end
Xelse
X	set h1 = $argv[1]:h
X	if( $h1 == $argv[1] ) set h1 = "."
X	set h2 = $argv[2]:h
X	if( $h2 == $argv[2] ) set h2 = "."
X	cp $argv[1] $argv[2]
X	cp $h1/.finderinfo/$argv[1]:t $h2/.finderinfo/$argv[2]:t
X	cp $h1/.resource/$argv[1]:t $h2/.resource/$argv[2]:t
Xendif
END_OF_FILE
if test 513 -ne `wc -c <'shell/dup'`; then
    echo shar: \"'shell/dup'\" unpacked with wrong size!
fi
chmod +x 'shell/dup'
# end of 'shell/dup'
fi
if test -f 'shell/m2u' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/m2u'\"
else
echo shar: Extracting \"'shell/m2u'\" \(83 characters\)
sed "s/^X//" >'shell/m2u' <<'END_OF_FILE'
X#
Xset f = _tmp_$$
Xforeach i ($argv)
X	mv $i $f
X	tr '\015' '\012' <$f >$i
X	rm $f
Xend
END_OF_FILE
if test 83 -ne `wc -c <'shell/m2u'`; then
    echo shar: \"'shell/m2u'\" unpacked with wrong size!
fi
chmod +x 'shell/m2u'
# end of 'shell/m2u'
fi
if test -f 'shell/macp' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/macp'\"
else
echo shar: Extracting \"'shell/macp'\" \(55 characters\)
sed "s/^X//" >'shell/macp' <<'END_OF_FILE'
X#
Xforeach i ($argv)
X	tr '\015' '\012' <$i | $PAGER
Xend
END_OF_FILE
if test 55 -ne `wc -c <'shell/macp'`; then
    echo shar: \"'shell/macp'\" unpacked with wrong size!
fi
chmod +x 'shell/macp'
# end of 'shell/macp'
fi
if test -f 'shell/newfolder' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/newfolder'\"
else
echo shar: Extracting \"'shell/newfolder'\" \(99 characters\)
sed "s/^X//" >'shell/newfolder' <<'END_OF_FILE'
X#
Xset u = `umask`
Xumask 007
Xforeach i ($argv)
X   mkdir $i $i/.finderinfo $i/.resource
Xend
Xumask $u
END_OF_FILE
if test 99 -ne `wc -c <'shell/newfolder'`; then
    echo shar: \"'shell/newfolder'\" unpacked with wrong size!
fi
chmod +x 'shell/newfolder'
# end of 'shell/newfolder'
fi
if test -f 'shell/toaufs' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/toaufs'\"
else
echo shar: Extracting \"'shell/toaufs'\" \(71 characters\)
sed "s/^X//" >'shell/toaufs' <<'END_OF_FILE'
X#
Xsetenv MAC_EXT .$$conv
Xmcvert -v $argv
Xcapit *$MAC_EXT
Xrm *$MAC_EXT
X
END_OF_FILE
if test 71 -ne `wc -c <'shell/toaufs'`; then
    echo shar: \"'shell/toaufs'\" unpacked with wrong size!
fi
chmod +x 'shell/toaufs'
# end of 'shell/toaufs'
fi
if test -f 'shell/trash' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/trash'\"
else
echo shar: Extracting \"'shell/trash'\" \(64 characters\)
sed "s/^X//" >'shell/trash' <<'END_OF_FILE'
X#
Xforeach i ($argv)
X   rm -f $i .finderinfo/$i .resource/$i
Xend
END_OF_FILE
if test 64 -ne `wc -c <'shell/trash'`; then
    echo shar: \"'shell/trash'\" unpacked with wrong size!
fi
chmod +x 'shell/trash'
# end of 'shell/trash'
fi
if test -f 'shell/u2m' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell/u2m'\"
else
echo shar: Extracting \"'shell/u2m'\" \(83 characters\)
sed "s/^X//" >'shell/u2m' <<'END_OF_FILE'
X#
Xset f = _tmp_$$
Xforeach i ($argv)
X	mv $i $f
X	tr '\012' '\015' <$f >$i
X	rm $f
Xend
END_OF_FILE
if test 83 -ne `wc -c <'shell/u2m'`; then
    echo shar: \"'shell/u2m'\" unpacked with wrong size!
fi
chmod +x 'shell/u2m'
# end of 'shell/u2m'
fi
if test ! -d 'stuffit' ; then
    echo shar: Creating directory \"'stuffit'\"
    mkdir 'stuffit'
fi
if test -f 'stuffit/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuffit/Makefile'\"
else
echo shar: Extracting \"'stuffit/Makefile'\" \(122 characters\)
sed "s/^X//" >'stuffit/Makefile' <<'END_OF_FILE'
Xstuffit: sit
X	rm -f stuffit
X	ln sit stuffit
X
Xsit:	sit.o updcrc.o
X	cc -o sit sit.o updcrc.o
X
Xclean:
X	rm -f stuffit sit *.o
END_OF_FILE
if test 122 -ne `wc -c <'stuffit/Makefile'`; then
    echo shar: \"'stuffit/Makefile'\" unpacked with wrong size!
fi
# end of 'stuffit/Makefile'
fi
if test -f 'stuffit/sit.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuffit/sit.1'\"
else
echo shar: Extracting \"'stuffit/sit.1'\" \(1006 characters\)
sed "s/^X//" >'stuffit/sit.1' <<'END_OF_FILE'
X.TH SIT L "December 1990"
X.UC
X.SH NAME
Xstuffit \- create a Stuffit archive from Unix text or CAP aufs files
X.br
Xsit \- create a Stuffit archive from Unix text or *.{rsrc,data,info} files
X.SH SYNOPSIS
X.B stuffit
X[
X.B \-ru
X] [
X.B \-o
X.I output
X] [
X.B \-C
X.I creator
X] [
X.B \-T
X.I type
X] file
X.br
X.B sit
X[
X.B \-ru
X] [
X.B \-o
X.I output
X] [
X.B \-C
X.I creator
X] [
X.B \-T
X.I type
X] file
X.br
X.SH DESCRIPTION
XCreate a Stuffit archive from CAP aufs (stuffit), *.{rsrc,data,info} (sit) or
XUnix text (both) files.
X.SH OPTIONS
X.TP
X.B \-r
XRemove input files when done.
X.TP
X.B \-o output
XSpecify name of output file. Defaults to
X.I archive.sit .
X.TP
X.B \-u
XInput files are Unix text not CAP aufs (stuffit) or *.{rsrc,data,info} (sit).
X.TP
X.B \-C creator
XSet files creator when input is Unix text, defaults to KAHL.
X.TP
X.B \-T type
XSet files type wehn input is Unix text, defaults to TEXT.
X.SH AUTHORS
Xstuffit: Nigel Perry (np@doc.ic.ac.uk), based on
X.br
Xsit: Tom Bereiter ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
END_OF_FILE
if test 1006 -ne `wc -c <'stuffit/sit.1'`; then
    echo shar: \"'stuffit/sit.1'\" unpacked with wrong size!
fi
# end of 'stuffit/sit.1'
fi
if test -f 'stuffit/sit.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuffit/sit.h'\"
else
echo shar: Extracting \"'stuffit/sit.h'\" \(1834 characters\)
sed "s/^X//" >'stuffit/sit.h' <<'END_OF_FILE'
X
X/* sit.h: contains declarations for SIT headers */
X
Xtypedef struct sitHdr {		/* 22 bytes */
X	u_char	sig1[4];		/* = 'SIT!' -- for verification */
X	u_char	numFiles[2];	/* number of files in archive */
X	u_char	arcLen[4];		/* length of entire archive incl. */
X	u_char	sig2[4];		/* = 'rLau' -- for verification */
X	u_char	version;		/* version number */
X	char reserved[7];
X};
X
Xtypedef struct fileHdr {	/* 112 bytes */
X	u_char	compRMethod;		/* rsrc fork compression method */
X	u_char	compDMethod;		/* data fork compression method */
X	u_char	fName[64];			/* a STR63 */
X	char	fType[4];			/* file type */
X	char	fCreator[4];		/* creator... */
X	char	FndrFlags[2];		/* copy of Finder flags */
X	char	cDate[4];			/* creation date */
X	char	mDate[4];			/* !restored-compat w/backup prgms */
X	u_char	rLen[4];			/* decom rsrc length */
X	u_char	dLen[4];			/* decomp data length */
X	u_char	cRLen[4];			/* compressed lengths */
X	u_char	cDLen[4];
X	u_char	rsrcCRC[2];			/* crc of rsrc fork */
X	u_char	dataCRC[2];			/* crc of data fork */
X	char	reserved[6];
X	u_char	hdrCRC[2];			/* crc of file header */
X};
X
X/* file format is:
X	sitArchiveHdr
X		file1Hdr
X			file1RsrcFork
X			file1DataFork
X		file2Hdr
X			file2RsrcFork
X			file2DataFork
X		.
X		.
X		.
X		fileNHdr
X			fileNRsrcFork
X			fileNDataFork
X*/
X
X
X
X/* compression methods */
X#define noComp	0	/* just read each byte and write it to archive */
X#define repComp 1	/* RLE compression */
X#define lpzComp 2	/* LZW compression */
X#define hufComp 3	/* Huffman compression */
X
X/* all other numbers are reserved */
X
X/*
X * the format of a *.info file made by xbin
X */
Xstruct infohdr {
X	char	res0;
X	char	name[64];	/*  2 (a str 63) */
X	char	type[4];	/* 65 */
X	char	creator[4];	/* 69 */
X	char	flag[2];	/* 73 */
X	char	res1[8];
X	char	dlen[4];	/* 83 */
X	char	rlen[4];	/* 87 */
X	char	ctime[4];	/* 91 */
X	char	mtime[4];	/* 95 */
X};
END_OF_FILE
if test 1834 -ne `wc -c <'stuffit/sit.h'`; then
    echo shar: \"'stuffit/sit.h'\" unpacked with wrong size!
fi
# end of 'stuffit/sit.h'
fi
if test ! -d 'unstuffit' ; then
    echo shar: Creating directory \"'unstuffit'\"
    mkdir 'unstuffit'
fi
if test -f 'unstuffit/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/Makefile'\"
else
echo shar: Extracting \"'unstuffit/Makefile'\" \(245 characters\)
sed "s/^X//" >'unstuffit/Makefile' <<'END_OF_FILE'
XGETOPT = 
X#GETOPT = getopt.o
X
Xunstuffit: unsit
X	rm -f unstuffit
X	ln unsit unstuffit
X
Xunsit : unsit.o updcrc.o $(GETOPT)
X	cc -o unsit unsit.o updcrc.o $(GETOPT)
X
Xunsit.o : unsit.c stuffit.h
Xgetopt.o : getopt.c
X
X
Xclean:
X	rm -f unstuffit unsit *.o
END_OF_FILE
if test 245 -ne `wc -c <'unstuffit/Makefile'`; then
    echo shar: \"'unstuffit/Makefile'\" unpacked with wrong size!
fi
# end of 'unstuffit/Makefile'
fi
if test -f 'unstuffit/getopt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/getopt.c'\"
else
echo shar: Extracting \"'unstuffit/getopt.c'\" \(1074 characters\)
sed "s/^X//" >'unstuffit/getopt.c' <<'END_OF_FILE'
X/*
X * getopt - get option letter from argv
X */
X
X#include <stdio.h>
X
Xchar	*optarg;	/* Global argument pointer. */
Xint	optind = 0;	/* Global argv index. */
X
Xstatic char	*scan = NULL;	/* Private scan pointer. */
X
Xextern char	*index();
X
Xint
Xgetopt(argc, argv, optstring)
Xint argc;
Xchar *argv[];
Xchar *optstring;
X{
X	register char c;
X	register char *place;
X
X	optarg = NULL;
X
X	if (scan == NULL || *scan == '\0') {
X		if (optind == 0)
X			optind++;
X	
X		if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return(EOF);
X		if (strcmp(argv[optind], "--")==0) {
X			optind++;
X			return(EOF);
X		}
X	
X		scan = argv[optind]+1;
X		optind++;
X	}
X
X	c = *scan++;
X	place = index(optstring, c);
X
X	if (place == NULL || c == ':') {
X		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
X		return('?');
X	}
X
X	place++;
X	if (*place == ':') {
X		if (*scan != '\0') {
X			optarg = scan;
X			scan = NULL;
X		} else if (optind < argc) {
X			optarg = argv[optind];
X			optind++;
X		} else {
X			fprintf(stderr, "%s: -%c argument missing\n", argv[0], c);
X			return('?');
X		}
X	}
X
X	return(c);
X}
X
END_OF_FILE
if test 1074 -ne `wc -c <'unstuffit/getopt.c'`; then
    echo shar: \"'unstuffit/getopt.c'\" unpacked with wrong size!
fi
# end of 'unstuffit/getopt.c'
fi
if test -f 'unstuffit/stuffit.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/stuffit.h'\"
else
echo shar: Extracting \"'unstuffit/stuffit.h'\" \(1871 characters\)
sed "s/^X//" >'unstuffit/stuffit.h' <<'END_OF_FILE'
X/* StuffIt.h: contains declarations for SIT headers */
X
Xtypedef struct sitHdr {			/* 22 bytes */
X	OSType	signature; 		/* = 'SIT!' -- for verification */
X	unsigned short	numFiles;	/* number of files in archive */
X	unsigned long	arcLength;	/* length of entire archive incl.
X						hdr. -- for verification */
X	OSType	signature2;		/* = 'rLau' -- for verification */
X	unsigned char	version;	/* version number */
X	char reserved[7];
X};
X
Xtypedef struct fileHdr {		/* 112 bytes */
X	unsigned char	compRMethod;	/* rsrc fork compression method */
X	unsigned char	compDMethod;	/* data fork compression method */
X	unsigned char	fName[64];	/* a STR63 */
X	OSType	fType;			/* file type */
X	OSType	fCreator;		/* er... */
X	short FndrFlags;		/* copy of Finder flags.  For our
X						purposes, we can clear:
X						busy,onDesk */
X	unsigned long	creationDate;
X	unsigned long	modDate;	/* !restored-compat w/backup prgms */
X	unsigned long	rsrcLength;	/* decompressed lengths */
X	unsigned long	dataLength;
X	unsigned long	compRLength;	/* compressed lengths */
X	unsigned long	compDLength;
X	unsigned short rsrcCRC;		/* crc of rsrc fork */
X	unsigned short dataCRC;		/* crc of data fork */
X	char reserved[6];
X	unsigned short hdrCRC;		/* crc of file header */
X};
X
X
X/* file format is:
X	sitArchiveHdr
X		file1Hdr
X			file1RsrcFork
X			file1DataFork
X		file2Hdr
X			file2RsrcFork
X			file2DataFork
X		.
X		.
X		.
X		fileNHdr
X			fileNRsrcFork
X			fileNDataFork
X*/
X
X
X
X/* compression methods */
X#define noComp 	0	/* just read each byte and write it to archive */
X#define rleComp 1	/* RLE compression */
X#define lzwComp 2	/* LZW compression */
X#define hufComp 3	/* Huffman compression */
X
X#define encrypted 16	/* bit set if encrypted.  ex: encrypted+lpzComp */
X
X#define startFolder 32	/* marks start of a new folder */
X#define endFolder 33	/* marks end of the last folder "started" */
X
X/* all other numbers are reserved */
END_OF_FILE
if test 1871 -ne `wc -c <'unstuffit/stuffit.h'`; then
    echo shar: \"'unstuffit/stuffit.h'\" unpacked with wrong size!
fi
# end of 'unstuffit/stuffit.h'
fi
if test -f 'unstuffit/unsit.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/unsit.1'\"
else
echo shar: Extracting \"'unstuffit/unsit.1'\" \(4233 characters\)
sed "s/^X//" >'unstuffit/unsit.1' <<'END_OF_FILE'
X.TH UNSIT L "Septermber 28, 1988"
X.UC
X.SH NAME
Xunsit \- extract/list files in a Macintosh Stuffit archive file
X.SH SYNOPSIS
X.B unsit
X[
X.B \-rdulM
X] [
X-vqfm
X] file
X.br
X.SH DESCRIPTION
XFor the Stuffit archive file listed, 
X.I unsit
Xextracts the files in the archive into separate files.
XThis makes it possible, for example, to separate a large StuffIt file
Xinto component files for selective downloading, rather than
Xdownloading the larger archive file just to extract a single, small
Xfile.  It also allows the use of StuffIt to compress a group of files
Xinto a single, smaller archive that can be uploaded to a Unix system
Xfor storage, printing, etc.
X.PP
XIn the normal mode, both the data and the resource forks of the
Xcomponent Macintosh files in the archive are extracted and stored in
XUnix files with the extension
X.I .data
Xand 
X.I .rsrc
Xappended to the end of the Macintosh file name.
XIn addition, a 
X.I .info
Xfile will be created with the Finder information.
XThese three file are compatible with the
X.I macput
Xprogram for downloading to a Mac running MacTerminal.  The output files can
Xalso be generated in the MacBinary format which is easier to use if they are to
Xbe sent to the Mac over a network connection using an FTP program.  The
XMacBinary format file will have the same name as the file would have on the
XMac.  If only the data or resource fork is extracted, no addition extension is
Xappended to the Mac file name.  Characters in the Mac file name that are
Xillegal (or unwieldy, like spaces) are changed to underscores in the Unix file
Xname.  The true Mac file name is retained internally in the MacBinary file or
Xin the
X.I .info
Xfile and is restored when the file is downloaded.
X.PP
XStuffIt version 1.5 has the ability to archive a group of files and folders
Xin such a way that the hierarchical relationship of the files and folders
Xis maintained.
X.I Unsit
Xversion 1.5 can unpack files archived in this manner and place them in
Xcorresponding subdirectories so as to maintain the hierarchy.  As an option,
Xthe hierarcy can be flattened out and all the files stored in the current
Xdirectory.
X.PP
XThe options are similar to those for 
X.I macput
Xand
X.I unpit.
X.TP
X.B \-M
XGenerate output files in MacBinary format instead of the .data, .rsrc,
Xand .info format.
X.TP
X.B \-f
XFor StuffIt files containing a "Hierarchy Maintained Folder" entry, extract the
Xfiles into a "flat" organization (all in the current directory) rather than
Xmaintaining the hierarchy by creating new directories, etc.
XDefault is to maintain the hierarchical folder organization.
X.TP
X.B \-l
XList the files in the archive but do not extract them.  The name, size,
Xtype, and creator of each file is listed.
X.TP
X.B \-m
XAssumes the input file in MacBinary format rather than macput/macget
Xformat and skips over the MacBinary header.
X.TP
X.B \-r
XExtract resources forks only.
X.TP
X.B \-d
XExtract data forks only.
X.TP
X.B \-u
XExtract data fork and change into a Unix text file.
XThis only works if the file is really a text file.
X.TP
X.B \-q
XQuery user before extracting files and folders.  If a "n" answer is given for
Xa folder, none of the files or folders in that folder will be extracted.
X.TP
X.B \-v
XVerbose option.  Causes 
X.I unsit
Xto list name, size, type, and creator of each file extracted.
X.SH BUGS
XFiles that were compressed by StuffIt with the Lempel-Ziv method and are
Xextracted with the 
X.B \-u
Xswitch (text files) are not checked for a correct CRC value when 
X.I unsit
Xuncompresses them.  This is because 
X.I unsit
Xpipes the data through
X.I compress
Xand
X.I tr
Xto extract the file and never has a chance to do the CRC check.
X.PP
XThe
X.I compress
Xprogram has been observed to go into strange states when uncompressing a 
Xdamaged file.  Often it will get stuck writing out bogus data until the
Xdisk fills up.  Since 
X.I unsit
Xsends data through 
X.I compress,
Xthe same problem could occur when extracting files from a damaged Stuffit
Xarchive.
X.SH FILES
XFor archives that have been compressed with the Lempel-Ziv method, the 
X.I compress 
Xprogram must be present on the system and in the search path since 
X.I unsit 
Xuses it for the uncompressing.
X.I Compress
Xis available from the comp.sources.unix archives.
X.SH AUTHOR
XAllan G. Weber (weber@sipi.usc.edu)
END_OF_FILE
if test 4233 -ne `wc -c <'unstuffit/unsit.1'`; then
    echo shar: \"'unstuffit/unsit.1'\" unpacked with wrong size!
fi
# end of 'unstuffit/unsit.1'
fi
if test -f 'unstuffit/unstuffit.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/unstuffit.1'\"
else
echo shar: Extracting \"'unstuffit/unstuffit.1'\" \(2941 characters\)
sed "s/^X//" >'unstuffit/unstuffit.1' <<'END_OF_FILE'
X.TH UNSTUFFIT L "December 1990"
X.UC
X.SH NAME
Xunstuffit \- unpack a Stuffit archive file to CAP aufs files
X.SH SYNOPSIS
X.B unstuffit
X[
X.B \-rdulM
X] [
X-vqfm
X] file(s)
X.br
X.SH DESCRIPTION
XFor the Stuffit archive(s) file listed, 
X.I unstuffit
Xextracts the files in the archive into separate files.
XThis makes it possible, for example, to separate a large StuffIt file
Xinto component files for selective downloading, rather than
Xdownloading the larger archive file just to extract a single, small
Xfile.  It also allows the use of StuffIt to compress a group of files
Xinto a single, smaller archive that can be uploaded to a Unix system
Xfor storage, printing, etc.
X.PP
X.I Unstuffit
Xstores extracted files in CAP aufs format in the current directory, which
Xmust be a CAP aufs folder.
XCharacters in the Mac file name that are
Xillegal (or unwieldy, like spaces) are changed to underscores in the Unix file
Xname.
X.PP
XStuffIt version 1.5 has the ability to archive a group of files and folders
Xin such a way that the hierarchical relationship of the files and folders
Xis maintained.
X.I Unstuffit
Xversion 1.5 can unpack files archived in this manner and place them in
Xcorresponding subdirectories, which it will create in CAP aufs folder format,  so as to maintain the hierarchy.  As an option,
Xthe hierarcy can be flattened out and all the files stored in the current
Xdirectory.
X.PP
X.TP
X.B \-f
XFor StuffIt files containing a "Hierarchy Maintained Folder" entry, extract the
Xfiles into a "flat" organization (all in the current directory) rather than
Xmaintaining the hierarchy by creating new directories, etc.
XDefault is to maintain the hierarchical folder organization.
X.TP
X.B \-l
XList the files in the archive but do not extract them.  The name, size,
Xtype, and creator of each file is listed.
X.TP
X.B \-m
XAssumes the input file in MacBinary format rather than aufs
Xformat and skips over the MacBinary header.
X.TP
X.B \-r
XExtract resources forks only.
X.TP
X.B \-d
XExtract data forks only.
X.TP
X.B \-q
XQuery user before extracting files and folders.  If a "n" answer is given for
Xa folder, none of the files or folders in that folder will be extracted.
X.TP
X.B \-v
XVerbose option.  Causes 
X.I unstuffit
Xto list name, size, type, and creator of each file extracted.
X.SH BUGS
XThe
X.I compress
Xprogram has been observed to go into strange states when uncompressing a 
Xdamaged file.  Often it will get stuck writing out bogus data until the
Xdisk fills up.  Since 
X.I unstuffit
Xsends data through 
X.I compress,
Xthe same problem could occur when extracting files from a damaged Stuffit
Xarchive.
X.SH FILES
XFor archives that have been compressed with the Lempel-Ziv method, the 
X.I compress 
Xprogram must be present on the system and in the search path since 
X.I unstuffit 
Xuses it for the uncompressing.
X.I Compress
Xis available from the comp.sources.unix archives.
X.SH AUTHOR
XNigel Perry (np@doc.ic.ac.uk) based upon unsit by
XAllan G. Weber (weber@sipi.usc.edu).
END_OF_FILE
if test 2941 -ne `wc -c <'unstuffit/unstuffit.1'`; then
    echo shar: \"'unstuffit/unstuffit.1'\" unpacked with wrong size!
fi
# end of 'unstuffit/unstuffit.1'
fi
echo shar: End of archive 1 \(of 4\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--- end of part 1 ---

np@doc.imperial.ac.uk (Nigel Perry) (02/21/91)

[AufsTools - part 2 of 4]

---
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 4)."
# Contents:  capit/capit.c mcvert/mactypes.h mcvert/mcvert.1
#   mcvert/unpack.c stuffit/updcrc.c unstuffit/updcrc.c
# Wrapped by np@asun5 on Mon Dec  3 13:15:56 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'capit/capit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'capit/capit.c'\"
else
echo shar: Extracting \"'capit/capit.c'\" \(8984 characters\)
sed "s/^X//" >'capit/capit.c' <<'END_OF_FILE'
X/* unmacbin - reverse of macbin - change a MacBinary file back in to
X   the .info .data .rsrc style that xbin, macput and macget understand.
X   Stole some from macbin. */
X
X/* Written by John M. Sellens, jmsellens@watdragon.uwaterloo.ca,
X   Math Faculty Computing Facility,
X   University of Waterloo
X   Waterloo, Ontario, Canada
X   N2L 3G1	*/
X
X/* capit - convert a macbin file into a CAP file on a CAP Unix Mac disc.
X   Basically:
X      file.data => file
X      file.rsrc => .resource/file
X      file.info => mangle it then .finderinfo/file
X 
X   Nigel Perry, Dept of Computing, Imperial College, London SW7 2BZ, England. July 90.
X   np@doc.ic.ac.uk
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <strings.h>
X
X#define BSIZE	(128)	/* size of blocks in MacBinary file */
Xtypedef long	int4;
X
X
X/* following from mcvert program */
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte;     /* one byte, obviously */
Xtypedef unsigned short word;    /* must be 2 bytes */
Xtypedef unsigned long ulong;    /* 4 bytes */
X
X#define NAMELEN 63              /* maximum legal Mac file name length */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks.  The first block is the
Xinfo_header (see below).  Then comes the data fork, null padded to fill the
Xlast block.  Then comes the resource fork, padded to fill the last block.  A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/ 
Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
X                        longs don't align to word boundaries */
X            byte version;           /* there is only a version 0 at this time */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;             /* Locked, Invisible,Bundle, System */
X                                    /* Bozo, Busy, Changed, Init */
X            byte icon_vert[2];      /* Vertical icon position within window */
X            byte icon_horiz[2];     /* Horizontal icon postion in window */
X            byte window_id[2];      /* Window or folder ID. */
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
X            byte rflen[4];          /* Resource Fork length         byte first */
X            byte cdate[4];          /* File's creation date. */
X            byte mdate[4];          /* File's "last modified" date. */
X            byte ilen[2];           /* GetInfo message length */
X	    byte flags2;            /* Finder flags, bits 0-7 */
X	    byte unused[14];       
X	    byte packlen[4];        /* length of total files when unpacked */
X	    byte headlen[2];        /* length of secondary header */
X	    byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
X	    byte readvers;          /* Minimum MacBinary II version needed to read this file */
X            byte crc[2];            /* CRC of the previous 124 bytes */
X	    byte padding[2];        /* two trailing unused bytes */
X            } info_header;
X
X/* end of mcvert stuff */
X/* from CAP aufs documentation */
X
X#define FINFOLEN 32
X#define MAXCLEN 199
Xtypedef struct
X{  /* byte fi_fndr[FINFOLEN]; */	/* finder info */
X   /* what I think the above is... */
X   ulong fndr_type, fndr_creator;
X   word fndr_flags;
X   ulong fndr_loc;
X   word fndr_fldr;
X   word fndr_icon;
X   byte fndr_unused[8];
X   word fndr_comment;
X   ulong fndr_putaway;
X   /* end of fi_fndr */
X
X   word fi_attr;			/* attributes */
X#define FI_MAGIC1 255
X   byte fi_magic1;		/* was: length of comment */
X#define FI_VERSION 0x10		/* version major 1, minor 0 */
X				/* if more than 8 versions then */
X				/* something wrong anyway */
X   byte fi_version;		/* version number */
X#define FI_MAGIC 0xda
X   byte fi_magic;		/* magic word check */
X   byte fi_bitmap;		/* bitmap of included info */
X#define FI_BM_SHORTFILENAME 0x1	/* is this included? */
X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
X   byte fi_shortfilename[12+1];	/* possible short file name */
X   byte fi_macfilename[32+1];	/* possible macintosh file name */
X   byte fi_comln;		/* comment length */
X   byte fi_comnt[MAXCLEN+1];	/* comment string */
X} FileInfo;
X
X/* end aufs */
X
Xstatic info_header info;
Xstatic FileInfo fndr_info;
X
Xstatic union trans {
X    int4	num;
X    char	ch[4];
X} trans;
X
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    FILE *fp, *ofp;
X    char bname[MAXNAMLEN];
X    char iname[MAXNAMLEN];
X    char dname[MAXNAMLEN];
X    char rname[MAXNAMLEN];
X    char buf[BSIZE];
X    char * charp;
X    int verbose = 0;
X    int len;
X    int arg;
X    int err = 0;
X    long dflen, rflen;
X    char *ext, *disc;
X    extern char *getenv();
X
X    if((ext = getenv("MAC_EXT")) == NULL) ext = ".bin";
X    if((disc = getenv("MAC_DISC")) == NULL) disc = ".";
X
X    arg = 1;
X    if (argc > 1 && strcmp(argv[1], "-v") == 0 ) {
X	verbose = 1;
X	++arg;
X    }
X    if ( arg >= argc ) {
X	fprintf(stderr,"%s: Usage: %s [-v] filename(s)\n",argv[0],argv[0]);
X	exit(1);
X    }
X    for ( ; arg < argc; arg++ ) {
X	if ( (charp = rindex (argv[arg], '.')) != NULL
X	    && strcmp(charp, ext) == 0 ) {
X	    *charp = '\0';
X	    strcpy(bname, argv[arg]);
X	    *charp = '.';
X	} else
X	    strcpy(bname, argv[arg]);
X
X	sprintf(iname, "%s/.finderinfo/%s", disc, bname);
X	sprintf(dname, "%s/%s", disc, bname);
X	sprintf(rname, "%s/.resource/%s", disc, bname);
X
X	if (verbose)
X	    printf( "Converting '%s'\n", argv[arg] );
X	if ( (fp = fopen( argv[arg], "r" )) == NULL ) {
X	    fprintf( stderr, "%s: couldn't open '%s' for reading",
X		argv[0], argv[arg] );
X	    perror( "" );
X	    exit(++err);
X	}
X	if ( fread(&info, sizeof(info), 1, fp) <= 0 ) {
X	    fprintf( stderr, "%s: couldn't read .info header from '%s'",
X		argv[0], argv[arg] );
X	    perror( "" );
X	    exit(++err);
X	}
X	if ( info.zero1 || info.zero2 || info.version ) {
X	    fprintf( stderr, "%s: '%s' is not in MacBinary format - skipped\n",
X		argv[0], argv[arg] );
X	    ++err;
X	    continue;
X	}
X
X	/* make the .finderinfo file */
X	bzero(&fndr_info, sizeof(FileInfo));
X	bcopy(info.type, &fndr_info.fndr_type, 4);
X	bcopy(info.auth, &fndr_info.fndr_creator, 4);
X        if(info.protect == '\1' ) fndr_info.fndr_flags = 0x40; /* maybe? */
X	fndr_info.fi_magic1 = FI_MAGIC1;
X	fndr_info.fi_version = FI_VERSION;
X	fndr_info.fi_magic = FI_MAGIC;
X	fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
X	bcopy(info.name, fndr_info.fi_macfilename, info.nlen);
X
X	/* write the .finderinfo file */
X	if ( (ofp = fopen( iname, "w" )) == NULL ) {
X	    fprintf( stderr, "%s: couldn't open '%s' for writing",
X		argv[0], iname );
X	    perror( "" );
X	    exit(++err);
X	}
X	fwrite( &fndr_info, sizeof(FileInfo), 1, ofp );
X	fclose( ofp );
X
X	/* It appears that the .data and .rsrc parts of the MacBinary file
X	   are padded to the nearest 128 (BSIZE) byte boundary, but they
X	   should be trimmed to their proper size when we split them. */
X
X	trans.ch[0] = info.dflen[0]; trans.ch[1] = info.dflen[1];
X	trans.ch[2] = info.dflen[2]; trans.ch[3] = info.dflen[3];
X	dflen = ntohl( trans.num );
X	trans.ch[0] = info.rflen[0]; trans.ch[1] = info.rflen[1];
X	trans.ch[2] = info.rflen[2]; trans.ch[3] = info.rflen[3];
X	rflen = ntohl( trans.num );
X
X	/* write the data fork */
X	if ( (ofp = fopen( dname, "w" )) == NULL ) {
X	    fprintf( stderr, "%s: couldn't open '%s' for writing",
X		argv[0], dname );
X	    perror( "" );
X	    exit(++err);
X	}
X	for ( len=0; len<dflen;  ) {
X	    if ( fread( buf, sizeof(char), BSIZE, fp ) != BSIZE ) {
X		fprintf( stderr, "%s: couldn't read %d bytes from '%s'",
X		    argv[0], BSIZE, argv[arg] );
X		fprintf(stderr,"got %d of %d'n",len,dflen);
X		perror( "" );
X		exit(++err);
X	    }
X	    len += BSIZE;
X	    if ( len > dflen )
X		fwrite( buf, sizeof(char), BSIZE-len+dflen, ofp );
X	    else
X		fwrite( buf, sizeof(char), BSIZE, ofp );
X	}
X	fclose( ofp );
X	    
X	/* write the .resource file */
X	if ( (ofp = fopen( rname, "w" )) == NULL ) {
X	    fprintf( stderr, "%s: couldn't open '%s' for writing",
X		argv[0], rname );
X	    perror( "" );
X	    exit(++err);
X	}
X	for ( len=0; len<rflen;  ) {
X	    if ( fread( buf, sizeof(char), BSIZE, fp ) != BSIZE ) {
X		fprintf( stderr, "%s: couldn't read %d bytes from '%s'",
X		    argv[0], BSIZE, argv[arg] );
X		fprintf(stderr,"got %d of %d'n",len,rflen);
X		perror( "" );
X		exit(++err);
X	    }
X	    len += BSIZE;
X	    if ( len > rflen )
X		fwrite( buf, sizeof(char), BSIZE-len+rflen, ofp );
X	    else
X		fwrite( buf, sizeof(char), BSIZE, ofp );
X	}
X	fclose( ofp );
X	fclose( fp );
X    }
X    exit( err );
X}
END_OF_FILE
if test 8984 -ne `wc -c <'capit/capit.c'`; then
    echo shar: \"'capit/capit.c'\" unpacked with wrong size!
fi
# end of 'capit/capit.c'
fi
if test -f 'mcvert/mactypes.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/mactypes.h'\"
else
echo shar: Extracting \"'mcvert/mactypes.h'\" \(7478 characters\)
sed "s/^X//" >'mcvert/mactypes.h' <<'END_OF_FILE'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <sys/stat.h>
X#include <sys/timeb.h>
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte;     /* one byte, obviously */
Xtypedef unsigned short word;    /* must be 2 bytes */
Xtypedef unsigned long ulong;    /* 4 bytes */
X#define TRUE  1
X#define FALSE 0
X#define CR 0x0d
X#define LF 0x0a
X
X/* Compatibility issues */
X#ifdef BSD
X#define mac2word (word) ntohs
X#define mac2long (ulong) ntohl
X#define word2mac (word) htons
X#define long2mac (ulong) htonl
X#else
X#define mac2word
X#define mac2long
X#define word2mac
X#define long2mac
X#endif
X
X#ifdef MAXNAMLEN/* 4.2 BSD, stdio.h */
X#define SYSNAMELEN MAXNAMLEN
X#else
X#define SYSNAMELEN DIRSIZ
X#endif
X
X#define NAMELEN 63              /* maximum legal Mac file name length */
X#define BINNAMELEN 68           /* NAMELEN + len(".bin\0") */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks.  The first block is the
Xinfo_header (see below).  Then comes the data fork, null padded to fill the
Xlast block.  Then comes the resource fork, padded to fill the last block.  A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/ 
Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
X                        longs don't align to word boundaries */
X            byte version;           /* there is only a version 0 at this time */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;             /* Locked, Invisible,Bundle, System */
X                                    /* Bozo, Busy, Changed, Init */
X            byte icon_vert[2];      /* Vertical icon position within window */
X            byte icon_horiz[2];     /* Horizontal icon postion in window */
X            byte window_id[2];      /* Window or folder ID. */
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
X            byte rlen[4];           /* Resource Fork length         byte first */
X            byte ctim[4];           /* File's creation date. */
X            byte mtim[4];           /* File's "last modified" date. */
X            byte ilen[2];           /* GetInfo message length */
X	    byte flags2;            /* Finder flags, bits 0-7 */
X	    byte unused[14];       
X	    byte packlen[4];        /* length of total files when unpacked */
X	    byte headlen[2];        /* length of secondary header */
X	    byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
X	    byte readvers;          /* Minimum MacBinary II version needed to read this file */
X            byte crc[2];            /* CRC of the previous 124 bytes */
X	    byte padding[2];        /* two trailing unused bytes */
X            } info_header;
X
X/* The *.info file of a MacTerminal file transfer either has exactly this
Xstructure or has the protect bit in bit 6 (near the sign bit) of byte zero1.
XThe code I have for macbin suggests the difference, but I'm not so sure */
X
X/* Format of a hqx file:
XIt begins with a line that begins "(This file
Xand the rest is 64 character lines (except possibly the last, and not
Xincluding newlines) where the first begins and the last ends with a colon.
XThe characters between colons should be only from the set in tr86, below,
Xeach of which corresponds to 6 bits of data.  Once that is translated to
X8 bit bytes, you have the real data, except that the byte 0x90 may 
Xindicate, if the following character is nonzero, that the previous
Xbyte is to be repeated 1 to 255 times.  The byte 0x90 is represented by
X0x9000.  The information in the file is the hqx_buf (see below),
Xa CRC word, the data fork, a CRC word, the resource fork, and a CRC word.
XThere is considerable confusion about the flags.  An official looking document
Xunclearly states that the init bit is always clear, as is the following byte.
XThe experience of others suggests, however, that this is not the case.
X*/
X
X#define HQXLINELEN 64
Xtypedef struct {
X            byte version;           /* there is only a version 0 at this time */
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte protect;           /* ?Pr??????, don't know what ? bits mean */
X            byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
X            byte rlen[4];           /* Resource Fork length         byte first */
X            byte bugblank;             /* to fix obscure sun 3/60 problem
X                                          that always makes sizeof(hqx_header
X                                          even */
X            } hqx_header;
Xtypedef struct {     /* hqx file header buffer (includes file name) */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename: only nlen actually appear */
X            hqx_header all_the_rest;/* and all the rest follows immediately */
X            } hqx_buf;
X
X/* Format of a Packit file:
XRepeat the following sequence for each file in the Packit file:
X    4 byte identifier ("PMag" = not compressed, "Pma4" = compressed)
X    320 byte compression data (if compressed file)
X        = preorder transversal of Huffman tree
X        255 0 bits corresponding to nonleaf nodes
X        256 1 bits corresponding to leaf nodes
X        256 bytes associating leaf nodes with bytes
X        1   completely wasted bit
X    92 byte header (see pit_header below) *
X    2 bytes CRC word for header *
X    data fork (length from header) *
X    resource fork (length from header) *
X    2 bytes CRC word for forks *
X
XLast file is followed by the 4 byte Ascii string, "Pend", and then the EOF.
XThe CRC calculations differ from those in the binhex format.
X
X* these are in compressed form if compression is on for the file
X
X*/
X
Xtypedef struct {     /* Packit file header (92 bytes) */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
X            byte rlen[4];           /* Resource Fork length         byte first */
X            byte ctim[4];           /* File's creation date. */
X            byte mtim[4];           /* File's "last modified" date. */
X            } pit_header;
X
X/* types for constructing the Huffman tree */
Xtypedef struct branch_st {
X            byte flag;
X            struct branch_st *one, *zero;
X            } branch;
X
Xtypedef struct leaf_st {
X            byte flag;
X            byte data;
X            } leaf;
END_OF_FILE
if test 7478 -ne `wc -c <'mcvert/mactypes.h'`; then
    echo shar: \"'mcvert/mactypes.h'\" unpacked with wrong size!
fi
# end of 'mcvert/mactypes.h'
fi
if test -f 'mcvert/mcvert.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/mcvert.1'\"
else
echo shar: Extracting \"'mcvert/mcvert.1'\" \(5991 characters\)
sed "s/^X//" >'mcvert/mcvert.1' <<'END_OF_FILE'
X.TH MCVERT LOCAL "May 5, 1987"
X.UC 4.2
X.SH NAME
Xmcvert \- BinHex 4.0 to MacBinary file conversion utility
X.SH SYNOPSIS
X.B mcvert
X[-options] name... [[-options] name...]...
X.br
X.SH DESCRIPTION
XThe
X.I mcvert
Xprogram translates MacIntosh files from one format to another.
XThe primary formats in which MacIntosh files are represented on non-Macs are:
X.TP
X.B MacBinary:
XAn eight bit wide representation of the data and resource forks of a Mac
Xfile and of relevant Finder information, MacBinary files are recognized
Xas "special" by several MacIntosh terminal emulators.  These emulators,
Xusing Kermit or Xmodem or any other file transfer protocol, can separate
Xthe incoming file into forks and appropriately modify the Desktop to display
Xicons, types, creation dates, and the like.
X.TP
X.B BinHex 4.0:
XA seven bit wide representation of a Mac file with CRC error checking,
XBinHex 4.0 files are designed for communication of Mac files over long
Xdistance, possibly noisy, seven bit wide paths.
X.TP
X.B PackIt:
XPackIt files are actually representations of collections of Mac files, possibly
XHuffman compressed.  Packing many small related files together before
Xa MacBinary transfer or a translation to BinHex 4.0 is common practice.
X.TP
X.B Text:
XA MacIntosh ends each line of a plain text file with a carriage return
Xcharacter (^M), rather than the newline character (^J) that some systems
Xseem to prefer.  Moreover, a MacBinary file has prepended Finder information
Xthat non-MacIntoshes don't need.
X.TP
X.B Data, Rsrc:
XA Data or Rsrc file is the exact copy of the data or resource fork of a
XMacIntosh file.
X.PP
XIt is the purpose of this program to convert to the MacBinary format
Xfiles in other of the above formats, and vice versa.
X.PP
X.SH PARAMETERS
XExactly one of the following operations may be specified for an input name:
X.TP
X.B x
XBinHex 4.0 - files in the MacBinary format are translated to BinHex
Xfiles, or vice versa.  The name argument may be the name of a file to be
Xconverted or a basename to which an appropriate suffix must be appended
Xto get a filename.  If the conversion is from Binhex 4.0 to MacBinary,
Xseveral files may comprise the BinHex representation of the Mac file.
XRather than manually concatenate the files and manually delete mail
Xheaders and other extraneous garbage, one may specify the names of the
Xfiles in order and
X.I mcvert
Xwill do the concatenating and deleting.  Conversely, in converting
Xa MacBinary file to BinHex 4.0 format for mailing over long distances,
Xone may be restricted to mail messages of no greater that some fixed
Xlength.  In this case,
X.I mcvert
Xcan automatically divide the BinHex file into pieces and label each
Xpiece appropriately.
XOption 'x' is selected by default.
X.TP
X.B r
XResource - files in the MacBinary format with empty data forks
Xand nonempty resource forks are made from ordinary data files, or vice versa.
X.TP
X.B d
XData - files in the MacBinary format with nonempty data forks
Xand empty resource forks are made from ordinary data files, or vice versa.
X.TP
X.B u
XText - files in the MacBinary format with nonempty data forks
Xand empty resource forks are made from ordinary data files, or vice versa.
XUnix newline
Xcharacters are interchanged with MacIntosh carriage return
Xcharacters, and a newly created MacBinary file has creator field given by
Xthe MAC_EDITOR environment variable.
X.PP
X.SH OPTIONS
X.TP
X.B p | q
XIf a BinHex to MacBinary conversion is taking place and option 'p' is selected,
Xany file of type "PIT "
Xwill be unpacked into its constituent parts.  This option does not recursively
Xunpack "PIT " files packed in "PIT " files.
XIf a MacBinary to BinHex conversion is taking place, this option is currently
Xignored.  By default, option 'q' is selected.
X.TP
X.B U | D
XWhen option 'U' is selected, the conversion that takes place is the one suitable
Xfor Uploading files.  That is, the conversion is from MacBinary to something
Xelse when 'U' is selected.  Conversely, option 'D', as in Download,
Xconverts from something to MacBinary.  Option 'D' is the default.
X.TP
X.B s | v
XNormally,
X.I mcvert
Xprints to stderr information about the files it is creating.  Selecting
Xoption 's', as in silent, disables this reporting.  Option 'v', for verbose,
Xis the default.
X.SH "ENVIRONMENT VARIABLES"
XThere are four environment variables one may use to customize 
Xthe behavior of
X.I mcvert
Xslightly.
X.TP
X.B MAC_EDITOR
XThe creator of MacBinary text files produced with options -uD.  
XThe default is MACA, the creator type of MacWrite.
X.TP
X.B MAC_DLOAD_DIR
XThe MacBinary files created when option -D is selected are placed in this
Xdirectory.  The default is ".", the current working directory.
X.TP
X.B MAC_EXT
XThe MacBinary files created when option -D is selected are named according
Xto the filename field stored in the file header, with the name extended by
Xthis suffix.  The default is ".bin".
X.TP
X.B MAC_LINE_LIMIT
XThe BinHex files created when option -U is selected may be no longer than
Xthis many lines long.  Files that would otherwise exceed this line limit
Xare broken up into several files with numbers embedded into their file 
Xnames to show their order.  Each such file has "Start of part x" and "End
Xof part x" messages included where appropriate.
X.SH BUGS
XIt should be possible to discard bad input now and successfully translate
Xgood input later, but bad input mostly just causes immediate termination.
X.PP
XA more diligent person would support BinHex 3.0 and BinHex 2.0 and BinHex
X5000.0 B. C., but I've never seen anyone use them in three years.  A
Xmore diligent person would also do something for users of macget and
Xmacput, but hopefully someone will make those programs support the
XMacBinary file protocol.
X.SH SEE ALSO
Xxbin(1), macget(1), macput(1), xmodem(1), kermit(1)
X.SH AUTHOR
XDoug Moore, Cornell University Computer Science.  Based upon
X.I xbin
Xby Dave Johnson, Brown University, as modified by Guido van Rossum, and upon
X.I unpit
Xby Allan G. Weber, as well as upon correspondence with several helpful
Xreaders of USENET.
X
END_OF_FILE
if test 5991 -ne `wc -c <'mcvert/mcvert.1'`; then
    echo shar: \"'mcvert/mcvert.1'\" unpacked with wrong size!
fi
# end of 'mcvert/mcvert.1'
fi
if test -f 'mcvert/unpack.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/unpack.c'\"
else
echo shar: Extracting \"'mcvert/unpack.c'\" \(6606 characters\)
sed "s/^X//" >'mcvert/unpack.c' <<'END_OF_FILE'
X#include "mactypes.h"
X
Xextern word magic[];
Xextern FILE *verbose;
Xextern char *dir, *ext;
X
Xulong pit_datalen, pit_rsrclen;
Xword hqx_crc, write_pit_fork(); 
Xchar pitfname[BINNAMELEN];              /* name of file being unpacked */
XFILE *pitfile;                          /* output file */
X
Xbranch branchlist[255], *branchptr, *read_tree();
Xleaf leaflist[256], *leafptr;
Xword Huff_nibble, Huff_bit_count;
Xbyte (*read_char)(), get_crc_byte(), getHuffbyte();
X
Xword un_pit()
X{   char PitId[4];
X    int i;
X    word pit_crc;
X
X    hqx_crc = 0;
X    /* Read and unpack until the PackIt End message is read */
X    for (;;) {
X        read_char = get_crc_byte;
X        for (i = 0; i < 4; i++) PitId[i] = (char) get_crc_byte();
X        if (!strncmp(PitId, "PEnd", 4)) break;
X
X        if (strncmp(PitId, "PMag", 4) && strncmp(PitId, "PMa4", 4))
X            error("Unrecognized Packit format message %s", PitId);
X
X        if (PitId[3] == '4') {          /* if this file is compressed */
X            branchptr = branchlist;     /* read the Huffman decoding  */
X            leafptr = leaflist;         /* tree that is on the input  */
X            Huff_bit_count = 0;         /* and use Huffman decoding   */
X            read_tree();                /* subsequently               */
X            read_char = getHuffbyte;
X            }
X
X        read_pit_hdr();     /* also calculates datalen, rsrclen,
X                               pitfile, pitfname */
X        pit_crc = write_pit_fork(pit_datalen, 0);
X        pit_crc = write_pit_fork(pit_rsrclen, pit_crc);
X        check_pit_crc(pit_crc, "  File data/rsrc CRC mismatch in %s", pitfname);
X        fclose(pitfile);
X        }
X    hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
X    hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
X    return hqx_crc;
X    }
X
Xcheck_pit_crc(calc_crc, msg, name)
Xword calc_crc;
Xchar msg[], name[];
X{   word read_crc;
X    read_crc = (*read_char)() << 8;
X    read_crc |= (*read_char)();
X    if (read_crc != calc_crc) error(msg, name);
X    }
X
X/* This routine reads the header of a packed file and appropriately twiddles it,
X    determines if it has CRC problems, creates the .bin file, and puts the info
X    into the .bin file.
X    Output is pit_datalen, pit_rsrclen, pitfname, pitfile */
Xread_pit_hdr()
X{   register int n;
X    register byte *pit_byte;
X    register ulong pit_crc;
X    pit_header pit;
X    info_header info;
X    short crc;
X
X    extern short calc_mb_crc();
X    /* read the pit header and compute the CRC */
X    pit_crc = 0;
X    pit_byte = (byte *) &pit;
X    for (n = 0; n < sizeof(pit_header); n++) {
X        *pit_byte = (*read_char)();
X        pit_crc = ((pit_crc & 0xff) << 8)
X                    ^ magic[*pit_byte++ ^ (pit_crc >> 8)];
X        }
X
X    /* stuff the pit header data into the info header */
X    bzero(&info, sizeof(info_header));
X    info.nlen = pit.nlen;
X    strncpy(info.name, pit.name, pit.nlen);     /* name */
X    bcopy(pit.type, info.type, 9);              /* type, author, flag */
X    bcopy(pit.dlen, info.dlen, 16);             /* (d,r)len, (c,m)tim */
X    info.flags  &= 0x7e;                        /* reset lock bit, init bit */
X    if (pit.protect & 0x40) info.protect = 1;   /* copy protect bit */
X    info.uploadvers = '\201';
X    info.readvers = '\201';
X
X    /* calculate MacBinary CRC */
X    crc = calc_mb_crc(&info, 124, 0);
X    info.crc[0] = (char) (crc >> 8);
X    info.crc[1] = (char) crc;
X
X    /* Create the .bin file and write the info to it */
X    pit.name[pit.nlen] = '\0';
X    unixify(pit.name);
X    sprintf(pitfname, "%s/%s%s", dir, pit.name, ext);
X    fprintf(verbose,
X        " %-14s%-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X        (read_char == get_crc_byte) ? "Unpacking" : "Decompressing",
X        pit.name, pit.type, pit.auth);
X    if ((pitfile = fopen(pitfname, "w")) == NULL)
X        error("  Cannot open %s", pitfname);
X    check_pit_crc(pit_crc, "  File header CRC mismatch in %s", pitfname);
X    fwrite(&info, sizeof(info_header), 1, pitfile);
X
X    /* Get a couple of items we'll need later */
X    bcopy(pit.dlen, &pit_datalen, 4);
X    pit_datalen = mac2long(pit_datalen);
X    bcopy(pit.rlen, &pit_rsrclen, 4);
X    pit_rsrclen = mac2long(pit_rsrclen);
X    }
X
X/* This routine copies bytes from the decoded input stream to the output
X    and calculates the CRC.  It also pads to a multiple of 128 bytes on the
X    output, which is part of the .bin format */
Xword write_pit_fork(nbytes, calc_crc)
Xregister ulong nbytes;
Xregister ulong calc_crc;
X{   register ulong b;
X    int extra_bytes;
X
X    extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
X    while (nbytes--) {
X        b = (*read_char)();
X        calc_crc = ((calc_crc & 0xff) << 8) ^ magic[b ^ (calc_crc >> 8)];
X        putc(b, pitfile);
X        }
X    while (extra_bytes--) putc(0, pitfile);
X    return (word) calc_crc;
X    }
X
X/* This routine recursively reads the compression decoding data.
X   It appears to be Huffman compression.  Every leaf is represented
X   by a 1 bit, then the byte it represents.  A branch is represented
X   by a 0 bit, then its zero and one sons */
Xbranch *read_tree()
X{   register branch *branchp;
X    register leaf *leafp;
X    register ulong b;
X    if (!Huff_bit_count--) {
X        Huff_nibble = get_crc_byte();
X        Huff_bit_count = 7;
X        }
X    if ((Huff_nibble<<=1) & 0x0100) {
X        leafp = leafptr++;
X        leafp->flag = 1;
X        b = get_crc_byte();
X        leafp->data = Huff_nibble | (b >> Huff_bit_count);
X        Huff_nibble = b << (8 - Huff_bit_count);
X        return (branch *) leafp;
X        }
X    else {
X        branchp = branchptr++;
X        branchp->flag = 0;
X        branchp->zero = read_tree();
X        branchp->one  = read_tree();
X        return branchp;
X        }
X    }
X
X/* This routine returns the next 8 bits.  It finds the byte in the
X   Huffman decoding tree based on the bits from the input stream. */
Xbyte getHuffbyte()
X{   register branch *branchp;
X    branchp = branchlist;
X    while (!branchp->flag) {
X        if (!Huff_bit_count--) {
X            Huff_nibble = get_crc_byte();
X            Huff_bit_count = 7;
X            }
X        branchp = ((Huff_nibble<<=1) & 0x0100) ? branchp->one : branchp->zero;
X        }
X    return ((leaf *) branchp)->data;
X    }
X
X/* This routine returns the next byte on the .hqx input stream, hiding
X    most file system details at a lower level.  .hqx CRC is maintained
X    here */
Xbyte get_crc_byte()
X{   register ulong c;
X    extern byte *buf_ptr, *buf_end;
X    if (buf_ptr == buf_end) fill_hqxbuf();
X    c = *buf_ptr++;
X    hqx_crc = ((hqx_crc << 8) | c) ^ magic[hqx_crc >> 8];
X    return (byte) c;
X    }
END_OF_FILE
if test 6606 -ne `wc -c <'mcvert/unpack.c'`; then
    echo shar: \"'mcvert/unpack.c'\" unpacked with wrong size!
fi
# end of 'mcvert/unpack.c'
fi
if test -f 'stuffit/updcrc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuffit/updcrc.c'\"
else
echo shar: Extracting \"'stuffit/updcrc.c'\" \(5848 characters\)
sed "s/^X//" >'stuffit/updcrc.c' <<'END_OF_FILE'
X/* updcrc(3), crc(1) - calculate crc polynomials
X *
X * Calculate, intelligently, the CRC of a dataset incrementally given a 
X * buffer full at a time.
X * 
X * Usage:
X * 	newcrc = updcrc( oldcrc, bufadr, buflen )
X * 		unsigned int oldcrc, buflen;
X * 		char *bufadr;
X *
X * Compiling with -DTEST creates a program to print the CRC of stdin to stdout.
X * Compile with -DMAKETAB to print values for crctab to stdout.  If you change
X *	the CRC polynomial parameters, be sure to do this and change
X *	crctab's initial value.
X *
X * Notes:
X *  Regards the data stream as an integer whose MSB is the MSB of the first
X *  byte recieved.  This number is 'divided' (using xor instead of subtraction)
X *  by the crc-polynomial P.
X *  XMODEM does things a little differently, essentially treating the LSB of
X * the first data byte as the MSB of the integer. Define SWAPPED to make
X * things behave in this manner.
X *
X * Author:	Mark G. Mendel, 7/86
X *		UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm
X */
X
X/* The CRC polynomial.
X * These 4 values define the crc-polynomial.
X * If you change them, you must change crctab[]'s initial value to what is
X * printed by initcrctab() [see 'compile with -DMAKETAB' above].
X */
X    /* Value used by:	    		CITT	XMODEM	ARC  	*/
X#define	P	 0xA001	 /* the poly:	0x1021	0x1021	A001	*/
X#define INIT_CRC 0L	 /* init value:	-1	0	0	*/
X#define SWAPPED		 /* bit order:	undef	defined	defined */
X#define W	16	 /* bits in CRC:16	16	16	*/
X
X    /* data type that holds a W-bit unsigned integer */
X#if W <= 16
X#  define WTYPE	unsigned short
X#else
X#  define WTYPE   unsigned long
X#endif
X
X    /* the number of bits per char: don't change it. */
X#define B	8
X
Xstatic WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ {
X0x0,  0xc0c1,  0xc181,  0x140,  0xc301,  0x3c0,  0x280,  0xc241,
X0xc601,  0x6c0,  0x780,  0xc741,  0x500,  0xc5c1,  0xc481,  0x440,
X0xcc01,  0xcc0,  0xd80,  0xcd41,  0xf00,  0xcfc1,  0xce81,  0xe40,
X0xa00,  0xcac1,  0xcb81,  0xb40,  0xc901,  0x9c0,  0x880,  0xc841,
X0xd801,  0x18c0,  0x1980,  0xd941,  0x1b00,  0xdbc1,  0xda81,  0x1a40,
X0x1e00,  0xdec1,  0xdf81,  0x1f40,  0xdd01,  0x1dc0,  0x1c80,  0xdc41,
X0x1400,  0xd4c1,  0xd581,  0x1540,  0xd701,  0x17c0,  0x1680,  0xd641,
X0xd201,  0x12c0,  0x1380,  0xd341,  0x1100,  0xd1c1,  0xd081,  0x1040,
X0xf001,  0x30c0,  0x3180,  0xf141,  0x3300,  0xf3c1,  0xf281,  0x3240,
X0x3600,  0xf6c1,  0xf781,  0x3740,  0xf501,  0x35c0,  0x3480,  0xf441,
X0x3c00,  0xfcc1,  0xfd81,  0x3d40,  0xff01,  0x3fc0,  0x3e80,  0xfe41,
X0xfa01,  0x3ac0,  0x3b80,  0xfb41,  0x3900,  0xf9c1,  0xf881,  0x3840,
X0x2800,  0xe8c1,  0xe981,  0x2940,  0xeb01,  0x2bc0,  0x2a80,  0xea41,
X0xee01,  0x2ec0,  0x2f80,  0xef41,  0x2d00,  0xedc1,  0xec81,  0x2c40,
X0xe401,  0x24c0,  0x2580,  0xe541,  0x2700,  0xe7c1,  0xe681,  0x2640,
X0x2200,  0xe2c1,  0xe381,  0x2340,  0xe101,  0x21c0,  0x2080,  0xe041,
X0xa001,  0x60c0,  0x6180,  0xa141,  0x6300,  0xa3c1,  0xa281,  0x6240,
X0x6600,  0xa6c1,  0xa781,  0x6740,  0xa501,  0x65c0,  0x6480,  0xa441,
X0x6c00,  0xacc1,  0xad81,  0x6d40,  0xaf01,  0x6fc0,  0x6e80,  0xae41,
X0xaa01,  0x6ac0,  0x6b80,  0xab41,  0x6900,  0xa9c1,  0xa881,  0x6840,
X0x7800,  0xb8c1,  0xb981,  0x7940,  0xbb01,  0x7bc0,  0x7a80,  0xba41,
X0xbe01,  0x7ec0,  0x7f80,  0xbf41,  0x7d00,  0xbdc1,  0xbc81,  0x7c40,
X0xb401,  0x74c0,  0x7580,  0xb541,  0x7700,  0xb7c1,  0xb681,  0x7640,
X0x7200,  0xb2c1,  0xb381,  0x7340,  0xb101,  0x71c0,  0x7080,  0xb041,
X0x5000,  0x90c1,  0x9181,  0x5140,  0x9301,  0x53c0,  0x5280,  0x9241,
X0x9601,  0x56c0,  0x5780,  0x9741,  0x5500,  0x95c1,  0x9481,  0x5440,
X0x9c01,  0x5cc0,  0x5d80,  0x9d41,  0x5f00,  0x9fc1,  0x9e81,  0x5e40,
X0x5a00,  0x9ac1,  0x9b81,  0x5b40,  0x9901,  0x59c0,  0x5880,  0x9841,
X0x8801,  0x48c0,  0x4980,  0x8941,  0x4b00,  0x8bc1,  0x8a81,  0x4a40,
X0x4e00,  0x8ec1,  0x8f81,  0x4f40,  0x8d01,  0x4dc0,  0x4c80,  0x8c41,
X0x4400,  0x84c1,  0x8581,  0x4540,  0x8701,  0x47c0,  0x4680,  0x8641,
X0x8201,  0x42c0,  0x4380,  0x8341,  0x4100,  0x81c1,  0x8081,  0x4040,
X} ;
X
XWTYPE
Xupdcrc( icrc, icp, icnt )
X    WTYPE icrc;
X    unsigned char *icp;
X    int icnt;
X{
X    register WTYPE crc = icrc;
X    register unsigned char *cp = icp;
X    register int cnt = icnt;
X
X    while( cnt-- ) {
X#ifndef SWAPPED
X	crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
X#else
X	crc = (crc>>B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++]; 
X#endif SWAPPED
X    }
X
X    return( crc );
X}
X
X#ifdef MAKETAB
X
X#include <stdio.h>
Xmain()
X{
X    initcrctab();
X}
X
Xinitcrctab()
X{
X    register  int b, i;
X    WTYPE v;
X
X    
X    for( b = 0; b <= (1<<B)-1; ++b ) {
X#ifndef SWAPPED
X	for( v = b<<(W-B), i = B; --i >= 0; )
X	    v = v & ((WTYPE)1<<(W-1)) ? (v<<1)^P : v<<1;
X#else
X	for( v = b, i = B; --i >= 0; )
X	    v = v & 1 ? (v>>1)^P : v>>1;
X#endif	    
X	crctab[b] = v;
X
X	printf( "0x%lx,", v & ((1L<<W)-1L));
X	if( (b&7) == 7 )
X	    printf("\n" );
X	else
X	    printf("  ");
X    }
X}
X#endif
X
X#ifdef TEST
X
X#include <stdio.h>
X#include <fcntl.h>
X
X#define MAXBUF	4096
X
X
X
Xmain( ac, av )
X    int ac; char **av;
X{
X    int fd;
X    int nr;
X    int i;
X    char buf[MAXBUF];
X    WTYPE crc, crc2;
X
X    fd = 0;
X    if( ac > 1 )
X	if( (fd = open( av[1], O_RDONLY )) < 0 ) {
X	    perror( av[1] );
X	    exit( -1 );
X	}
X    crc = crc2 = INIT_CRC;
X
X    while( (nr = read( fd, buf, MAXBUF )) > 0 ) {
X	crc = updcrc( crc, buf, nr );
X    }
X
X    if( nr != 0 )
X	perror( "reading" );
X    else {
X	printf( "%lx\n", crc );
X    }
X
X#ifdef MAGICCHECK
X    /* tack one's complement of crc onto data stream, and
X       continue crc calculation.  Should get a constant (magic number)
X       dependent only on P, not the data.
X     */
X    crc2 = crc ^ -1L;
X    for( nr = W-B; nr >= 0; nr -= B ) {
X	buf[0] = (crc2 >> nr);
X	crc = updcrc(crc, buf, 1);
X    }
X
X    /* crc should now equal magic */
X    buf[0] = buf[1] = buf[2] = buf[3] = 0;
X    printf( "magic test: %lx =?= %lx\n", crc, updcrc(-1, buf, W/B));
X#endif MAGICCHECK
X}
X
X#endif
END_OF_FILE
if test 5848 -ne `wc -c <'stuffit/updcrc.c'`; then
    echo shar: \"'stuffit/updcrc.c'\" unpacked with wrong size!
fi
# end of 'stuffit/updcrc.c'
fi
if test -f 'unstuffit/updcrc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/updcrc.c'\"
else
echo shar: Extracting \"'unstuffit/updcrc.c'\" \(5848 characters\)
sed "s/^X//" >'unstuffit/updcrc.c' <<'END_OF_FILE'
X/* updcrc(3), crc(1) - calculate crc polynomials
X *
X * Calculate, intelligently, the CRC of a dataset incrementally given a 
X * buffer full at a time.
X * 
X * Usage:
X * 	newcrc = updcrc( oldcrc, bufadr, buflen )
X * 		unsigned int oldcrc, buflen;
X * 		char *bufadr;
X *
X * Compiling with -DTEST creates a program to print the CRC of stdin to stdout.
X * Compile with -DMAKETAB to print values for crctab to stdout.  If you change
X *	the CRC polynomial parameters, be sure to do this and change
X *	crctab's initial value.
X *
X * Notes:
X *  Regards the data stream as an integer whose MSB is the MSB of the first
X *  byte recieved.  This number is 'divided' (using xor instead of subtraction)
X *  by the crc-polynomial P.
X *  XMODEM does things a little differently, essentially treating the LSB of
X * the first data byte as the MSB of the integer. Define SWAPPED to make
X * things behave in this manner.
X *
X * Author:	Mark G. Mendel, 7/86
X *		UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm
X */
X
X/* The CRC polynomial.
X * These 4 values define the crc-polynomial.
X * If you change them, you must change crctab[]'s initial value to what is
X * printed by initcrctab() [see 'compile with -DMAKETAB' above].
X */
X    /* Value used by:	    		CITT	XMODEM	ARC  	*/
X#define	P	 0xA001	 /* the poly:	0x1021	0x1021	A001	*/
X#define INIT_CRC 0L	 /* init value:	-1	0	0	*/
X#define SWAPPED		 /* bit order:	undef	defined	defined */
X#define W	16	 /* bits in CRC:16	16	16	*/
X
X    /* data type that holds a W-bit unsigned integer */
X#if W <= 16
X#  define WTYPE	unsigned short
X#else
X#  define WTYPE   unsigned long
X#endif
X
X    /* the number of bits per char: don't change it. */
X#define B	8
X
Xstatic WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ {
X0x0,  0xc0c1,  0xc181,  0x140,  0xc301,  0x3c0,  0x280,  0xc241,
X0xc601,  0x6c0,  0x780,  0xc741,  0x500,  0xc5c1,  0xc481,  0x440,
X0xcc01,  0xcc0,  0xd80,  0xcd41,  0xf00,  0xcfc1,  0xce81,  0xe40,
X0xa00,  0xcac1,  0xcb81,  0xb40,  0xc901,  0x9c0,  0x880,  0xc841,
X0xd801,  0x18c0,  0x1980,  0xd941,  0x1b00,  0xdbc1,  0xda81,  0x1a40,
X0x1e00,  0xdec1,  0xdf81,  0x1f40,  0xdd01,  0x1dc0,  0x1c80,  0xdc41,
X0x1400,  0xd4c1,  0xd581,  0x1540,  0xd701,  0x17c0,  0x1680,  0xd641,
X0xd201,  0x12c0,  0x1380,  0xd341,  0x1100,  0xd1c1,  0xd081,  0x1040,
X0xf001,  0x30c0,  0x3180,  0xf141,  0x3300,  0xf3c1,  0xf281,  0x3240,
X0x3600,  0xf6c1,  0xf781,  0x3740,  0xf501,  0x35c0,  0x3480,  0xf441,
X0x3c00,  0xfcc1,  0xfd81,  0x3d40,  0xff01,  0x3fc0,  0x3e80,  0xfe41,
X0xfa01,  0x3ac0,  0x3b80,  0xfb41,  0x3900,  0xf9c1,  0xf881,  0x3840,
X0x2800,  0xe8c1,  0xe981,  0x2940,  0xeb01,  0x2bc0,  0x2a80,  0xea41,
X0xee01,  0x2ec0,  0x2f80,  0xef41,  0x2d00,  0xedc1,  0xec81,  0x2c40,
X0xe401,  0x24c0,  0x2580,  0xe541,  0x2700,  0xe7c1,  0xe681,  0x2640,
X0x2200,  0xe2c1,  0xe381,  0x2340,  0xe101,  0x21c0,  0x2080,  0xe041,
X0xa001,  0x60c0,  0x6180,  0xa141,  0x6300,  0xa3c1,  0xa281,  0x6240,
X0x6600,  0xa6c1,  0xa781,  0x6740,  0xa501,  0x65c0,  0x6480,  0xa441,
X0x6c00,  0xacc1,  0xad81,  0x6d40,  0xaf01,  0x6fc0,  0x6e80,  0xae41,
X0xaa01,  0x6ac0,  0x6b80,  0xab41,  0x6900,  0xa9c1,  0xa881,  0x6840,
X0x7800,  0xb8c1,  0xb981,  0x7940,  0xbb01,  0x7bc0,  0x7a80,  0xba41,
X0xbe01,  0x7ec0,  0x7f80,  0xbf41,  0x7d00,  0xbdc1,  0xbc81,  0x7c40,
X0xb401,  0x74c0,  0x7580,  0xb541,  0x7700,  0xb7c1,  0xb681,  0x7640,
X0x7200,  0xb2c1,  0xb381,  0x7340,  0xb101,  0x71c0,  0x7080,  0xb041,
X0x5000,  0x90c1,  0x9181,  0x5140,  0x9301,  0x53c0,  0x5280,  0x9241,
X0x9601,  0x56c0,  0x5780,  0x9741,  0x5500,  0x95c1,  0x9481,  0x5440,
X0x9c01,  0x5cc0,  0x5d80,  0x9d41,  0x5f00,  0x9fc1,  0x9e81,  0x5e40,
X0x5a00,  0x9ac1,  0x9b81,  0x5b40,  0x9901,  0x59c0,  0x5880,  0x9841,
X0x8801,  0x48c0,  0x4980,  0x8941,  0x4b00,  0x8bc1,  0x8a81,  0x4a40,
X0x4e00,  0x8ec1,  0x8f81,  0x4f40,  0x8d01,  0x4dc0,  0x4c80,  0x8c41,
X0x4400,  0x84c1,  0x8581,  0x4540,  0x8701,  0x47c0,  0x4680,  0x8641,
X0x8201,  0x42c0,  0x4380,  0x8341,  0x4100,  0x81c1,  0x8081,  0x4040,
X} ;
X
XWTYPE
Xupdcrc( icrc, icp, icnt )
X    WTYPE icrc;
X    unsigned char *icp;
X    int icnt;
X{
X    register WTYPE crc = icrc;
X    register unsigned char *cp = icp;
X    register int cnt = icnt;
X
X    while( cnt-- ) {
X#ifndef SWAPPED
X	crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
X#else
X	crc = (crc>>B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++]; 
X#endif SWAPPED
X    }
X
X    return( crc );
X}
X
X#ifdef MAKETAB
X
X#include <stdio.h>
Xmain()
X{
X    initcrctab();
X}
X
Xinitcrctab()
X{
X    register  int b, i;
X    WTYPE v;
X
X    
X    for( b = 0; b <= (1<<B)-1; ++b ) {
X#ifndef SWAPPED
X	for( v = b<<(W-B), i = B; --i >= 0; )
X	    v = v & ((WTYPE)1<<(W-1)) ? (v<<1)^P : v<<1;
X#else
X	for( v = b, i = B; --i >= 0; )
X	    v = v & 1 ? (v>>1)^P : v>>1;
X#endif	    
X	crctab[b] = v;
X
X	printf( "0x%lx,", v & ((1L<<W)-1L));
X	if( (b&7) == 7 )
X	    printf("\n" );
X	else
X	    printf("  ");
X    }
X}
X#endif
X
X#ifdef TEST
X
X#include <stdio.h>
X#include <fcntl.h>
X
X#define MAXBUF	4096
X
X
X
Xmain( ac, av )
X    int ac; char **av;
X{
X    int fd;
X    int nr;
X    int i;
X    char buf[MAXBUF];
X    WTYPE crc, crc2;
X
X    fd = 0;
X    if( ac > 1 )
X	if( (fd = open( av[1], O_RDONLY )) < 0 ) {
X	    perror( av[1] );
X	    exit( -1 );
X	}
X    crc = crc2 = INIT_CRC;
X
X    while( (nr = read( fd, buf, MAXBUF )) > 0 ) {
X	crc = updcrc( crc, buf, nr );
X    }
X
X    if( nr != 0 )
X	perror( "reading" );
X    else {
X	printf( "%lx\n", crc );
X    }
X
X#ifdef MAGICCHECK
X    /* tack one's complement of crc onto data stream, and
X       continue crc calculation.  Should get a constant (magic number)
X       dependent only on P, not the data.
X     */
X    crc2 = crc ^ -1L;
X    for( nr = W-B; nr >= 0; nr -= B ) {
X	buf[0] = (crc2 >> nr);
X	crc = updcrc(crc, buf, 1);
X    }
X
X    /* crc should now equal magic */
X    buf[0] = buf[1] = buf[2] = buf[3] = 0;
X    printf( "magic test: %lx =?= %lx\n", crc, updcrc(-1, buf, W/B));
X#endif MAGICCHECK
X}
X
X#endif
END_OF_FILE
if test 5848 -ne `wc -c <'unstuffit/updcrc.c'`; then
    echo shar: \"'unstuffit/updcrc.c'\" unpacked with wrong size!
fi
# end of 'unstuffit/updcrc.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--- end of part 2 ---

np@doc.imperial.ac.uk (Nigel Perry) (02/21/91)

[AufsTools - part 3 of 4]

---
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 4)."
# Contents:  mcvert/hqxify.c mcvert/mcvert.c stuffit/sit.c
# Wrapped by np@asun5 on Mon Dec  3 13:15:58 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mcvert/hqxify.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/hqxify.c'\"
else
echo shar: Extracting \"'mcvert/hqxify.c'\" \(19992 characters\)
sed "s/^X//" >'mcvert/hqxify.c' <<'END_OF_FILE'
X#include "mactypes.h"
X
X#define HQXBUFLEN 512
Xbyte hqxbuf[HQXBUFLEN+1], *buf_ptr, *buf_end, *buf_start=hqxbuf+1;
X
X#define MAXLINE 255
Xbyte line[MAXLINE+1], *line_ptr, *line_end, *line_start=line+1;
X
Xint line_count, file_count;
Xint save_state, total_bytes, save_run_length;
Xword save_nibble;
Xchar binfname[BINNAMELEN], hqxfname[BINNAMELEN];
XFILE *hqxfile, *binfile;
X
X/* This routine reads the header of a hqxed file and appropriately twiddles it,
X    determines if it has CRC problems, creates the .bin file, and puts the info
X    into the .bin file.
X    Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile */
X
Xhqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen)
Xchar *type;
Xulong *hqx_datalen, *hqx_rsrclen;
X{   register byte *hqx_ptr, *hqx_end;
X    register ulong calc_crc;
X    hqx_buf *hqx_block;
X    hqx_header *hqx;
X    info_header info;
X    ulong mtim;
X    short crc;
X
X    extern word magic[];
X    extern FILE *verbose;
X    extern char *dir, *ext;
X    extern short calc_mb_crc();
X
X    /* read the hqx header, assuming that I won't exhaust hqxbuf in so doing */
X    fill_hqxbuf();
X    hqx_block = (hqx_buf *) buf_ptr;
X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
X    hqx_ptr = buf_ptr;
X    hqx_end = (byte *) hqx + sizeof(hqx_header) - 1;
X    calc_crc = 0;
X    while (hqx_ptr < hqx_end)
X        calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    buf_ptr = hqx_ptr;
X
X    /* stuff the hqx header data into the info header */
X    bzero(&info, sizeof(info_header));
X    info.nlen = hqx_block->nlen;
X    strncpy(info.name, hqx_block->name, info.nlen);     /* name */
X    bcopy(hqx->type, info.type, 9);             /* type, author, flag */
X    info.flags  &= 0x7e;                        /* reset lock bit, init bit */
X    if (hqx->protect & 0x40) info.protect = 1;  /* copy protect bit */
X    bcopy(hqx->dlen, info.dlen, 8);             /* dlen, rlen */
X    mtim = time2mac(time(0));
X    bcopy(&mtim, info.mtim, 4);
X    bcopy(&mtim, info.ctim, 4);
X    info.uploadvers = '\201';
X    info.readvers = '\201';
X
X    /* calculate MacBinary CRC */
X    crc = calc_mb_crc(&info, 124, 0);
X    info.crc[0] = (char) (crc >> 8);
X    info.crc[1] = (char) crc;
X
X    /* Create the .bin file and write the info to it */
X    unixify(hqx_block->name);
X    sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
X    fprintf(verbose,
X        "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X        hqx_block->name, info.type, info.auth);
X    if ((binfile = fopen(binfname, "w")) == NULL)
X        error("Cannot open %s", binfname);
X    check_hqx_crc(calc_crc, "File header CRC mismatch in %s", binfname);
X    fwrite(&info, sizeof(info), 1, binfile);
X
X    /* Get a couple of items we'll need later */
X    bcopy(info.dlen, hqx_datalen, 4);
X    *hqx_datalen = mac2long(*hqx_datalen);
X    bcopy(info.rlen, hqx_rsrclen, 4);
X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
X    bcopy(info.type, type, 4);
X    }
X
X/* This routine reads the header of a bin file and appropriately twiddles it,
X    creates the .hqx file, and puts the info into the .hqx file.
X    Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
X
Xbin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
Xulong *hqx_datalen, *hqx_rsrclen;
X{   register byte *hqx_ptr, *hqx_end;
X    register ulong calc_crc;
X    hqx_buf *hqx_block;
X    hqx_header *hqx;
X    info_header info;
X    extern word magic[];
X    extern FILE *verbose;
X    extern char **hqxnames_left;
X    extern char *ext;
X
X    strcpy(binfname, *hqxnames_left++);
X    if (!(binfile = fopen(binfname, "r"))) {
X        /* Maybe we are supposed to figure out the suffix ourselves? */
X        strcat(binfname, ext);
X        if (!(binfile = fopen(binfname, "r")))
X            error("Cannot open %s", binfname);
X        }
X    if (!fread(&info, sizeof(info), 1, binfile))
X        error("Unexpected EOF in header of %s", binfname);
X
X    /* stuff the info header into the hqx header */
X    hqx_block = (hqx_buf *) buf_ptr;
X    hqx_block->nlen = info.nlen;
X    strncpy(hqx_block->name, info.name, info.nlen);
X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
X    hqx->version  = 0;
X    bcopy(info.type, hqx->type, 9);             /* type, author, flags */
X    if (info.protect = 1) hqx->protect = 0;     /* protect bit: 0x40 */
X    else hqx->protect = 0;
X    bcopy(info.dlen, hqx->dlen, 8);             /* dlen, rlen */
X
X    /* Create the .hqx file and write the info to it */
X    strncpy(hqxfname, info.name, info.nlen);
X	hqxfname[info.nlen] = '\0';
X    unixify(hqxfname);
X    fprintf(verbose,
X        "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X        hqxfname, info.type, info.auth);
X
X    calc_crc = 0;
X    hqx_ptr = (byte *) hqx_block;
X    hqx_end = hqx_ptr + hqx_block->nlen + sizeof(hqx_header);
X    while (hqx_ptr < hqx_end)
X        calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    buf_ptr = hqx_end;
X    write_hqx_crc(calc_crc);
X
X    /* Get a couple of items we'll need later */
X    bcopy(info.dlen, hqx_datalen, 4);
X    *hqx_datalen = mac2long(*hqx_datalen);
X    bcopy(info.rlen, hqx_rsrclen, 4);
X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
X    }
X
X
X/* This routine copies bytes from the decoded input stream to the output.  
X    It also pads to a multiple of 128 bytes on the output, which is part
X    of the .bin format */
Xword hqx_to_bin_fork(nbytes)
Xregister ulong nbytes;
X{   register byte *c;
X    register ulong calc_crc;
X    register int c_length;
X    ulong extra_bytes;
X    extern word magic[];
X
X    extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
X    calc_crc = 0;
X    for (;;) {
X        c = buf_ptr;
X        c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
X        nbytes -= c_length;
X        fwrite(c, sizeof(byte), c_length, binfile);
X        while (c_length--)
X            calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
X        if (!nbytes) break;
X        fill_hqxbuf();
X        }
X    buf_ptr = c;
X    while (extra_bytes--) putc(0, binfile);
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    return (word) calc_crc;
X    }
X
X/* This routine copies bytes from the input stream to the encoded output.  
X    It also pads to a multiple of 128 bytes on the input, which is part
X    of the .bin format */
Xword bin_to_hqx_fork(nbytes)
Xregister ulong nbytes;
X{   register byte *c;
X    register ulong calc_crc;
X    register int c_length;
X    ulong extra_bytes;
X    extern word magic[];
X
X    extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
X    calc_crc = 0;
X    for (;;) {
X        c = buf_ptr;
X        c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
X        nbytes -= c_length;
X        fread(c, sizeof(byte), c_length, binfile);
X        buf_ptr += c_length;
X        while (c_length--)
X            calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
X        if (!nbytes) break;
X        empty_hqxbuf();
X        }
X    buf_ptr = c;
X
X    fseek(binfile, extra_bytes, 1);
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X    return (word) calc_crc;
X    }
X
X/* Essentials for Binhex 8to6 run length encoding */
X#define RUNCHAR 0x90
X#define MAXRUN 255
X#define IS_LEGAL <0x40
X#define ISNT_LEGAL >0x3f
X#define DONE 0x7F /* tr68[':'] = DONE, since Binhex terminator is ':' */
X#define SKIP 0x7E /* tr68['\n'|'\r'] = SKIP, i. e. end of line char.  */
X#define FAIL 0x7D /* character illegal in binhex file */
X
Xbyte tr86[] =
X        "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; 
Xbyte tr68[] = {
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
X    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
X    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
X    0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
X    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
X    0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
X    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
X    0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
X    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
X    0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
X    0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X    };
X
X/*
X *  This procedure transparently reads and decodes the hqx input.  It does run 
X *  length and 6 to 8 decoding.
X */
X#define READING 0
X#define SKIPPING 1
X#define FIND_START_COLON 2
X
X/* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
X#define X_MAIL_STR "\054\014\043\061\070\073\065\077\177"
X#define X_MAIL_LEN strlen(X_MAIL_STR)
X
Xfill_hqxbuf()
X{   register ulong c, nibble;
X    register int not_in_a_run = TRUE, state68;
X    register byte *fast_buf, *fast_line;
X    static int status = FIND_START_COLON;
X
X    buf_ptr = fast_buf = buf_start;
X    fast_line = line_ptr;
X    state68 = save_state;
X    nibble = save_nibble;
X    if (save_run_length > 0) {
X        c = save_run_length;
X        save_run_length = 0;
X        goto continue_run;
X        }
X    while (fast_buf < buf_end) {
X        next_char:
X        if ((c = *fast_line++) ISNT_LEGAL) {
X            if (c == DONE) break;
X            next_line:
X            if (!fgets(line_start, MAXLINE, hqxfile) && !new_in_hqx_file())
X                if (status == FIND_START_COLON) exit(0);
X		else error("Premature EOF in %s\n", hqxfname);
X            line_ptr = line_start;
X            scan_line:
X            fast_line = line_ptr;
X	    while ((*fast_line = tr68[*fast_line]) IS_LEGAL) fast_line++;
X	    c = *fast_line;
X            switch (status) {
X            case READING:
X                if (c == SKIP && fast_line == line_end) break;
X                if (c == DONE) {
X                    status = FIND_START_COLON;
X                    break;
X                    }
X                status = SKIPPING;
X                goto next_line;
X            case SKIPPING:
X                if (c == SKIP && fast_line == line_end) {
X                    status = READING;
X                    break;
X                    }
X		/*  GMT, 1/9/90: Added this clause to avoid losing the last
X		 *  line if it was preceeded by a skipped line.  */
X                if (c == DONE) { 
X		  /* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
X		  if( (fast_line - line_ptr == X_MAIL_LEN - 1)
X		     && (strncmp(line_ptr, X_MAIL_STR, X_MAIL_LEN) == 0)) goto next_line;
X                    status = FIND_START_COLON;
X                    break;
X                    }
X                goto next_line;
X            case FIND_START_COLON:
X                if (*line_start == DONE) {
X                    status = READING;
X                    line_ptr++;
X                    goto scan_line;
X                    }
X                goto next_line;
X                }
X            fast_line = line_ptr;
X            c = *fast_line++;
X	  }
X
X        /* Finally, we have the next 6 bits worth of data */
X        switch (state68++) {
X        case 0:
X            nibble = c;
X            goto next_char;
X        case 1:
X            nibble = (nibble << 6) | c;
X            c = nibble >> 4;
X            break;
X        case 2:
X            nibble = (nibble << 6) | c;
X            c = (nibble >> 2) & 0xff;
X            break;
X        case 3:
X            c = (nibble << 6) & 0xff | c;
X            state68 = 0;
X            break;
X            }
X        if (not_in_a_run)
X            if (c != RUNCHAR) *fast_buf++ = c;
X            else {not_in_a_run = FALSE; goto next_char;}
X        else {
X            if (c--) {
X                not_in_a_run = buf_end - fast_buf;
X                if (c > not_in_a_run) {
X                    save_run_length = c - not_in_a_run;
X                    c = not_in_a_run;
X                    }
X                continue_run:
X                not_in_a_run = fast_buf[-1];
X                while (c--) *fast_buf++ = not_in_a_run;
X                }
X            else *fast_buf++ = RUNCHAR;
X            not_in_a_run = TRUE;
X            }
X        }
X    total_bytes += fast_buf - buf_ptr;
X    buf_start[-1] = fast_buf[-1];
X    line_ptr = fast_line;
X    save_state = state68;
X    save_nibble = nibble;
X    }
X
X
Xnew_in_hqx_file()
X{   char *hqx_ext;
X    extern char **hqxnames_left;
X    if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') return FALSE;
X    strcpy(hqxfname, *hqxnames_left++);
X    hqx_ext = hqxfname + strlen(hqxfname) - 4;
X    if (!strcmp(hqx_ext, ".hqx"))
X        if (!freopen(hqxfname, "r", hqxfile))
X            error("Cannot open %s\n", hqxfname);
X            else;
X    else {
X        if (!freopen(hqxfname, "r", hqxfile)) {
X            hqx_ext += 4;
X            strcpy(hqx_ext, ".hqx");
X            if (!freopen(hqxfname, "r", hqxfile)) {
X                error("Cannot find %s\n", hqxfname);
X            }
X        }
X      }
X    fgets(line_start, MAXLINE, hqxfile);
X    return TRUE;
X    }
X
X/*
X *  This procedure transparently encodes and writes the hqx output.  
X *  It does run length and 8 to 6 encoding.
X */
Xempty_hqxbuf()
X{   register ulong c, nibble, last_c;
X    register byte *fast_buf, *fast_line;
X    register int state86, dont_look_for_runs = FALSE, run_length;
X    extern int maxlines;
X
X    run_length = save_run_length;
X    last_c = buf_start[-1];
X    fast_buf = buf_start;
X    fast_line = line_ptr;
X    state86 = save_state;
X    nibble = save_nibble;
X    while (fast_buf < buf_ptr) {
X        c = *fast_buf++;
X        if (dont_look_for_runs) dont_look_for_runs = FALSE;
X        else if (last_c == c &&  run_length < MAXRUN) {run_length++; continue;}
X        else {
X            if (run_length >1) {
X                --fast_buf;
X                if (run_length == 2 && last_c != RUNCHAR) c = last_c;
X                else {
X                    c = RUNCHAR;
X                    *--fast_buf = run_length;
X                    dont_look_for_runs = TRUE;
X                    }
X                run_length = 1;
X                }
X            else last_c = c;
X            if (c == RUNCHAR && !dont_look_for_runs) {
X                *--fast_buf = 0;
X                dont_look_for_runs = TRUE;
X                }
X            }
X
X        if (fast_line == line_end) {
X            if (line_count++ == maxlines) new_out_hqx_file();
X            fputs(line_start, hqxfile);
X            fast_line = line_start;
X            }
X
X        switch (state86++) {
X        case 0:
X            *fast_line++ = tr86[ c >> 2 ];
X            nibble = (c << 4) & 0x3f;
X            break;
X        case 1:
X            *fast_line++ = tr86[ (c >> 4) | nibble ];
X            nibble = (c << 2) & 0x3f;
X            break;
X        case 2:
X            *fast_line++ = tr86[ (c >> 6) | nibble ];
X            if (fast_line == line_end) {
X                if (line_count++ == maxlines) new_out_hqx_file();
X                fputs(line_start, hqxfile);
X                fast_line = line_start;
X                }
X            *fast_line++ = tr86[ c & 0x3f ];
X            state86 = 0;
X            break;
X            }
X        }
X    save_run_length = run_length;
X    buf_start[-1] = last_c;
X    buf_ptr = buf_start;
X    line_ptr = fast_line;
X    save_state = state86;
X    save_nibble = nibble;
X    }
X
Xnew_out_hqx_file()
X{   char filename[NAMELEN + 7];
X    extern int maxlines;
X    fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
X    fclose(hqxfile);
X    file_count++;
X    if (maxlines) sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
X    else sprintf(filename, "%s.hqx", hqxfname);
X    if ((hqxfile = fopen(filename, "w")) == NULL)
X        error("Can't create %s", filename);
X    if (file_count > 1)
X        fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
X    else fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
X    line_count = 3;
X    }
X
Xcheck_hqx_crc(calc_crc, msg, name)
Xword calc_crc;
Xchar msg[], name[];
X{   word read_crc;
X    if (buf_ptr >= buf_end) fill_hqxbuf();
X    read_crc = *buf_ptr++ << 8;
X    if (buf_ptr >= buf_end) fill_hqxbuf();
X    read_crc |= *buf_ptr++;
X    if (read_crc != calc_crc) error(msg, name);
X    }
X
Xwrite_hqx_crc(calc_crc)
Xword calc_crc;
X{   if (buf_ptr == buf_end) empty_hqxbuf();
X    *buf_ptr++ = calc_crc >> 8;
X    if (buf_ptr == buf_end) empty_hqxbuf();
X    *buf_ptr++ = calc_crc;
X    }
X
Xun_hqx(unpit_flag)
Xint unpit_flag;
X{   char type[4];
X    ulong hqx_datalen, hqx_rsrclen;
X    word un_pit();
X    int unpitting, bytes_read;
X    word calc_crc;
X    extern char **hqxnames_left;
X
X    hqxfile = fopen("/dev/null", "r");
X    line_end = line_start + HQXLINELEN;
X    buf_end = buf_start + HQXBUFLEN;
X	for (;;) {
X        total_bytes = 0;
X        line_ptr = line_start;
X        line_ptr[0] = SKIP;
X        save_state = 0;
X        save_run_length = 0;
X
X        hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen); /* binfname */
X
X        unpitting = unpit_flag && !strcmp(type, "PIT ");
X        if (unpitting) {
X            fclose(binfile);
X            unlink(binfname);
X            bytes_read = total_bytes - (buf_end - buf_ptr);
X            calc_crc = un_pit();
X            bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
X            if (bytes_read != hqx_datalen)
X                fprintf(stderr,
X                  "Warning - Extraneous characters ignored in %s\n", binfname);
X            }
X        else calc_crc = hqx_to_bin_fork(hqx_datalen);
X        check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
X
X        calc_crc = hqx_to_bin_fork(hqx_rsrclen);
X        check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
X
X        if (!unpitting) fclose(binfile);
X        }
X    }
X
Xre_hqx()
X{   word calc_crc;
X    ulong hqx_datalen, hqx_rsrclen;
X    extern char **hqxnames_left;
X    extern int maxlines;
X    line_end = line_start + HQXLINELEN;
X    buf_end = buf_start + HQXBUFLEN;
X    while (*hqxnames_left[0] != '-') {
X        hqxfile = fopen("/dev/null", "w");
X        line_count = maxlines;
X        file_count = 0;
X        line_ptr = line_start;
X        *line_ptr++ = ':';
X        strcpy(line_end, "\n");
X        buf_ptr = buf_start;
X        save_state = 0;
X        save_run_length = 1;
X
X        bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen);   /* calculates hqxfname */
X
X        calc_crc = bin_to_hqx_fork(hqx_datalen);
X        write_hqx_crc(calc_crc);
X
X        calc_crc = bin_to_hqx_fork(hqx_rsrclen);
X        write_hqx_crc(calc_crc);
X		*buf_ptr = !buf_ptr[-1];      /* To end a run and to get the last */
X		buf_ptr++;
X        empty_hqxbuf();                 /* stray bits, temporarily add a char */
X        if (save_state != 2) --line_ptr;
X        if (line_ptr == line_end) {
X            fputs(line_start, hqxfile);
X            line_ptr = line_start;
X            }
X        strcpy(line_ptr, ":\n");
X        fputs(line_start, hqxfile);
X        fclose(hqxfile);
X        }
X    }
END_OF_FILE
if test 19992 -ne `wc -c <'mcvert/hqxify.c'`; then
    echo shar: \"'mcvert/hqxify.c'\" unpacked with wrong size!
fi
# end of 'mcvert/hqxify.c'
fi
if test -f 'mcvert/mcvert.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcvert/mcvert.c'\"
else
echo shar: Extracting \"'mcvert/mcvert.c'\" \(13666 characters\)
sed "s/^X//" >'mcvert/mcvert.c' <<'END_OF_FILE'
X/* mcvert.c - version 1.05 - 10 January, 1990 modified 12 March, 1990 by NP
X * Written by Doug Moore - Rice University - dougm@rice.edu - April '87
X * Sun bug fixes, assorted stuff - Jim Sasaki, March '89
X * Changed default max_line_size from 2000 to unlimited - Doug Moore, April, '89
X * Sun 3/60 doesn't like odd-sized structs.  Bug fixed - Doug Moore, April, '89
X *                                              - aided by Spencer W. Thomas
X * Didn't handle properly many hqx files combined in one file.  Bug fixed -
X *                                           Doug Moore, June, '89
X * Modified to handle MacBinaryII specification. Jim Van Verth, Sept, '89
X *
X * Fixed a bug when there are blank lines in hqx data, as happens when newline
X * get translated to CRLF and then to \n\n, common for some file transfers.
X * The last hqx line would be lost if the previous line was blank or junk.
X *	Glenn Trewitt, Stanford University, 1990	(1.05)
X *
X * Mcvert would hiccup on mail header lines "X-Mailer: ELM [version 2.2 PL14]"
X * as "X-Mailer:" is a vaild hqx line! Added in code to special case this
X * line and keep scanning for the real hqx data.
X *      Nigel Perry, Imperial College, 12 March 1990 [NP]
X *
X * This program may be freely distributed for non-profit purposes.  It may not
X * be sold, by itself or as part of a collection of software.  It may be freely
X * modified as long as no modified version is distributed.  Modifications of
X * interest to all can be incorporated into the program by sending them to me
X * for distribution.  Parts of the code can be used in other programs.  I am not
X * responsible for any damage caused by this program.  I hope you enjoy it.
X */
X
X#include "mactypes.h"
X
X#define HQX 0
X#define TEXT 1
X#define DATA 2
X#define RSRC 3
X#define HOST 4
X#define FORWARDS 0
X#define BACKWARDS 1
X
XFILE *verbose;
Xchar **hqxnames, **hqxnames_left;
Xchar *dir, *ext, *text_author;
Xchar *maxlines_str;
Xint maxlines;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{   char *flags, *getenv();
X    int direction, mode, unpit_flag;
X
X    argv++;
X    argc--;
X    verbose = stderr;
X    direction = FORWARDS;
X    mode = HQX;
X    unpit_flag = 0;
X
X    if ((text_author = getenv("MAC_EDITOR"))    == NULL)    text_author = "MACA";
X    if ((ext =         getenv("MAC_EXT"))       == NULL)    ext = ".bin";
X    if ((dir =         getenv("MAC_DLOAD_DIR")) == NULL)    dir = ".";
X    if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL)  maxlines = 0;
X    else										 maxlines = atoi(maxlines_str);
X    
X    /* Make command line arguments globally accessible */
X    hqxnames = (char **) calloc(argc+1, sizeof(char *));
X    hqxnames_left = hqxnames;
X    while (argc--)  *hqxnames_left++ = *argv++;
X    *hqxnames_left = "-";
X    hqxnames_left = hqxnames;
X
X    while (strcmp(*hqxnames_left, "-")) {
X        if (hqxnames_left[0][0] == '-') {
X            flags = *hqxnames_left++;
X            while (*++flags)
X                switch (*flags) {
X                case 'x':
X                    mode = HQX;
X                    break;
X                case 'u':
X                    mode = TEXT;
X                    break;
X                case 'd':
X                    mode = DATA;
X                    break;
X                case 'r':
X                    mode = RSRC;
X                    break;
X		case 'h':
X		    mode = HOST;
X		    break;
X                case 'D':
X                    direction = FORWARDS;
X                    break;
X                case 'U':
X                    direction = BACKWARDS;
X                    break;
X                case 'q':
X                    unpit_flag = 0;
X                    break;
X                case 'p':
X                    unpit_flag = 1;
X                    break;
X                case 's':
X                    verbose = fopen("/dev/null", "w");
X                    break;
X                case 'v':
X                    verbose = stderr;
X                    break;
X                default:
X                    error(
X                    "Usage: mcvert [ -[r|d|u|x|h] [D|U] [p|q] [s|v] ] filename...",
X                    NULL);
X                    }
X            }
X
X        if (direction == BACKWARDS)
X            if (mode == HQX && unpit_flag) re_hqx();/* no re_pit() yet */
X            else if (mode == HQX) re_hqx();
X            else re_other(mode);
X        else
X            if (mode == HQX) un_hqx(unpit_flag);
X            else un_other(mode);
X        }
X    }
X
X/* An array useful for CRC calculations that use 0x1021 as the "seed" */
Xword magic[] = {
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X    };
X
X
X/*
X * calc_crc() --
X *   Compute the MacBinary II-style CRC for the data pointed to by p, with the
X *   crc seeded to seed.
X *
X *   Modified by Jim Van Verth to use the magic array for efficiency.
X */
Xshort calc_mb_crc(p, len, seed)
Xunsigned char *p;
Xlong len;
Xshort seed;
X{
X  short hold;      /* crc computed so far */
X  long  i;         /* index into data */
X
X  extern unsigned short magic[];   /* the magic array */
X
X  hold = seed;     /* start with seed */
X  for (i = 0; i < len; i++, p++) {
X    hold ^= (*p << 8);
X    hold = (hold << 8) ^ magic[(unsigned char)(hold >> 8)];
X  }
X
X  return (hold);
X} /* calc_crc() */
X
X
X/* Report a fatal error */
Xerror(msg, name)
Xchar msg[], name[];
X{   fprintf(stderr, msg, name);
X    putc('\n', stderr);
X    exit(1);
X    }
X
X/* replace illegal Unix characters in file name */
X/* make sure host file name doesn't get truncated beyond recognition */
Xunixify(np)
Xregister byte *np;
X{   register ulong c;
X    c = strlen(np);
X    if (c > SYSNAMELEN - 4) c = SYSNAMELEN - 4;
X    np[c] = '\0';
X    np--;
X    while (c = *++np)
X        if (c <= ' ' || c == '/' || c > '~') *np = '_';
X    }
X
X/* Convert Unix time (GMT since 1-1-1970) to Mac
X                                    time (local since 1-1-1904) */
X#define MACTIMEDIFF 0x7c25b080 /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
X
Xulong time2mac(time)
Xulong time;
X{   struct timeb tp;
X    ftime(&tp);
X    return long2mac(time + MACTIMEDIFF
X                    - 60 * (tp.timezone - 60 * tp.dstflag));
X    }
X
X
X/* This procedure copies the input file to the output file, basically, although
X    in TEXT mode it changes LF's to CR's and in any mode it forges a Mac info 
X    header.  Author type for TEXT mode can come from the MAC_EDITOR environ-
X    ment variable if it is defined. */
X
Xun_other(mode)
Xint mode;
X{   register ulong b;
X    register ulong nchars;
X    char txtfname[BINNAMELEN], binfname[BINNAMELEN];
X    FILE *txtfile, *binfile; 
X    char *suffix;
X    struct stat stbuf;
X    info_header info;
X    int extra_chars;
X    ulong dlen, rlen, mtim, ctim;
X    short crc, calc_mb_crc();
X
X    if (mode == DATA) suffix = ".data";
X    else if (mode == RSRC) suffix = ".rsrc";
X    else suffix = ".text";
X
X    while (hqxnames_left[0][0] != '-') {
X
X        strcpy(txtfname, *hqxnames_left++);
X        if (!(txtfile = fopen(txtfname, "r"))) {
X            /* Maybe we are supposed to figure out the suffix ourselves? */
X            strcat(txtfname, suffix);
X            if (!(txtfile = fopen(txtfname, "r")))
X                error("Cannot open %s", txtfname);
X            }
X
X        if (stat(txtfname, &stbuf))
X            error("Cannot read %s", txtfname);
X
X        /* stuff header data into the info header */
X        bzero(&info, sizeof(info_header));
X        info.nlen = strlen(txtfname);
X        info.nlen = (info.nlen > NAMELEN) ? NAMELEN : info.nlen;
X	info.name[info.nlen] = '\0';
X        strcpy(info.name, txtfname);           /* name */
X        mtim = time2mac(stbuf.st_mtime);
X        ctim = time2mac(stbuf.st_ctime);
X        bcopy(&mtim, info.mtim, 4);
X        bcopy(&ctim, info.ctim, 4);
X	info.uploadvers = '\201';
X	info.readvers = '\201';
X
X        if (mode == RSRC) {
X            /* dlen is already zero */
X            rlen = long2mac(stbuf.st_size);
X            bcopy(&rlen, info.rlen, 4);
X            bcopy("APPL", info.type, 4);
X            bcopy("CCOM", info.auth, 4);
X            }
X        else {
X            dlen = long2mac(stbuf.st_size);
X            bcopy(&dlen, info.dlen, 4);
X            /* rlen is already zero */
X            bcopy("TEXT", info.type, 4);
X            if (mode == DATA) bcopy("????", info.auth, 4);
X            else bcopy(text_author, info.auth, 4);
X            }
X
X	/* calculate CRC */
X	crc = calc_mb_crc(&info, 124, 0);
X	info.crc[0] = (char) (crc >> 8);
X	info.crc[1] = (char) crc;
X
X        /* Create the .bin file and write the info to it */
X        sprintf(binfname, "%s/%s%s", dir, txtfname, ext);
X        if ((binfile = fopen(binfname, "w")) == NULL)
X            error("Cannot open %s", binfname);
X        fprintf(verbose,
X                "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X                txtfname, info.type, info.auth);
X        fwrite(&info, sizeof(info), 1, binfile);
X
X        nchars = stbuf.st_size;
X        extra_chars = 127 - (nchars+127) % 128;
X        if (mode == TEXT) while (nchars--) {
X            b = getc(txtfile);
X            if (b == LF) b = CR;
X            putc(b, binfile);
X            }
X        else while (nchars--) putc(getc(txtfile), binfile);
X
X        while (extra_chars--) putc(0, binfile);
X        fclose(binfile);
X        fclose(txtfile);
X        }
X    }
X
X/* This procedure copies the input file to the output file, basically, although
X    in TEXT mode it changes CR's to LF's and in any mode it skips over the Mac
X    info header. */
X
Xre_other(mode)
Xint mode;
X{   register ulong b;
X    register ulong nchars;
X    char txtfname[BINNAMELEN], binfname[BINNAMELEN];
X    FILE *txtfile, *binfile; 
X    char *suffix;
X    info_header info;
X
X    if (mode == DATA) suffix = ".data";
X    else if (mode == RSRC) suffix = ".rsrc";
X    else suffix = ".text";
X
X    while (hqxnames_left[0][0] != '-') {
X
X        strcpy(binfname, *hqxnames_left++);
X        if ((binfile = fopen(binfname, "r")) == NULL) {
X            /* Maybe we are supposed to figure out the suffix ourselves? */
X            strcat(binfname, ext);
X            if (!(binfile = fopen(binfname, "r")))
X                error("Cannot open %s", binfname);
X            }
X
X        /* Read the info from the .bin file, create the output file */
X        fread(&info, sizeof(info), 1, binfile);
X        strncpy(txtfname, info.name, info.nlen);
X	txtfname[info.nlen] = '\0';
X        fprintf(verbose,
X                "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X                txtfname, info.type, info.auth);
X        if ((txtfile = fopen(txtfname, "r")) == NULL) {
X            if ((txtfile = fopen(txtfname, "w")) == NULL)
X                error("Cannot open %s", txtfname);
X            }
X        else {
X            fclose(txtfile);
X            strcat(txtfname, suffix);
X            if ((txtfile = fopen(txtfname, "w")) == NULL)
X                error("Cannot open %s", txtfname);
X            }
X
X        nchars = mac2long(* (ulong *) info.dlen);
X        if (mode == TEXT) while (nchars--) {
X            b = getc(binfile);
X            if (b == CR) b = LF;
X            putc(b, txtfile);
X            }
X        else if (mode == DATA) while (nchars--)
X            putc(getc(binfile), txtfile);
X        else {
X            while (nchars--) getc(binfile);
X            nchars = mac2long(* (ulong *) info.rlen);
X            while (nchars--) putc(getc(binfile), txtfile);
X            }
X
X        fclose(binfile);
X        fclose(txtfile);
X        }
X    }
END_OF_FILE
if test 13666 -ne `wc -c <'mcvert/mcvert.c'`; then
    echo shar: \"'mcvert/mcvert.c'\" unpacked with wrong size!
fi
# end of 'mcvert/mcvert.c'
fi
if test -f 'stuffit/sit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stuffit/sit.c'\"
else
echo shar: Extracting \"'stuffit/sit.c'\" \(12417 characters\)
sed "s/^X//" >'stuffit/sit.c' <<'END_OF_FILE'
X/*
X * sit - Stuffit for UNIX
X *  Puts unix data files into stuffit archive suitable for downloading
X *	to a Mac.  Automatically processes files output from xbin.
X *
X *  Reverse engineered from unsit by Allan G. Weber, which was based on
X *  macput, which was based on ...
X *  Just like unsit this uses the host's version of compress to do the work.
X *
X * Examples:
X *   1) take collection of UNIX text files and make them LSC text files 
X *	when uncompressed on the mac:
X *	   sit -u -T TEXT -C KAHL file ...
X *   2) Process output from xbin:
X *	   xbin file1	 (produces FileOne.{info,rsrc,data})
X *	   sit file1
X *
X *  Tom Bereiter
X *	..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
X *
X * This version for CAP aufs files based on info from aufs source + mcvert etc.
X * Aufs version is program is called AUFSNAME (default stuffit)
X *
X * Aug 90. Nigel Perry, np@doc.ic.ac.uk
X *
X */
X#define BSD
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include "sit.h"
X#ifdef BSD
X#include <sys/time.h>
X#include <sys/timeb.h>
X#else
X#include <time.h>
Xextern long timezone;
X#endif
X
X#ifndef min
X#define min(a,b) ((a)<(b)?(a):(b))
X#endif
X
X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
X#define TIMEDIFF 0x7c25b080
X
X/* if called by this name, program will work on aufs files */
X#define AUFSNAME "stuffit"
X
Xstruct sitHdr sh;
Xstruct fileHdr fh;
X
Xchar buf[BUFSIZ];
Xchar *defoutfile = "archive.sit";
Xint ofd;
Xushort crc;
Xint clen;
Xint rmfiles;
Xint	unixf;
Xchar *Creator, *Type;
Xint aufs;
X
Xusage() { fprintf(stderr,"Usage: sit file\n"); }
Xextern char *optarg;
Xextern int optind;
X
X/********************************************************************************/
X/* added for aufs, nicked from various places... */
X
X/* following from mcvert program */
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte;     /* one byte, obviously */
Xtypedef unsigned short word;    /* must be 2 bytes */
Xtypedef unsigned long ulong;    /* 4 bytes */
X
X#define NAMELEN 63              /* maximum legal Mac file name length */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks.  The first block is the
Xinfo_header (see below).  Then comes the data fork, null padded to fill the
Xlast block.  Then comes the resource fork, padded to fill the last block.  A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/ 
Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
X                        longs don't align to word boundaries */
X            byte version;           /* there is only a version 0 at this time */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;             /* Locked, Invisible,Bundle, System */
X                                    /* Bozo, Busy, Changed, Init */
X            byte icon_vert[2];      /* Vertical icon position within window */
X            byte icon_horiz[2];     /* Horizontal icon postion in window */
X            byte window_id[2];      /* Window or folder ID. */
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
X            byte rflen[4];          /* Resource Fork length         byte first */
X            byte cdate[4];          /* File's creation date. */
X            byte mdate[4];          /* File's "last modified" date. */
X            byte ilen[2];           /* GetInfo message length */
X	    byte flags2;            /* Finder flags, bits 0-7 */
X	    byte unused[14];       
X	    byte packlen[4];        /* length of total files when unpacked */
X	    byte headlen[2];        /* length of secondary header */
X	    byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
X	    byte readvers;          /* Minimum MacBinary II version needed to read this file */
X            byte crc[2];            /* CRC of the previous 124 bytes */
X	    byte padding[2];        /* two trailing unused bytes */
X            } info_header;
X
X/* end of mcvert stuff */
X/* from CAP aufs documentation */
X
X#define FINFOLEN 32
X#define MAXCLEN 199
Xtypedef struct
X{  /* byte fi_fndr[FINFOLEN]; */	/* finder info */
X   /* what I think the above is... */
X   ulong fndr_type, fndr_creator;
X   word fndr_flags;
X   ulong fndr_loc;
X   word fndr_fldr;
X   word fndr_icon;
X   byte fndr_unused[8];
X   word fndr_comment;
X   ulong fndr_putaway;
X   /* end of fi_fndr */
X
X   word fi_attr;			/* attributes */
X#define FI_MAGIC1 255
X   byte fi_magic1;		/* was: length of comment */
X#define FI_VERSION 0x10		/* version major 1, minor 0 */
X				/* if more than 8 versions then */
X				/* something wrong anyway */
X   byte fi_version;		/* version number */
X#define FI_MAGIC 0xda
X   byte fi_magic;		/* magic word check */
X   byte fi_bitmap;		/* bitmap of included info */
X#define FI_BM_SHORTFILENAME 0x1	/* is this included? */
X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
X   byte fi_shortfilename[12+1];	/* possible short file name */
X   byte fi_macfilename[32+1];	/* possible macintosh file name */
X   byte fi_comln;		/* comment length */
X   byte fi_comnt[MAXCLEN+1];	/* comment string */
X} FileInfo;
X
XFileInfo fndr_info;
X
X/* end aufs */
X/********************************************************************************/
X
Xmain(argc,argv) char **argv; {
X	int i,n;
X	int total, nfiles;
X	int c;
X
X    rmfiles = unixf = 0;
X    aufs = strcmp(argv[0], AUFSNAME) == 0;
X
X    while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
X	switch (c) {
X		case 'r':
X			rmfiles++;	/* remove files when done */
X			break;
X		case 'o':		/* specify output file */
X			defoutfile = optarg;
X			break;
X		case 'u':		/* unix file -- change '\n' to '\r' */
X			unixf++;
X			break;
X		case 'C':		/* set Mac creator */
X			Creator = optarg;
X			break;
X		case 'T':		/* set Mac file type */
X			Type = optarg;
X			break;
X		case '?':
X			usage();
X			exit(1);
X	}
X
X	if(aufs && (strlen(defoutfile) > 32))
X	{   fprintf(stderr, "Output name must not exceed 32 characters: %s\n", defoutfile);
X	    exit(-1);
X	}
X
X	if(aufs)
X	{    /* make the .finderinfo file */
X	    char buf[32+12+1];
X
X	    strcpy(buf, ".finderinfo/");
X	    strcat(buf, defoutfile);
X	    if ((ofd=creat(buf,0644))<0)
X	    {   perror(buf);
X		    exit(1);
X	    }
X	    bzero(&fndr_info, sizeof(FileInfo));
X	    bcopy("SIT!", &fndr_info.fndr_type, 4);
X	    bcopy("SIT!", &fndr_info.fndr_creator, 4);
X	    fndr_info.fi_magic1 = FI_MAGIC1;
X	    fndr_info.fi_version = FI_VERSION;
X	    fndr_info.fi_magic = FI_MAGIC;
X	    fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
X	    strcpy(fndr_info.fi_macfilename, defoutfile);
X	    write(ofd, &fndr_info, sizeof(FileInfo));
X	    close(ofd);
X	}
X
X	if ((ofd=creat(defoutfile,0644))<0) {
X		perror(defoutfile);
X		exit(1);
X	}
X	/* empty header, will seek back and fill in later */
X	write(ofd,&sh,sizeof sh);
X
X	for (i=optind; i<argc; i++) {
X		n = put_file(argv[i]);
X		if (n) {
X			total += n;
X			nfiles++;
X		}
X	}
X	lseek(ofd,0,0);
X
X	total += sizeof(sh);
X	/* header header */
X    strncpy(sh.sig1,"SIT!",4);
X    cp2(nfiles,sh.numFiles);
X    cp4(total,sh.arcLen);
X    strncpy(sh.sig2,"rLau",4);
X    sh.version = 1;
X
X	write(ofd,&sh,sizeof sh);
X}
X
Xput_file(name)
Xchar name[];
X{
X	struct stat st;
X	struct infohdr ih;
X	int i,n,fd;
X	long fpos1, fpos2;
X	char nbuf[256], *p;
X	int fork=0;
X	long tdiff;
X	struct tm *tp;
X#ifdef BSD
X	struct timeb tbuf;
X#else
X	long bs;
X#endif
X
X	fpos1 = lseek(ofd,0,1); /* remember where we are */
X	/* write empty header, will seek back and fill in later */
X	bzero(&fh,sizeof fh);
X	write(ofd,&fh,sizeof fh);
X
X	/* look for resource fork */
X	if(aufs)
X	{   strcpy(nbuf, ".resource/");
X	    strcat(nbuf, name);
X	}
X	else
X	{   strcpy(nbuf,name);
X	    strcat(nbuf,".rsrc");
X	}
X	if (stat(nbuf,&st)>=0 && st.st_size) {	/* resource fork exists */
X		dofork(nbuf);
X		cp4(st.st_size,fh.rLen);
X		cp4(clen,fh.cRLen);
X		cp2(crc,fh.rsrcCRC);
X		fh.compRMethod = lpzComp;
X		fork++;
X	}
X	if (rmfiles) unlink(nbuf);	/* ignore errors */
X
X	/* look for data fork */
X	st.st_size = 0;
X	strcpy(nbuf,name);
X	if (stat(nbuf,&st)<0) {		/* first try plain name */
X		strcat(nbuf,".data");
X		stat(nbuf,&st);
X	}
X	if (st.st_size) {		/* data fork exists */
X		dofork(nbuf);
X		cp4(st.st_size,fh.dLen);
X		cp4(clen,fh.cDLen);
X		cp2(crc,fh.dataCRC);
X		fh.compDMethod = lpzComp;
X		fork++;
X	}
X	if (fork == 0) {
X		fprintf(stderr,"%s: no data or resource files\n",name);
X		return 0;
X	}
X	if (rmfiles) unlink(nbuf);	/* ignore errors */
X
X	/* look for .info file */
X	if(aufs)
X	{   strcpy(nbuf, ".finderinfo/");
X	    strcat(nbuf, name);
X	}
X	else
X	{   strcpy(nbuf,name);
X	    strcat(nbuf,".info");
X	}
X	if((fd=open(nbuf,0))>=0
X	   && ((!aufs && read(fd,&ih,sizeof(ih))==sizeof(ih))
X	       || (aufs && read(fd,&fndr_info,sizeof(FileInfo))==sizeof(FileInfo))
X	      )
X	  )
X	{   if(aufs)
X	    {   char *np;
X		
X		np = (char *)(fndr_info.fi_bitmap & FI_BM_MACINTOSHFILENAME ? fndr_info.fi_macfilename
X									    : fndr_info.fi_shortfilename);
X		fh.fName[0] = (char)strlen(np);
X		strncpy(fh.fName+1, np, 64);
X		bcopy(&fndr_info.fndr_type, fh.fType, 4);
X		bcopy(&fndr_info.fndr_creator, fh.fCreator, 4);
X		bcopy(&fndr_info.fndr_flags, fh.FndrFlags, 2);
X#ifdef BSD
X		ftime(&tbuf);
X		tp = localtime(&tbuf.time);
X		tdiff = TIMEDIFF - tbuf.timezone * 60;
X		if (tp->tm_isdst)
X			tdiff += 60 * 60;
X#else
X		/* I hope this is right! -andy */
X		time(&bs);
X		tp = localtime(&bs);
X		tdiff = TIMEDIFF - timezone;
X		if (tp->tm_isdst)
X			tdiff += 60 * 60;
X#endif
X		cp4(st.st_ctime + tdiff, fh.cDate);
X		cp4(st.st_mtime + tdiff, fh.mDate);
X	    }
X	    else
X	    {   strncpy(fh.fName, ih.name,64);
X		strncpy(fh.fType, ih.type, 4);
X		strncpy(fh.fCreator, ih.creator, 4);
X		strncpy(fh.FndrFlags, ih.flag, 2);
X		strncpy(fh.cDate, ih.ctime, 4);
X		strncpy(fh.mDate, ih.mtime, 4);
X	    }
X	}
X	else {	/* no info file so fake it */
X		strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
X		/* default to LSC text file */
X		strncpy(fh.fType, Type ? Type : "TEXT", 4);
X		strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
X		/* convert unix file time to mac time format */
X#ifdef BSD
X		ftime(&tbuf);
X		tp = localtime(&tbuf.time);
X		tdiff = TIMEDIFF - tbuf.timezone * 60;
X		if (tp->tm_isdst)
X			tdiff += 60 * 60;
X#else
X		/* I hope this is right! -andy */
X		time(&bs);
X		tp = localtime(&bs);
X		tdiff = TIMEDIFF - timezone;
X		if (tp->tm_isdst)
X			tdiff += 60 * 60;
X#endif
X		cp4(st.st_ctime + tdiff, fh.cDate);
X		cp4(st.st_mtime + tdiff, fh.mDate);
X	}
X	close(fd);
X	if (rmfiles) unlink(nbuf);	/* ignore errors */
X
X	crc = updcrc(0,&fh,(sizeof fh)-2);
X	cp2(crc, fh.hdrCRC);
X
X	fpos2 = lseek(ofd,0,1);		/* remember where we are */
X	lseek(ofd,fpos1,0);				/* seek back over file(s) and header */
X	write(ofd,&fh,sizeof fh);		/* write back header */
X	fpos2=lseek(ofd,fpos2,0);				/* seek forward file */
X
X	return (fpos2 - fpos1);
X}
X	
Xdofork(name)
Xchar name[];
X{
X	FILE *fs;
X	int n, fd, ufd;
X	char *p;
X
X	if ((fd=open(name,0))<0) {
X		perror(name);
X		return 0;
X	}   
X	if (unixf)		/* build conversion file */
X		if ((ufd=creat("sit+temp",0644))<0) {
X			perror("sit+temp");
X			return 0;
X		}   
X	/* do crc of file: */
X	crc = 0;
X	while ((n=read(fd,buf,BUFSIZ))>0) {
X		if (unixf) {	/* convert '\n' to '\r' */
X			for (p=buf; p<&buf[n]; p++)
X				if (*p == '\n') *p = '\r';
X			write(ufd,buf,n);
X		}
X		crc = updcrc(crc,buf,n);
X	}
X	close(fd);
X	/*
X	 * open pipe to compress file
X	 *   If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
X	 *   with the conversion done.	Otherwise, 'sit+temp' is just a link to 
X	 *   the input file.
X	 */
X	if (unixf)
X		close(ufd);
X	else link(name,"sit+temp");
X	fs = popen("compress -c -n -b 14 sit+temp","r");
X	if (fs == NULL) {
X		perror(name);
X		return 0;
X	}
X	/* write out compressed file */
X	clen = 0;
X	while ((n=fread(buf,1,BUFSIZ,fs))>0) {
X		write(ofd,buf,n);
X		clen += n;
X	}
X	pclose(fs);
X	unlink("sit+temp");
X}
X
Xcp2(x,dest)
Xunsigned short x;
Xchar dest[];
X{
X	dest[0] = x>>8;
X	dest[1] = x;
X}
X
Xcp4(x,dest)
Xunsigned long x;
Xchar dest[];
X{
X	dest[0] = x>>24;
X	dest[1] = x>>16;
X	dest[2] = x>>8;
X	dest[3] = x;
X}
END_OF_FILE
if test 12417 -ne `wc -c <'stuffit/sit.c'`; then
    echo shar: \"'stuffit/sit.c'\" unpacked with wrong size!
fi
# end of 'stuffit/sit.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--- end of part 3 ---

np@doc.imperial.ac.uk (Nigel Perry) (02/21/91)

[AufsTools - part 4 of 4]

---
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 4)."
# Contents:  unstuffit/unsit.c
# Wrapped by np@asun5 on Mon Dec  3 13:15:59 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'unstuffit/unsit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unstuffit/unsit.c'\"
else
echo shar: Extracting \"'unstuffit/unsit.c'\" \(31819 characters\)
sed "s/^X//" >'unstuffit/unsit.c' <<'END_OF_FILE'
X/* Modified Aug & Dec 90, Nigel Perry, Dept of Computing, Imperial College,
X   London SW7 2BZ, np@doc.ic.ac.uk
X
X   If called by AUFSNAME (default unstuffit) will input/output to
X   CAPS aufs disc.
X
X   Will now untiff multiple files.
X
X */
X/*
X	       unsit - Macintosh StuffIt file extractor
X
X		     Version 1.5f, for StuffIt 1.5
X
X			    July 23, 1990
X
XThis program will unpack a Macintosh StuffIt file into separate files.
XThe data fork of a StuffIt file contains both the data and resource
Xforks of the packed files.  The program will unpack each Mac file into
Xeither separate .data, .rsrc., and .info files that can be downloaded
Xto a Mac using macput and MacTerminal over a tty line, or into a
Xsingle MacBinary format file.  The MacBinary format is generally more
Xconvenient for those with network connections and FTP capability.  The
Xprogram is much like the "unpit" program for breaking apart Packit
Xarchive files.
X
X			***** IMPORTANT *****
XTo extract StuffIt files that have been compressed with the Lempel-Ziv
Xcompression method, unsit pipes the data through the "compress"
Xprogram with the appropriate switches, rather than incorporate the
Xuncompression routines within "unsit".  Therefore, it is necessary to
Xhave the "compress" program on the system and in the search path to
Xmake "unsit" work.  "Compress" is available from the comp.sources.unix
Xarchives.
X
XThe program syntax is much like unpit and macput/macget, with some added
Xoptions:
X
X	unsit [-rdulM] [-vqfm] stuffit-file.data
X
XOnly one of the flags r, d, u, l, or M should be specified.  The
Xdefault mode is to create the three macput/MacTerminal compatible
Xfile.  The -M flag will cause the output to be in MacBinary format (a
Xsingle file).  This can be swapped (default = MacBinary, -M = macput)
Xby changing the definitions of DEFAULT_MODE and OTHER_MODE below.  The
X-r and -d flags will cause only the resource and data forks to be
Xwritten.  The -u flag will cause only the data fork to be written and
Xto have carriage return characters changed to Unix newline characters.
XThe -l flag will make the program only list the files in the StuffIt
Xfile.
X
XThe -v flag causes the program to list the names, sizes, type, and
Xcreators of the files it is writing.  The -q flag causes it to list
Xthe name, type and size of each file and wait for a 'y' or 'n' for
Xeither writing that file or skipping it, respectively.  The -m flag is
Xused when the input file in in the MacBinary format instead of just
Xthe data fork.  It causes the program to skip the 128 byte MacBinary
Xheader before looking for the StuffIt header.  It is not necessary to
Xspecify the -m flag since the program now checks for MacBinary format
Xinput files and handles them correctly
X
XVersion 1.5 of the unsit supports extracting files and folders as
Ximplemented by StuffIt 1.5's "Hierarchy Maintained Folder" feature.
XEach folder is extracted as a subdirectory on the Unix system with the
Xfiles in the folder placed in the corresponding subdirectory.  The -f
Xoption can be used to "flatten" out the hierarchy and unsit will store
Xall the files in the current directory.  If the query option (-q) is
Xused and a "n" response is given to a folder name, none of the files
Xor folders in that folder will be extraced.
X
XSome of the program is borrowed from the macput.c/macget.c programs.
XMany, many thanks to Raymond Lau, the author of StuffIt, for including
Xinformation on the format of the StuffIt archives in the
Xdocumentation.  Several changes and enhancements supplied by David
XShanks (cde@atelabs.UUCP) have been incorporated into the program for
Xdoing things like supporting System V and recognizing MacBinary files.
XChristopher Bingham <kb@umnstat.stat.umn.edu> supplied some Macbinary
Xpatches.  Code was also borrowed from the macbin program by Jim Budler
Xfor convert macput format files to MacBinary.  I'm always glad to
Xreceive advice, suggestions, or comments about the program so feel free
Xto send whatever you think would be helpful
X
X
X	Author: Allan G. Weber
X		weber@sipi.usc.edu
X		...!usc!sipi!weber
X	Date:   July 23, 1990
X
X*/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
Xtypedef long OSType;
X
X#include "stuffit.h"
X
X/*
X * Define the following if your Unix can only handle 14 character file names
X * (e.g. Version 7 and System V).
X */
X/* #define SHORTNAMES */
X
X/*
X * The following defines the name of the compress program that is used for the
X * uncompression of Lempel-Ziv compressed files.  If the path is set up to
X * include the right directory, this should work.
X */
X#define COMPRESS   "compress"
X
X#define IOBUFSIZ   4096
X
X#define MACBINHDRSIZE  128L
X
X#define INIT_CRC 0L
Xextern unsigned short updcrc();
X
X#define INFOBYTES 128
X
X#define BYTEMASK 0xff
X
X#define S_SIGNATURE    0
X#define S_NUMFILES     4
X#define S_ARCLENGTH    6
X#define S_SIGNATURE2  10
X#define	S_VERSION     14
X#define SITHDRSIZE    22
X
X#define F_COMPRMETHOD    0
X#define F_COMPDMETHOD    1
X#define F_FNAME          2
X#define F_FTYPE         66
X#define F_CREATOR       70
X#define F_FNDRFLAGS     74
X#define F_CREATIONDATE  76
X#define F_MODDATE       80
X#define F_RSRCLENGTH    84
X#define F_DATALENGTH    88
X#define F_COMPRLENGTH   92
X#define F_COMPDLENGTH   96
X#define F_RSRCCRC      100
X#define F_DATACRC      102
X#define F_HDRCRC       110
X#define FILEHDRSIZE    112
X
X#define F_NAMELEN 63
X#ifdef SHORTNAMES		/* short file names */
X# define I_NAMELEN 15		/* 14 char file names + '\0' terminator */
X#else
X# define I_NAMELEN 69		/* 63 + strlen(".info") + 1 */
X#endif
X
X/* The following are copied out of macput.c/macget.c */
X#define I_NAMEOFF 1
X/* 65 <-> 80 is the FInfo structure */
X#define I_TYPEOFF 65
X#define I_AUTHOFF 69
X#define I_FLAGOFF 73
X#define I_LOCKOFF 81
X#define I_DLENOFF 83
X#define I_RLENOFF 87
X#define I_CTIMOFF 91
X#define I_MTIMOFF 95
X
X#define INITED_BUG
X#define INITED_OFF	I_FLAGOFF	/* offset to byte with Inited flag */
X#define INITED_MASK	(~1)		/* mask to '&' with byte to reset it */
X
X#define TEXT 0
X#define DATA 1
X#define RSRC 2
X#define MACPUT 3
X#define DUMP 4
X#define MACBINARY 5
X
X/* Swap the following definitions if you want the output to default to
X   MacBinary, and the -M switch to create macput file (.data, .rsrc, .info) */
X#define DEFAULT_MODE MACPUT
X#define OTHER_MODE   MACBINARY
X
X/* #define ADDBIN */	/* add .bin to macbinary file names */
X
X#define NODECODE 0
X#define DECODE   1
X
X#define H_ERROR -1
X#define H_EOF    0
X#define H_WRITE  1
X#define H_SKIP   2
X
X/* if called by this name program works on aufs files */
X#define AUFSNAME "unstuffit"
X
Xstruct node {
X	int flag, byte;
X	struct node *one, *zero;
X} nodelist[512], *nodeptr, *read_tree();	/* 512 should be big enough */
X
Xstruct sitHdr sithdr;
X
Xchar f_info[I_NAMELEN];
Xchar f_data[I_NAMELEN];
Xchar f_rsrc[I_NAMELEN];
X
Xchar info[INFOBYTES];
Xchar mname[F_NAMELEN+1];
Xchar uname[F_NAMELEN+1];
Xchar dname[F_NAMELEN+1];	/* directory name for aufs */
Xchar iobuf[IOBUFSIZ];
Xchar zbuf[128];			/* buffer of zeros to pad MacBinary forks */
X
Xint mode, txtmode, listonly, verbose, query, flatten;
Xint bit, chkcrc, numfiles, depth;
Xint aufs;			/* aufs flag */
Xint debug = 0;
XFILE *infp;
X
Xlong get4();
Xshort get2();
Xunsigned short write_file();
X
X/********************************************************************************/
X/* added for aufs, nicked from various places... */
X
X/* following from mcvert program */
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte;     /* one byte, obviously */
Xtypedef unsigned short word;    /* must be 2 bytes */
Xtypedef unsigned long ulong;    /* 4 bytes */
X
X#define NAMELEN 63              /* maximum legal Mac file name length */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks.  The first block is the
Xinfo_header (see below).  Then comes the data fork, null padded to fill the
Xlast block.  Then comes the resource fork, padded to fill the last block.  A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/ 
Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
X                        longs don't align to word boundaries */
X            byte version;           /* there is only a version 0 at this time */
X            byte nlen;              /* Length of filename. */
X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
X            byte type[4];           /* File type. */
X            byte auth[4];           /* File creator. */
X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
X            byte zero1;             /* Locked, Invisible,Bundle, System */
X                                    /* Bozo, Busy, Changed, Init */
X            byte icon_vert[2];      /* Vertical icon position within window */
X            byte icon_horiz[2];     /* Horizontal icon postion in window */
X            byte window_id[2];      /* Window or folder ID. */
X            byte protect;           /* = 1 for protected file, 0 otherwise */
X            byte zero2;
X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
X            byte rflen[4];          /* Resource Fork length         byte first */
X            byte cdate[4];          /* File's creation date. */
X            byte mdate[4];          /* File's "last modified" date. */
X            byte ilen[2];           /* GetInfo message length */
X	    byte flags2;            /* Finder flags, bits 0-7 */
X	    byte unused[14];       
X	    byte packlen[4];        /* length of total files when unpacked */
X	    byte headlen[2];        /* length of secondary header */
X	    byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
X	    byte readvers;          /* Minimum MacBinary II version needed to read this file */
X            byte crc[2];            /* CRC of the previous 124 bytes */
X	    byte padding[2];        /* two trailing unused bytes */
X            } info_header;
X
X/* end of mcvert stuff */
X/* from CAP aufs documentation */
X
X#define FINFOLEN 32
X#define MAXCLEN 199
Xtypedef struct
X{  /* byte fi_fndr[FINFOLEN]; */	/* finder info */
X   /* what I think the above is... */
X   ulong fndr_type, fndr_creator;
X   word fndr_flags;
X   ulong fndr_loc;
X   word fndr_fldr;
X   word fndr_icon;
X   byte fndr_unused[8];
X   word fndr_comment;
X   ulong fndr_putaway;
X   /* end of fi_fndr */
X
X   word fi_attr;			/* attributes */
X#define FI_MAGIC1 255
X   byte fi_magic1;		/* was: length of comment */
X#define FI_VERSION 0x10		/* version major 1, minor 0 */
X				/* if more than 8 versions then */
X				/* something wrong anyway */
X   byte fi_version;		/* version number */
X#define FI_MAGIC 0xda
X   byte fi_magic;		/* magic word check */
X   byte fi_bitmap;		/* bitmap of included info */
X#define FI_BM_SHORTFILENAME 0x1	/* is this included? */
X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
X   byte fi_shortfilename[12+1];	/* possible short file name */
X   byte fi_macfilename[32+1];	/* possible macintosh file name */
X   byte fi_comln;		/* comment length */
X   byte fi_comnt[MAXCLEN+1];	/* comment string */
X} FileInfo;
X
XFileInfo fndr_info;
X
X/* end aufs */
X/********************************************************************************/
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    int status;
X    int c;
X    extern int optind;
X    extern char *optarg;
X    int errflg;
X    int macbin;
X
X    mode = DEFAULT_MODE;
X    errflg = 0;
X    macbin = 0;
X    flatten = 0;
X    numfiles = 0;
X    depth = 0;
X    aufs = strcmp(argv[0], AUFSNAME) == 0;
X
X    while ((c = getopt(argc, argv, "DMdflmqruvx")) != EOF)
X	switch (c) {
X	  case 'r':		/* extract resource fork only */
X	    mode = RSRC;
X	    break;
X	  case 'd':		/* extract data fork only */
X	    mode = DATA;
X	    break;
X	  case 'u':		/* extract data fork as Unix text file */
X	    mode = TEXT;
X	    break;
X	  case 'l':		/* list contents of archive */
X	    listonly++;
X	    break;
X	  case 'q':		/* query user on each extraction */
X	    query++;
X	    break;
X	  case 'v':		/* verbose mode */
X	    verbose++;
X	    break;
X	  case 'x':		/* don't decode data, just dump to files*/
X	    mode = DUMP;
X	    break;
X	  case 'm':		/* input file is in Macbinary format */
X	    macbin = 1;
X	    break;
X	  case 'M':		/* output file in OTHER_MODE */
X	    mode = OTHER_MODE;
X	    break;
X	  case 'f':		/* don't create flat directory tree */
X	    flatten = 1;
X	    break;
X	  case 'D':		/* debugging mode */
X	    debug = 1;
X	    break;
X	  case '?':
X	    errflg++;
X	    break;
X	}
X    if (errflg) {
X	usage();
X	exit(1);
X    }
X
X    /* -a incompatible with -M and -u */
X    if(aufs && (mode == MACBINARY || mode == TEXT))
X    {   fprintf(stderr, "Aufs mode cannot be combined with MacBinary (-M) or text (-t) mode\n");
X	exit(1);
X    }
X
X    if (optind == argc) {
X	usage();
X	exit(1);
X    }
X    else
X	while(optind < argc)
X        {   if ((infp = fopen(argv[optind], "r")) == NULL)
X	    {   fprintf(stderr,"Can't open input file \"%s\"\n",argv[optind]);
X	        exit(1);
X	    }
X
X	    if (macbin) {
X		if (fseek(infp, MACBINHDRSIZE, 0) == -1) {
X		    fprintf(stderr, "Can't skip over MacBinary header\n");
X		    exit(1);
X		}
X	    }
X
X	    if (readsithdr(&sithdr) == 0) {
X		fprintf(stderr, "Can't read file header\n");
X		exit(1);
X	    }
X	    if (debug) {
X		printf("archive header (%d bytes):\n", SITHDRSIZE);
X		printf("numFiles=%d, arcLength=%ld, version=%d\n",
X		       sithdr.numFiles, sithdr.arcLength, sithdr.version & 0xff);
X	    }
X	    status = extract("", 0);
X	    if(status < 0) exit(1);
X
X	    optind++;
X	}
X
X	exit(0);
X}
X
Xusage()
X{
X    fprintf(stderr, "Usage: unsit/unstuffit [-rdulM] [-vqfm] filename\n");
X}
X
X/*
X  extract(parent, skip) - Extract all files from the current folder.
X  char *parent;           name of parent folder
X  int  skip;              1 to skip all files and folders in this one
X                          0 to extract them
X
X  returns 1 if came an endFolder record
X          0 if EOF
X	 -1 if error (bad fileHdr, bad file, etc.)
X*/
X
Xextract(parent, skip)
Xchar *parent;
Xint skip;
X{
X    struct fileHdr filehdr;
X    struct stat sbuf;
X    int status, rstat, sstat, skipit;
X    char name[256];
X
X    while (1) {
X	rstat = readfilehdr(&filehdr, skip);
X	if (rstat == H_ERROR || rstat == H_EOF) {
X	    status = rstat;
X	    break;
X	}
X	if (debug) {
X	    printf("file header (%d bytes):\n", FILEHDRSIZE);
X	    printf("compRMethod=%d, compDMethod=%d\n",
X		   filehdr.compRMethod, filehdr.compDMethod);
X	    printf("rsrcLength=%ld, dataLength=%ld\n",
X		   filehdr.rsrcLength, filehdr.dataLength);
X	    printf("compRLength=%ld, compDLength=%ld\n",
X		   filehdr.compRLength, filehdr.compDLength);
X	    printf("rsrcCRC=%d=0x%04x, dataCRC=%d=0x%04x\n",
X		   filehdr.rsrcCRC, filehdr.rsrcCRC,
X		   filehdr.dataCRC, filehdr.dataCRC);
X	}
X
X	skipit = (rstat == H_SKIP) ? 1 : 0;
X
X	if (filehdr.compRMethod == endFolder && 
X	    filehdr.compDMethod == endFolder) {
X	    status = 1;		/* finished with this folder */
X	    break;
X	}
X	else if (filehdr.compRMethod == startFolder && 
X		 filehdr.compDMethod == startFolder) {
X	    if (!listonly && rstat == H_WRITE && !flatten) {
X		sstat = stat(uname, &sbuf);
X		if (sstat == -1) {	/* directory doesn't exist */
X		    if (mkdir(uname, 0777) == -1) {
X			fprintf(stderr,
X				"Can't create subdirectory %s\n", uname);
X			return(-1);
X		    }
X		}
X		else {		/* something exists with this name */
X		    if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
X			fprintf(stderr, "Directory name %s already in use\n",
X				uname);
X			return(-1);
X		    }
X		}
X		if(aufs) /* create .finderinfo & .resource subdirectories */
X		{   strcpy(dname, uname);
X		    strcat(dname, "/.finderinfo");
X		    sstat = stat(dname, &sbuf);
X		    if (sstat == -1) {	/* directory doesn't exist */
X			if (mkdir(dname, 0777) == -1) {
X			    fprintf(stderr,
X				    "Can't create subdirectory %s\n", dname);
X			    return(-1);
X			}
X		    }
X		    else {		/* something exists with this name */
X			if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
X			    fprintf(stderr, "Directory name %s already in use\n",
X				    dname);
X			    return(-1);
X			}
X		    }
X		    strcpy(dname, uname);
X		    strcat(dname, "/.resource");
X		    sstat = stat(dname, &sbuf);
X		    if (sstat == -1) {	/* directory doesn't exist */
X			if (mkdir(dname, 0777) == -1) {
X			    fprintf(stderr,
X				    "Can't create subdirectory %s\n", dname);
X			    return(-1);
X			}
X		    }
X		    else {		/* something exists with this name */
X			if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
X			    fprintf(stderr, "Directory name %s already in use\n",
X				    dname);
X			    return(-1);
X			}
X		    }
X		}
X		if (chdir(uname) == -1) {
X		    fprintf(stderr, "Can't chdir to %s\n", uname);
X		    return(-1);
X		}
X		sprintf(name,"%s:%s", parent, uname);
X	    }
X	    depth++;
X	    status = extract(name, skipit);
X	    depth--;
X	    if (status != 1)
X		break;		/* problem with folder */
X	    if (depth == 0)	/* count how many top-level files done */
X		numfiles++;
X	    if (!flatten)
X		chdir("..");
X	}
X	else {
X	    if ((status = extractfile(&filehdr, skipit)) != 1)
X		break;
X	    if (depth == 0)	/* count how many top-level files done */
X		numfiles++;
X	}
X	if (numfiles == sithdr.numFiles)
X	    break;
X    }
X    return(status);
X}
X
Xextractfile(fh, skip)
Xstruct fileHdr *fh;
Xint skip;
X{
X    unsigned short crc;
X    FILE *fp, *fp1;
X    int n;
X
X    f_data[0] = f_rsrc[0] = f_info[0] = '\0'; /* assume no output files */
X    /* figure out what file names to use and what to do */
X    if (!listonly && !skip) {
X	switch (mode) {
X	  case MACPUT:		/* do both rsrc and data forks */
X	    if(aufs)
X	    {   sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
X		sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
X		sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
X	    }
X	    else
X	    {   sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
X		sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
X		sprintf(f_info, "%.*s.info", I_NAMELEN - 6, uname);
X	    }
X	    break;
X	  case RSRC:		/* rsrc fork only */
X	    if(aufs)
X	    {   sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
X		sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
X	    }
X	    else
X		sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
X	    break;
X	  case DATA:		/* data fork only */
X	    if(aufs)
X	    {   sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
X		sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
X	    }
X	    else
X	        sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
X	    break;
X	  case TEXT:
X	    sprintf(f_data, "%.*s.text", I_NAMELEN - 6, uname);
X	    break;
X	  case DUMP:		/* for debugging, dump data as is */
X	    sprintf(f_data, "%.*s.ddump", I_NAMELEN - 7, uname);
X	    sprintf(f_rsrc, "%.*s.rdump", I_NAMELEN - 7, uname);
X	    fh->compRMethod = fh->compDMethod = noComp;
X	    break;
X	  case MACBINARY:	/* output file in MacBinary format */
X	    sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
X	    sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
X#ifndef ADDBIN
X	    sprintf(f_info, "%.*s", I_NAMELEN - 1, uname);
X#else
X	    sprintf(f_info, "%.*s.bin", I_NAMELEN - 5, uname);
X#endif /*ADDBIN*/
X	    break;
X	}
X    }
X
X    fp = NULL;			/* so we can tell if a file is open */
X    if (f_info[0] != '\0' && check_access(f_info) != -1) {
X	fp = fopen(f_info, "w");
X	if (fp == NULL) {
X	    perror(f_info);
X	    exit(1);
X	}
X	if(aufs) /* convert info structure */
X	{   register info_header *pinfo;
X	
X	    pinfo = (info_header *)info;
X
X	    /* make the .finderinfo file */
X	    bzero(&fndr_info, sizeof(FileInfo));
X	    bcopy(pinfo->type, &fndr_info.fndr_type, 4);
X	    bcopy(pinfo->auth, &fndr_info.fndr_creator, 4);
X	    bcopy(&pinfo->flags, &fndr_info.fndr_flags, 2);
X	    fndr_info.fi_magic1 = FI_MAGIC1;
X	    fndr_info.fi_version = FI_VERSION;
X	    fndr_info.fi_magic = FI_MAGIC;
X	    fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
X	    bcopy(pinfo->name, fndr_info.fi_macfilename, pinfo->nlen);
X
X	    fwrite(&fndr_info, sizeof(FileInfo), 1, fp);
X	}
X	else
X	{   if (mode == MACBINARY) { /* convert to MacBinary header */
X		/* taken from the macbin program */
X		if (info[74] & 0x40) info[81] = '\1'; /* protected */
X		info[74] = '\0'; /* clear zero2 */
X		info[82] = '\0'; /* force zero3 clear */
X	    }
X	    fwrite(info, 1, INFOBYTES, fp);
X	}
X    }
X
X    if (f_rsrc[0] != '\0') {
X	txtmode = 0;
X	crc = write_file(f_rsrc, fh->compRLength,
X			 fh->rsrcLength, fh->compRMethod);
X	if (chkcrc && fh->rsrcCRC != crc) {
X	    fprintf(stderr,
X		    "CRC error on resource fork: need 0x%04x, got 0x%04x\n",
X		    fh->rsrcCRC, crc);
X	    return(-1);
X	}
X    }
X    else {
X	fseek(infp, (long) fh->compRLength, 1);
X    }
X    if (f_data[0] != '\0') {
X	txtmode = (mode == TEXT);
X	crc = write_file(f_data, fh->compDLength,
X			 fh->dataLength, fh->compDMethod);
X	if (chkcrc && fh->dataCRC != crc) {
X	    fprintf(stderr,
X		    "CRC error on data fork: need 0x%04x, got 0x%04x\n",
X		    fh->dataCRC, crc);
X	    return(-1);
X	}
X    }
X    else {
X	fseek(infp, (long) fh->compDLength, 1);
X    }
X    if (fp != NULL) {
X	/* if Macbinary output, copy the data and resource forks to the
X	   end of the info file, and pad each to multiples of 128 bytes. */
X	if (mode == MACBINARY) {
X	    fp1 = fopen(f_data, "r"); /* re-open the file we just wrote */
X	    if (fp1 == NULL) {
X		perror(f_data);
X		exit(1);
X	    }
X	    while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
X		fwrite(iobuf, 1, n, fp); /* append it to the info file */
X	    /* pad out to multiple of 128 if in MacBinary format */
X	    n = fh->dataLength % 128;
X	    if (n > 0)
X		outc(zbuf, 128 - n, fp);
X	    fclose(fp1);
X	    unlink(f_data);
X	    fp1 = fopen(f_rsrc, "r"); /* re-open the file we just wrote */
X	    if (fp1 == NULL) {
X		perror(f_rsrc);
X		exit(1);
X	    }
X	    while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
X		fwrite(iobuf, 1, n, fp); /* append it to the info file */
X	    /* pad out to multiple of 128 if in MacBinary format */
X	    n = fh->rsrcLength % 128;
X	    if (n > 0)
X		outc(zbuf, 128 - n, fp);
X	    fclose(fp1);
X	    unlink(f_rsrc);
X	}
X	fclose(fp);
X    }
X    return(1);
X}
X
Xreadsithdr(s)
Xstruct sitHdr *s;
X{
X    char temp[FILEHDRSIZE];
X    int count = 0;
X
X    for (;;) {
X	if (fread(temp, 1, SITHDRSIZE, infp) != SITHDRSIZE) {
X	    fprintf(stderr, "Can't read file header\n");
X	    return(0);
X	}
X    	
X	if (strncmp(temp + S_SIGNATURE,  "SIT!", 4) == 0 &&
X	    strncmp(temp + S_SIGNATURE2, "rLau", 4) == 0) {
X	    s->numFiles = get2(temp + S_NUMFILES);
X	    s->arcLength = get4(temp + S_ARCLENGTH);
X	    return(1);
X	}
X    
X	if (++count == 2) {
X	    fprintf(stderr, "Not a StuffIt file\n");
X	    return(0);
X	}
X	
X	if (fread(&temp[SITHDRSIZE], 1, FILEHDRSIZE - SITHDRSIZE, infp) !=
X	    FILEHDRSIZE - SITHDRSIZE) {
X	    fprintf(stderr, "Can't read file header\n");
X	    return(0);
X	}
X    
X	if (strncmp(temp + I_TYPEOFF, "SIT!", 4) == 0 &&
X	    strncmp(temp + I_AUTHOFF, "SIT!", 4) == 0) {	/* MacBinary format */
X	    fseek(infp, (long)(INFOBYTES-FILEHDRSIZE), 1);	/* Skip over header */
X	}
X    }
X}
X
X/*
X  readfilehdr - reads the file header for each file and the folder start
X  and end records.
X
X  returns: H_ERROR = error
X	   H_EOF   = EOF
X	   H_WRITE = write file/folder
X	   H_SKIP  = skip file/folder
X*/
X
Xreadfilehdr(f, skip)
Xstruct fileHdr *f;
Xint skip;
X{
X    unsigned short crc;
X    int i, n, write_it, isfolder;
X    char hdr[FILEHDRSIZE];
X    char ch, *mp, *up;
X    char *tp, temp[10];
X
X    for (i = 0; i < INFOBYTES; i++)
X	info[i] = '\0';
X
X    /* read in the next file header, which could be folder start/end record */
X    n = fread(hdr, 1, FILEHDRSIZE, infp);
X    if (n == 0)			/* return 0 on EOF */
X	return(H_EOF);
X    else if (n != FILEHDRSIZE) {
X	fprintf(stderr, "Can't read file header\n");
X	return(H_ERROR);
X    }
X
X    /* check the CRC for the file header */
X    crc = INIT_CRC;
X    crc = updcrc(crc, hdr, FILEHDRSIZE - 2);
X    f->hdrCRC = get2(hdr + F_HDRCRC);
X    if (f->hdrCRC != crc) {
X	fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
X		f->hdrCRC, crc);
X	return(H_ERROR);
X    }
X
X    /* grab the name of the file or folder */
X    n = hdr[F_FNAME] & BYTEMASK;
X    if (n > F_NAMELEN)
X	n = F_NAMELEN;
X    info[I_NAMEOFF] = n;
X    copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n);
X    strncpy(mname, hdr + F_FNAME + 1, n);
X    mname[n] = '\0';
X    /* copy to a string with no illegal Unix characters in the file name */
X    mp = mname;
X    up = uname;
X    while ((ch = *mp++) != '\0') {
X	if (ch <= ' ' || ch > '~' || index("/!()[]*<>?\\\"$\';&`", ch) != NULL)
X	    ch = '_';
X	*up++ = ch;
X    }
X    *up = '\0';
X
X    /* get lots of other stuff from the header */
X    f->compRMethod = hdr[F_COMPRMETHOD];
X    f->compDMethod = hdr[F_COMPDMETHOD];
X    f->rsrcLength = get4(hdr + F_RSRCLENGTH);
X    f->dataLength = get4(hdr + F_DATALENGTH);
X    f->compRLength = get4(hdr + F_COMPRLENGTH);
X    f->compDLength = get4(hdr + F_COMPDLENGTH);
X    f->rsrcCRC = get2(hdr + F_RSRCCRC);
X    f->dataCRC = get2(hdr + F_DATACRC);
X
X    /* if it's an end folder record, don't need to do any more */
X    if (f->compRMethod == endFolder && f->compDMethod == endFolder)
X	return(H_WRITE);
X
X    /* prepare an info file in case its needed */
X
X    copy(info + I_TYPEOFF, hdr + F_FTYPE, 4);
X    copy(info + I_AUTHOFF, hdr + F_CREATOR, 4);
X    copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2);
X#ifdef INITED_BUG
X    info[INITED_OFF] &= INITED_MASK; /* reset init bit */
X#endif
X    copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4);
X    copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4);
X    copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4);
X    copy(info + I_MTIMOFF, hdr + F_MODDATE, 4);
X
X    isfolder = f->compRMethod == startFolder && f->compDMethod == startFolder;
X	
X    /* list the file name if verbose or listonly mode, also if query mode */
X    if (skip)			/* skip = 1 if skipping all in this folder */
X	write_it = 0;
X    else {
X	write_it = 1;
X	if (listonly || verbose || query) {
X	    for (i = 0; i < depth; i++)
X		putchar(' ');
X	    if (isfolder)
X		printf("Folder: \"%s\"", uname);
X	    else
X		printf("name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
X		       uname, hdr + F_FTYPE, hdr + F_CREATOR,
X		       f->dataLength, f->rsrcLength);
X	    if (query) {	/* if querying, check with the boss */
X		printf(" ? ");
X		fgets(temp, sizeof(temp) - 1, stdin);
X		tp = temp;
X		write_it = 0;
X		while (*tp != '\0') {
X		    if (*tp == 'y' || *tp == 'Y') {
X			write_it = 1;
X			break;
X		    }
X		    else
X			tp++;
X		}
X	    }
X	    else		/* otherwise, terminate the line */
X		putchar('\n');
X	}
X    }
X    return(write_it ? H_WRITE : H_SKIP);
X}
X
Xcheck_access(fname)	/* return 0 if OK to write on file fname, -1 otherwise */
Xchar *fname;
X{
X    char temp[10], *tp;
X
X    if (access(fname, 0) == -1) {
X	return(0);
X    }
X    else {
X	printf("%s exists.  Overwrite? ", fname);
X	fgets(temp, sizeof(temp) - 1, stdin);
X	tp = temp;
X	while (*tp != '\0') {
X	    if (*tp == 'y' || *tp == 'Y') {
X		return(0);
X	    }
X	    else
X		tp++;
X	}
X    }
X    return(-1);
X}
X
Xunsigned short write_file(fname, ibytes, obytes, type)
Xchar *fname;
Xunsigned long ibytes, obytes;
Xunsigned char type;
X{
X    unsigned short crc;
X    int i, n, ch, lastch;
X    FILE *outf;
X    char temp[256];
X
X    crc = INIT_CRC;
X    chkcrc = 1;			/* usually can check the CRC */
X
X    if (check_access(fname) == -1) {
X	fseek(infp, ibytes, 1);
X	chkcrc = 0;		/* inhibit crc check if file not written */
X    	return(-1);
X    }
X	
X    switch (type) {
X      case noComp:		/* no compression */
X	outf = fopen(fname, "w");
X	if (outf == NULL) {
X	    perror(fname);
X	    exit(1);
X	}
X	while (ibytes > 0) {
X	    n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
X	    n = fread(iobuf, 1, n, infp);
X	    if (n == 0)
X		break;
X	    crc = updcrc(crc, iobuf, n);
X	    outc(iobuf, n, outf);
X	    ibytes -= n;
X	}
X	fclose(outf);
X	break;
X      case rleComp:		/* run length encoding */
X	outf = fopen(fname, "w");
X	if (outf == NULL) {
X	    perror(fname);
X	    exit(1);
X	}
X	while (ibytes > 0) {
X	    ch = getc(infp) & 0xff;
X	    ibytes--;
X	    if (ch == 0x90) {	/* see if its the repeat marker */
X		n = getc(infp) & 0xff; /* get the repeat count */
X		ibytes--;
X		if (n == 0) { /* 0x90 was really an 0x90 */
X		    iobuf[0] = 0x90;
X		    crc = updcrc(crc, iobuf, 1);
X		    outc(iobuf, 1, outf);
X		}
X		else {
X		    n--;
X		    for (i = 0; i < n; i++)
X			iobuf[i] = lastch;
X		    crc = updcrc(crc, iobuf, n);
X		    outc(iobuf, n, outf);
X		}
X	    }
X	    else {
X		iobuf[0] = ch;
X		crc = updcrc(crc, iobuf, 1);
X		lastch = ch;
X		outc(iobuf, 1, outf);
X	    }
X	}
X	fclose(outf);
X	break;
X      case lzwComp:		/* LZW compression */
X	sprintf(temp, "%s%s", COMPRESS, " -d -c -n -b 14 ");
X	if (txtmode) {
X	    strcat(temp, "| tr \'\\015\' \'\\012\' ");
X	    chkcrc = 0;		/* can't check CRC in this case */
X	}
X	strcat(temp, "> '");
X	strcat(temp, fname);
X	strcat(temp, "'");
X	outf = popen(temp, "w");
X	if (outf == NULL) {
X	    perror(fname);
X	    exit(1);
X	}
X	while (ibytes > 0) {
X	    n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
X	    n = fread(iobuf, 1, n, infp);
X	    if (n == 0)
X		break;
X	    fwrite(iobuf, 1, n, outf);
X	    ibytes -= n;
X	}
X	pclose(outf);
X	if (chkcrc) {
X	    outf = fopen(fname, "r"); /* read the file to get CRC value */
X	    if (outf == NULL) {
X		perror(fname);
X		exit(1);
X	    }
X	    while (1) {
X		n = fread(iobuf, 1, IOBUFSIZ, outf);
X		if (n == 0)
X		    break;
X		crc = updcrc(crc, iobuf, n);
X	    }
X	    fclose(outf);
X	}
X	break;
X      case hufComp:		/* Huffman compression */
X	outf = fopen(fname, "w");
X	if (outf == NULL) {
X	    perror(fname);
X	    exit(1);
X	}
X	nodeptr = nodelist;
X	bit = 0;		/* put us on a byte boundary */
X	read_tree();
X	while (obytes > 0) {
X	    n = (obytes > IOBUFSIZ) ? IOBUFSIZ : obytes;
X	    for (i = 0; i < n; i++)
X		iobuf[i] = gethuffbyte(DECODE);
X	    crc = updcrc(crc, iobuf, n);
X	    outc(iobuf, n, outf);
X	    obytes -= n;
X	}
X	fclose(outf);
X	break;
X      default:
X	fprintf(stderr, "Unknown compression method\n");
X	chkcrc = 0;		/* inhibit crc check if file not written */
X	return(-1);
X    }
X
X    return(crc & 0xffff);
X}
X
Xoutc(p, n, fp)
Xchar *p;
Xint n;
XFILE *fp;
X{
X    register char *p1;
X    register int i;
X    if (txtmode) {
X	for (i = 0, p1 = p; i < n; i++, p1++)
X	    if ((*p1 & BYTEMASK) == '\r')
X		*p1 = '\n';
X    }
X    fwrite(p, 1, n, fp);
X}
X
Xlong get4(bp)
Xchar *bp;
X{
X    register int i;
X    long value = 0;
X
X    for (i = 0; i < 4; i++) {
X	value <<= 8;
X	value |= (*bp & BYTEMASK);
X	bp++;
X    }
X    return(value);
X}
X
Xshort get2(bp)
Xchar *bp;
X{
X    register int i;
X    int value = 0;
X
X    for (i = 0; i < 2; i++) {
X	value <<= 8;
X	value |= (*bp & BYTEMASK);
X	bp++;
X    }
X    return(value);
X}
X
Xcopy(p1, p2, n)
Xchar *p1, *p2;
Xint n;
X{
X	while (n-- > 0)
X		*p1++ = *p2++;
X}
X
X/* This routine recursively reads the Huffman encoding table and builds
X   and decoding tree. */
X
Xstruct node *read_tree()
X{
X	struct node *np;
X	np = nodeptr++;
X	if (getbit() == 1) {
X		np->flag = 1;
X		np->byte = gethuffbyte(NODECODE);
X	}
X	else {
X		np->flag = 0;
X		np->zero = read_tree();
X		np->one  = read_tree();
X	}
X	return(np);
X}
X
X/* This routine returns the next bit in the input stream (MSB first) */
X
Xgetbit()
X{
X	static char b;
X	if (bit == 0) {
X		b = getc(infp) & 0xff;
X		bit = 8;
X	}
X	bit--;
X	return((b >> bit) & 1);
X}
X
X/* This routine returns the next 8 bits.  If decoding is on, it finds the
Xbyte in the decoding tree based on the bits from the input stream.  If
Xdecoding is not on, it either gets it directly from the input stream or
Xputs it together from 8 calls to getbit(), depending on whether or not we
Xare currently on a byte boundary
X*/
Xgethuffbyte(decode)
Xint decode;
X{
X	register struct node *np;
X	register int i, b;
X	if (decode == DECODE) {
X		np = nodelist;
X		while (np->flag == 0)
X			np = (getbit()) ? np->one : np->zero;
X		b = np->byte;
X	}
X	else {
X		if (bit == 0)	/* on byte boundary? */
X			b = getc(infp) & 0xff;
X		else {		/* no, put a byte together */
X			b = 0;
X			for (i = 8; i > 0; i--) {
X				b = (b << 1) + getbit();
X			}
X		}
X	}
X	return(b);
X}
END_OF_FILE
if test 31819 -ne `wc -c <'unstuffit/unsit.c'`; then
    echo shar: \"'unstuffit/unsit.c'\" unpacked with wrong size!
fi
# end of 'unstuffit/unsit.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--- end of part 4 ---