[comp.sources.apple2] v001SRC036: Nulib - Archive Library Tools

jac@yoko.rutgers.edu (Jonathan A. Chandross) (05/02/91)

Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
Posting-number: Volume 1, Source:36
Archive-name: archive/unix/nulib/part05.10
Architecture: UNIX
Version-number: 3.03


=nuetc.c
-/*
- * nuetc.c - extra stuff; most is #ifdefed to death (mostly time routines
- *           and file stuff that are highly system dependent)
- *
- * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "NuMain"
-#endif
-
-#include "nudefs.h"
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>	  /* errno declarations */
-#include <ctype.h>	  /* for tolower(), isupper() */
-
-#ifdef UNIX
-# include <time.h>	  /* need localtime() */
-# include <sys/types.h>   /* defn of time_t */
-# include <sys/stat.h>
-#endif
-#ifdef APW
-# include <stdlib.h>	   /* exit(), etc. */
-# include <types.h>	   /* has _toolErr in it */
-# include <prodos.h>
-# include "apwerr.h"	   /* APW/ProDOS error codes */
-#endif
-#ifdef MSDOS
-# include <process.h>
-# include <stdlib.h>
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <time.h>
-#endif
-
-#include "nuetc.h"
-/* note "nuread.h" is not included... none of the routines here assume */
-/* any knowledge of NuFX archives.                                     */
-
-#ifndef MSDOS
-extern char *malloc(); /* all systems ... except DOS : RBH */
-#endif  /* +PORT+ */
-
-extern void free();
-extern char *getenv();
-#ifdef APW
-extern Time ReadTimeHex();  /* should be TimeRec, from misctool.h */
-#endif
-
-/* This is a generally available TEMPORARY filename buffer */
-char tmpNameBuf[MAXFILENAME];
-
-
-/******************** general misc routines ********************/
-
-/*
- * Fatal error handler
- */
-void Fatal(deathstr, procName)
-char *deathstr, *procName;
-{
-    fflush(stdout);
-    fprintf(stderr, "\n%s: fatal error: %s\n--- ", prgName, deathstr);
-    perror(procName);
-    Quit (-1);
-}
-
-
-/*
- * Quit can be used to perform cleanup operations before exiting.
- */
-void Quit(val)
-int val;
-{
-    exit(val);
-}
-
-
-/*
- * Safe malloc()... checks return value
- */
-char *Malloc(size)
-int size;
-{
-    char *ptr = (char *) malloc(size);
-
-    if (ptr != (char *) NULL) {
-	return(ptr);
-    } else {
-       /* 8910.31 - RBH: report byte size that failed */
-       printf("Malloc: memory alloc error [%u : bytes]\n", size);
-#ifdef MSDOS
-       printf("(Largest Available Block: %u)\n", _memmax());
-#endif
-	Quit (-1);
-    }
-}
-
-/******************** UNIX compatibility routines ********************/
-
-#ifdef UNIX
-/*
- * Convert expanded date to a number of seconds for UNIX systems.
- *
- * Remember that *atime follows the NuFX docs for time values, which
- * don't necessarily match those in UNIX manual pages.
- * Adapted from _Advanced UNIX Programming_ by Marc J. Rochkind.
- *
- * Returns 0 if date/time is invalid.
- */
-long timecvt(atime)
-Time *atime;
-{
-    long tm;
-    int days;
-    BOOLEAN isleapyear;
-    int tzone;
-    char *getenv(), *tz;
-
-    if ((tz = getenv("TZ")) == NULL)
-	tzone = 8;  /* pacific std time */
-    else
-	tzone = atoi(&tz[3]);
-
-    isleapyear = (atime->year != 0) && (atime->year%4 == 0);  /* 2000 isn't */
-    if (atime->year < 70)
-	atime->year += 100;  /* years after 2000 */
-    days = (atime->year - 70) * 365L;
-    days += ((atime->year - 69L) / 4);  /* previous years' leap days */
-
-    switch (atime->month +1) {  /* month is 0-11 */
-    case 12:
-	days += 30;  /* Nov */
-    case 11:
-	days += 31;  /* Oct */
-    case 10:
-	days += 30;  /* Sep */
-    case 9:
-	days += 31;  /* Aug */
-    case 8:
-	days += 31;  /* Jul */
-    case 7:
-	days += 30;  /* Jun */
-    case 6:
-	days += 31;  /* May */
-    case 5:
-	days += 30;  /* Apr */
-    case 4:
-	days += 31;  /* Mar */
-    case 3:
-	days += (isleapyear ? 29 : 28);  /* Feb */
-    case 2:
-	days += 31;  /* Jan */
-    case 1:
-	break;
-    default:
-	/*printf("Invalid month\n");*/
-	return (0L);
-    }
-
-    if (atime->day > 31) {
-	/*printf("Invalid day\n");*/
-	return (0L);
-    }
-    tm = (days + atime->day) * 24L * 60L * 60L;
-
-    if (atime->hour > 23) {
-	/*printf("Invalid hour\n");*/
-	return (0L);
-    }
-    atime->hour += tzone;  /* correct for time zone */
-    tm += atime->hour * 60L * 60L;
-
-    if (atime->minute > 59) {
-	/*printf("Invalid minute\n");*/
-	return (0L);
-    }
-    tm += atime->minute * 60L;
-
-    if (atime->second > 59) {
-	/*printf("Invalid second\n");*/
-	return (0L);
-    }
-    tm += atime->second;
-
-    if (localtime(&tm)->tm_isdst)  /* was that day in dst? */
-	tm -= 60L * 60L;  /* adjust for daylight savings */
-    return (tm);
-}
-#endif /* UNIX */
-
-/******************** APW compatibility routines ********************/
-
-#ifdef APW
-/*
- * Normally a C library function to print out a description of the most
- * recent system (non-toolbox, non-ProDOS) error.  Exists under UNIX and
- * MS C 5.1, so I'm assuming it exists most everywhere else...
- */
-void perror(errstr)
-char *errstr;
-{
-    fflush(stdout);
-    if ( (errno > 0) && (errno < sys_nerr) ) {	/* known APW error? */
-	fprintf(stderr, "%s: %s\n", errstr, sys_errlist[errno]);
-    } else {
-	fprintf(stderr, "%s: ", errstr);
-	fflush(stderr);
-	ERROR( errno );
-    }
-    Quit (-1);
-}
-
-
-/* Check for //gs toolbox errors; all are fatal */
-void ToolErrChk()
-{
-    int err = _toolErr;
-
-    if (err) {
-	if (err < MPErr) {  /* was a ProDOS error? */
-	    fprintf(stderr, "Error: $%.2x %s\n", (char) err,
-		ProDOSErr[err]);
-	} else {
-	    fprintf(stderr, "Tool err ($%.4x): ", err);
-	    fflush(stderr);
-	    ERROR( err );
-	}
-	Quit (-1);
-    }
-}
-
-#endif /* APW */
-
-/******************** miscellaneous string routines ********************/
-
-/*
- * Compare strings, ignoring case (may be in standard C lib; stricmp()?)
- */
-int strcasecmp(str1, str2)
-register char *str1, *str2;
-{
-    register char one, two;
-    register int val;
-
-    for ( ; *str1 && *str2; str1++, str2++) {
-	one = (isupper(*str1) ? tolower(*str1) : *str1);
-	two = (isupper(*str2) ? tolower(*str2) : *str2);
-	if (val = two - one)
-	    return (val);
-    }
-    if (!(*str1) && !(*str2))  /* both zero -> equivalent */
-	return (0);
-    else {  /* one is shorter; return result */
-	one = (isupper(*str1) ? tolower(*str1) : *str1);
-	two = (isupper(*str2) ? tolower(*str2) : *str2);
-	return (two - one);
-    }
-}
-
-int strncasecmp(str1, str2, num)
-register char *str1, *str2;
-int num;
-{
-    register int i;
-    register char one, two;
-    register int val;  /* keep going 'til no more registers... */
-
-    for (i = 0; (i < num) && (*str1) && (*str2); i++, str1++, str2++) {
-	one = (isupper(*str1) ? tolower(*str1) : *str1);
-	two = (isupper(*str2) ? tolower(*str2) : *str2);
-	if (val = two - one)
-	    return (val);
-    }
-    if (i == num)  /* first num characters are equal, so return zero */
-	return (0);
-    else {  /* one ended early; return result */
-	one = (isupper(*str1) ? tolower(*str1) : *str1);
-	two = (isupper(*str2) ? tolower(*str2) : *str2);
-	return (two - one);
-    }
-}
-
-/******************* file-related routines ********************/
-
-/*
- * Do operating system-dependent CREATE stuff
- *
- * Creates a NuFX archive file, with type info where necessary.
- * Does not leave file open.
- */
-void ArcfiCreate(filename)
-char *filename;
-{
-    static char *procName = "ArcfiCreate";
-#ifdef UNIX
-    int fd;
-
-    if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0)
-	Fatal("Unable to create file", procName);
-    close(fd);
-#else
-# ifdef APW
-    FileRec create_p;
-
-    c2pstr(filename);
-    create_p.pathname = filename;
-    create_p.fAccess = 0x00e3;
-    create_p.fileType = 0x00e0;  /* LBR */
-    create_p.auxType = 0x8002;	 /* SHK */
-    create_p.storageType = 0x0001;
-    create_p.createDate = 0x0000;  /* let ProDOS fill in the blanks */
-    create_p.createTime = 0x0000;
-    CREATE( &create_p );
-    ToolErrChk();
-    p2cstr(filename);
-# endif /* APW */
-# ifdef MSDOS
-    int fd;
-
-    if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0)
-	Fatal("Unable to create file", procName);
-    close(fd);
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    int fd;
-
-    if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0)
-	Fatal("Unable to create file", procName);
-    close(fd);
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-}
-
-
-/*
- * Determine if a file already exists.
- */
-BOOLEAN Exists(filename)
-char *filename;
-{
-    static char *procName = "Exists";
-#ifdef UNIX
-    struct stat sm;
-
-    if (stat(filename, &sm) < 0) {
-	if (errno == ENOENT)  /* if doesn't exist, then okay */
-	    return (FALSE);
-	else  /* some other problem killed stat(), probably serious */
-	    fprintf(stderr, "Unable to stat() '%s'\n", filename);
-	    Fatal("Bad stat()", procName); /*serious prob*/
-    } else  /* successful call - file exists */
-	return (TRUE);
-#else
-# ifdef APW
-    FileRec info_p;  /* check if file exists, is dir */
-    int err;
-
-    c2pstr(filename);
-    info_p.pathname = filename;
-    GET_FILE_INFO( &info_p );
-    err = _toolErr;
-    p2cstr(filename);
-    if (err == pathNotFound || err == fileNotFound)
-	return (FALSE);
-    else if (!err)
-	return (TRUE);
-    else {
-	_toolErr = err;
-	ToolErrChk();
-	return (TRUE);
-    }
-# endif /* APW */
-# ifdef MSDOS
-    struct stat sm;
-
-    if (stat(filename, &sm) < 0) {
-       if (errno == ENOENT)  /* if doesn't exist, then okay */
-           return (FALSE);
-       else  /* some other problem killed stat(), probably serious */
-           fprintf(stderr, "Unable to stat() '%s'\n", filename);
-           Fatal("Bad stat()", procName); /*serious prob*/
-    } else  /* successful call - file exists */
-       return (TRUE);
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    printf("Need [other] Exists()\n");  /* +PORT+ */
-    return (FALSE);
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-}
-
-
-/*
- * Generate a temporary file name (system dependent).
- * Assumes space is allocated for buffer.
- */
-char *MakeTemp(buffer)
-char *buffer;
-{
-    static char *procName = "MakeTemp";
-#ifdef UNIX
-    extern char *mktemp();
-
-    strcpy(buffer, "nulb.tmpXXXXXX");
-    return (mktemp(buffer));
-#else
-# ifdef APW
-    int idx = 0;
-
-    do {
-        sprintf(buffer, "nulb.tmp%d", idx++);
-    } while (Exists(buffer));
-    return (buffer);
-# endif /* APW */
-# ifdef MSDOS
-    extern char *mktemp();
-
-    strcpy(buffer, "nulbXXXX.tmp");
-    return (mktemp(buffer));
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    strcpy(buffer, "nulb.tmp");  /* +PORT+ */
-    return (buffer);
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-}
-
-#ifdef NO_RENAME
-/*
- * This is a replacement for the library call, in case somebody's C library
- * doesn't have it.
- */
-int rename(fromname, toname)
-{
-    if (link(fromname, toname) < 0)
-	return (-1);
-    if (unlink(fromname) < 0)
-	return (-1);
-}
-#endif
-
-
-/*
- * Rename a file.
- */
-void Rename(fromname, toname)
-char *fromname, *toname;
-{
-    static char *procName = "Rename";
-#ifdef UNIX
-    if (Exists(toname)) {
-	fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n",
-	    prgName, fromname, toname);
-	fflush(stderr);
-    }
-# ifdef AOSVS					/* BAK 04/30/90 */
-    printf("Work on AOS/VS rename command\n");	/* BAK 04/30/90 */
-# else						/* BAK 04/30/90 */
-    else {
-	if (rename(fromname, toname) < 0) {  /* this should "never" fail */
-	    fprintf(stderr,
-		"\n%s: WARNING: Unable to rename '%s' as '%s'\n",
-		prgName, fromname, toname);
-	    Fatal("Bad rename()", procName); /*serious prob*/
-	}
-    }
-# endif
-#else
-# ifdef APW
-    PathNameRec cpath_p;
-
-    if (Exists(toname)) {
-	fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n",
-	    prgName, fromname, toname);
-	fflush(stderr);
-	return;
-    }
-
-    cpath_p.pathname = fromname;
-    cpath_p.newPathname = toname;
-    c2pstr(fromname);
-    c2pstr(toname);
-    CHANGE_PATH( &cpath_p );
-    ToolErrChk();
-    p2cstr(fromname);
-    p2cstr(toname);
-# endif /* APW */
-# ifdef MSDOS
-    if (Exists(toname)) {
-	fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n",
-	    prgName, fromname, toname);
-	fflush(stderr);
-	return;
-    }
-    printf("Work on MSDOS rename command\n");
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    if (Exists(toname)) {
-	fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n",
-	    prgName, fromname, toname);
-	fflush(stderr);
-	return;
-    }
-    printf("Need [other] rename command\n");  /* +PORT+ */
-# endif /* none2 */
-# endif /* none1 */
-#endif /*UNIX*/
-}
-
-/******************** date/time routines ********************/
-
-/*
- * Expand date/time from file-sys dependent format to eight byte NuFX format.
- * tptr is filesys format, TimePtr is NuFX format
- */
-void ExpandTime(tptr, TimePtr)	   /* (BSD) UNIX version */
-onebyt *tptr;  /* usually points to a time_t (long) */
-Time *TimePtr;
-{
-#ifdef UNIX
-    time_t *tp = (time_t *) tptr;
-    struct tm *unixt;
-
-    unixt = localtime(tp);  /* expand time_t into components */
-    TimePtr->second = unixt->tm_sec;
-    TimePtr->minute = unixt->tm_min;
-    TimePtr->hour = unixt->tm_hour;
-    TimePtr->year = unixt->tm_year;
-    TimePtr->day = unixt->tm_mday -1;  /* want 0-xx, not 1-xx */
-    TimePtr->month = unixt->tm_mon;
-    TimePtr->extra = 0;
-    TimePtr->weekDay = unixt->tm_wday +1;  /* Sunday = 1, not 0 like UNIX */
-#else
-# ifdef APW			    /* APW version */
-    twobyt date, time;
-
-    date = (twobyt)tptr[0] + ((twobyt)tptr[1] << 8);
-    time = (twobyt)tptr[2] + ((twobyt)tptr[3] << 8);
-    TimePtr->second = 0;  /* not stored in ProDOS file info */
-    TimePtr->minute = (char) time;  /* truncated to char */
-    TimePtr->hour = time >> 8;
-    TimePtr->year = date >> 9;
-    TimePtr->day = (date & 0x1f) - 1;
-    TimePtr->month = ((date & 0x01e0) >> 5) - 1;
-    TimePtr->extra = 0;
-    TimePtr->weekDay = 0;
-# endif /* APW */
-# ifdef MSDOS
-    struct tm *newtime;
-    time_t *tp = (time_t *) tptr;
-
-    newtime = localtime (tp);
-    TimePtr->second = (onebyt)newtime->tm_sec;
-    TimePtr->minute = (onebyt)newtime->tm_min;
-    TimePtr->hour   = (onebyt)newtime->tm_hour;
-    TimePtr->year   = (onebyt)newtime->tm_year;
-    TimePtr->day    = (onebyt)newtime->tm_mday - 1;
-    TimePtr->month  = (onebyt)newtime->tm_mon;
-    TimePtr->extra  = 0;
-    TimePtr->weekDay= (onebyt)newtime->tm_wday + 1;
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    printf("Need [other] time-expander\n");  /* +PORT+ */
-    TimePtr->second = 0;
-    TimePtr->minute = 0;
-    TimePtr->hour = 0;
-    TimePtr->year = 0;
-    TimePtr->day = 0;
-    TimePtr->month = 0;
-    TimePtr->extra = 0;
-    TimePtr->weekDay = 0;
-# endif /* none1 */
-# endif /* none2 */
-#endif /* UNIX */
-}
-
-
-/*
- * Get current time, put in struct
- */
-Time *GetTime()
-{
-    static Time t;
-#ifdef UNIX
-    struct tm *unixt;
-    time_t now = time(NULL);
-
-    unixt = localtime(&now);
-    t.second = unixt->tm_sec;
-    t.minute = unixt->tm_min;
-    t.hour = unixt->tm_hour;
-    t.year = unixt->tm_year;
-    t.day = unixt->tm_mday -1;	/* want 0-xx, not 1-xx */
-    t.month = unixt->tm_mon;
-    t.extra = 0;
-    t.weekDay = unixt->tm_wday +1;  /* Sunday = 1, not 0 like UNIX */
-    /* return (&t) */
-#else
-# ifdef APW
-    t = ReadTimeHex(t);
-    /* return (&t) */
-# endif /* APW */
-# ifdef MSDOS
-    struct tm *pctime;
-    time_t now = time(NULL);
-
-    pctime = localtime(&now);
-    t.second = (onebyt)pctime->tm_sec;
-    t.minute = (onebyt)pctime->tm_min;
-    t.hour   = (onebyt)pctime->tm_hour;
-    t.year   = (onebyt)pctime->tm_year;
-    t.day    = (onebyt)pctime->tm_mday -1; /* want 0-xx, not 1-xx */
-    t.month  = (onebyt)pctime->tm_mon;
-    t.extra  = 0;
-    t.weekDay= (onebyt)pctime->tm_wday +1;  /* Sunday = 1, not 0 */
-    /* return (&t) */
-# endif /* MSDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    printf("\nNeed [other] GetTime\n");  /* +PORT+ */
-    t->second = 0;
-    t->minute = 0;
-    t->hour = 0;
-    t->year = 0;
-    t->day = 0;
-    t->month = 0;
-    t->filler = 0;
-    t->weekDay = 0;
-    /* return (&t) */
-# endif /* none1 */
-# endif /* none2 */
-#endif /* UNIX */
-    return (&t);
-}
-
-
-/*
- * Convert a NuFX Time struct to a compact system-dependent format
- *
- * This is used to set a file's date when extracting.  Most systems don't
- * dedicate 8 bytes to storing the date; this reduces it to the format
- * used by a "set_file_date" command.
- */
-long ReduceTime(tptr)
-Time *tptr;
-{
-#ifdef UNIX
-    long t = timecvt(tptr);
-
-    return (t ? t : time(NULL));	/* if stored time is invalid, */
-					/* return current time */
-#else
-# ifdef APW
-    twobyt date, time;
-    long val;
-
-    date = ((twobyt)tptr->year << 9) | ((((twobyt)tptr->month)+1) << 5) |
-   	(((twobyt)tptr->day)+1);
-    time = ((twobyt)tptr->hour << 8) | ((twobyt)tptr->minute);
-
-    val = (long) date + ((long) time << 16);
-    return (val);
-# endif /* APW */
-# ifdef MSDOS
-    return (time(NULL)); /* not sure what to do, return current : RBH */
-# endif /* MSDOS */
-
-#ifndef APW
-#ifndef MSDOS
-    printf("Need [other] ReduceTime\n");  /* +PORT+ */
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-}
-
=numain.c
-/*
- * numain.c - shell-based front end for NuLib
- *
- * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "main"
-#endif
-
-static char *header =
- "NuLib v3.03  February 1991  Freeware   Copyright 1989-91 By Andy McFadden";
-
-#include "nudefs.h"	/* system-dependent defines */
-#include <stdio.h>	/* standard I/O library */
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>	/* C type stuff, like tolower() */
-#ifdef BSD43
-# include <strings.h>
-#else  /* SYSV, APW, MSC */
-# include <string.h>	/* string stuff */
-#endif
-
-#ifdef APW
-# include <stdlib.h>
-# include <types.h>
-# include <strings.h>
-# include <shell.h>
-#endif
-
-#include "nuread.h"	/* structs for archive info, archive read routines */
-#include "nuview.h"	/* archive listing functions */
-#include "nuadd.h"	/* archive operations (add, create, move) */
-#include "nuext.h"	/* archive operations (extract) */
-#include "nupdel.h"	/* archive operations (delete, update, freshen) */
-#include "nublu.h"	/* Binary II archive operations */
-#include "nupak.h"	/* need PAKBUFSIZ */	
-#include "nuetc.h"	/* Malloc(), Fatal(), etc. */
-
-extern char *getenv();  /* +PORT+ */
-
-#define Whoops(str) printf("WARNING: typedef %s may be set incorrectly\n",str);
-#define ENVAR	"NULIBOPT"  /* environment variable with options in it */
-
-/*
- * global to entire program
- */
-int HiLo;		/* byte ordering; FALSE on low-first (65816) */
-int verbose;		/* print verbose? */
-int interact;		/* interactive overwrite mode? */
-int dopack;		/* do we want to pack/unpack? */
-int doExpand;		/* do we want to expand archive filenames? */
-int doSubdir;		/* process subdirectories at all? */
-int doMessages;		/* do comments instead of data */
-int transfrom;	/* how to do CR<->LF translation (from what?)  (-1 = off) */
-int transto;	/* translate to ? */
-int packMethod;		/* how to pack a file */
-fourbyt defFileType;	/* default file type */
-fourbyt defAuxType;	/* default aux type */
-onebyt *pakbuf;  /* used by compression routines; created once to reduce */
-		 /* overhead involved in malloc()ing a 64K buffer */
-char *prgName = "NuLib";    /* for error messages; don't like argv[0] */
-			    /* besides, the name changes every 3 weeks */
-
-/*
- * Print simple usage info
- */
-static void Usage(argv0)
-char *argv0;
-{
-    printf("\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0);
-    printf("\nType \"%s h\" for help.\n", argv0);
-}
-
-
-/*
- * Print usage info
- */
-static void Help(argv0, options)
-char *argv0, *options;
-{
-    if (INDEX(options+1, 'n')) {  /* using 'n' suboption? */
-	printf("%s\n", header);
-	printf("\nCompression methods:\n");
-	printf("  #  Name                        Abbr  Pack?  Unpack?\n");
-	printf("  0: Uncompressed                unc     Y      Y\n");
-	printf("  1: SQueezed (sq/usq)           squ     N      Y\n");
-	printf("  2: Dynamic LZW-I (ShrinkIt)    shk     Y      Y\n");
-	printf("  3: Dynamic LZW-II (ShrinkIt)   sh2     N      N\n");
-	printf("  4: UNIX 12-bit compress        u12     Y      Y\n");
-	printf("  5: UNIX 16-bit compress        u16     Y      Y\n");
-	printf("The default is #2\n");
-	printf("\nText conversion methods (during extraction):\n");
-	printf("  0: Convert from CR to this system (ProDOS files)\n");
-	printf("  1: Convert from LF to this system (UNIX files)\n");
-	printf("  2: Convert from CRLF to this system (MS-DOS files)\n");
-
-    } else if (INDEX(options+1, 'w')) {  /* print author info */
-
-	printf("%s\n", header);
-	printf(
-       "Internet: fadden@cory.berkeley.edu   Usenet: ...!ucbvax!cory!fadden\n");
-	printf("\nShrinkIt and NuFX standard by Andy Nicholas.\n");
-	printf(
-  "ShrinkIt LZW compression by Kent Dickey.  LZW/II (a modified version of\n");
-	printf("  Kent's algorithm) by Andy Nicholas.\n");
-	printf("\nUNIX compress code adapted from COMPRESS v4.3.\n");
-	printf(
-"\nBinary II unpack and unsqueeze C code adapted from unblu.c and usq.c by\n");
-	printf("  Marcel J.E. Mol (usq.c based on usq2/sq3 by Don Elton).\n");
-	printf("\nMS-DOS port by Robert B. Hess and Bruce Kahn.\n");
-	printf(
-"\nThis program is Freeware.  Please distribute as widely as possible, but\n");
-	printf(
-      "  don't sell it.  Source code is available via e-mail upon request.\n");
-	printf(
-	   "\nUsers without Usenet/Internet access may send mail to me at:\n");
-	printf("  1474 Saskatchewan Drive\n");
-	printf("  Sunnyvale, CA 94087\n");
-
-    } else if (INDEX(options+1, 's')) {  /* suboption info */
-	printf("%s\n", header);
-	printf("\nUsual meaning of suboptions:\n");
-	printf("  c  - compression type, followed by a number\n");
-	printf(
-	    "  f  - file/aux type to add, followed by file/aux type spec\n");
-	printf("  i  - interactive; prompt before overwriting file\n");
-	printf("  m  - messages (add/extract comments instead of data)\n");
-	printf("  r  - don't recursively descend subdirectories\n");
-	printf("  s  - storage type (store as compressed w/o compressing), ");
-	printf("followed by number\n");
-	printf(
-	   "  t  - text translation (CR<->LF), followed by conversion mode\n");
-	printf("  u  - store as uncompressed (same as c0)\n");
-	printf("  v  - verbose mode\n");
-#ifndef NO_BLU
-	printf("  x  - extract during Binary II operations\n");
-#endif
-	printf("  +  - match partial pathnames for extract and delete\n");
-	printf("\nTable of contents suboptions:\n");
-	printf("  v  - verbose output (same as V option)\n");
-	printf("  a  - ARC/ZOO style format\n");
-	printf("  z  - full output, prints all aspects of archive\n");
-
-	printf("\nSample shell variable command (csh):\n");
-	printf(
-      "  setenv NULIBOPT=verbose,interactive,type=SRC,aux=000a,compress=5\n");
-	printf("  (default is non-verbose, non-interactive, type=NON, ");
-	printf(  "aux=0000, compress=2)\n");
-	
-    } else {  /* default help screen */
-
-	printf("%s\n", header);
-	printf(
-	     "\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0);
-	printf("Option must be one of:\n");
-	printf("  a[vucsrf]   add to archive\n");
-#ifndef NO_BLU
-	printf("  b[xvti]     Binary II archive operations\n");
-#endif
-	printf(
-       "  c[vucsrf]   create archive (add, but suppress 'create' message)\n");
-	printf("  d[v+]       delete file from archive\n");
-	printf("  f[vucsrf]   freshen files in archive\n");
-	printf("  h[snw]      show help screen (subopt/numbers/who's who)\n");
-	printf("  i[v]        verify archive integrity\n");
-	printf("  m[vucsrf]   move files to archive (add, delete original)\n");
-	printf("  p[vmt+]     print archived file to stdout\n");
-	printf("  t[vaz]      display table of contents\n");
-	printf("  u[vucsrf]   update files in archive\n");
-	printf("  v           verbose listing (ProDOS 8 ShrinkIt format)\n");
-	printf("  x,e[vumti+] extract from archive\n");
-    }
-}
-
-
-/*
- * Check machine dependencies
- */
-static void CheckMach()
-{
-    onebyt one;
-    onebyt *oneptr;
-    twobyt two;
-    fourbyt four;
-
-#ifdef UNIX
-# ifdef APW
-    ^^ "ERROR: You have both APW and UNIX defined" ^^
-# endif
-# ifdef MSDOS
-    ^^ "ERROR: You have both MSDOS and UNIX defined" ^^
-# endif
-#endif /*UNIX*/
-#ifdef APW
-# ifdef MSDOS
-    ^^ "ERROR: You have both APW and MSDOS defined" ^^
-# endif
-#endif
-
-    /* some compilers complain about (unsigned) -1 , so I'm doing it this */
-    /* way to keep everybody quiet.					  */
-
-    one = 0x100;
-    if (one)
-	Whoops("onebyt");  /* one > 1 */
-    two = 0x10000;
-    if (two)
-	Whoops("twobyt");  /* two > 2 */
-    two = 0x1000;
-    if (!two)
-	Whoops("twobyt");  /* two < 2 */
-    four = 0xffffffff;
-    four++;
-    if (four)
-	Whoops("fourbyt");  /* four > 4 */
-    four = 0x10000;
-    if (!four)
-	Whoops("fourbyt");  /* four < 4 */
-
-    /* check byte ordering */
-    two = 0x1122;
-    oneptr = (onebyt *) &two;
-    if (*oneptr == 0x11)
-	HiLo = TRUE;
-    else if (*oneptr == 0x22)
-	HiLo = FALSE;
-    else {
-	printf("WARNING: Unable to determine a value for HiLo\n");
-	HiLo = FALSE;
-    }
-
-    /* check some other stuff... compilers may (should?) give warnings here */
-    if (ATTSIZE < MHsize)
-	printf("WARNING: ATTSIZE must be >= than MHsize\n");
-    if (RECBUFSIZ < ATTSIZE)
-	printf("WARNING: RECBUFSIZ should be larger than ATTSIZE\n");
-    if (MHsize != 48 || THsize != 16)
-	printf("WARNING: Bad MHsize or THsize\n");
-    if (sizeof(Time) != 8)
-	printf("WARNING: struct Time not 8 bytes\n");
-}
-
-
-/*
- * Check to see if string 2 is in string 1.
- *
- * Returns the position of string 2 within string 1; -1 if not found.
- */
-static int strc(host, sub)
-char *host, *sub;
-{
-    int hlen = strlen(host);
-    int slen = strlen(sub);
-    int i;
-
-    if (slen > hlen)  /* substring longer than host string */
-	return (-1);
-
-    /* generic linear search... */
-    for (i = 0; i <= (hlen - slen); i++)
-	if ((*(host+i) == *sub) && (!strncmp(host+i, sub, slen)))
-	    return (i);
-    
-    return (-1);
-}
-
-
-/*
- * Yank a number from a character string.
- */
-int OptNum(ptr)
-char *ptr;
-{
-    int val = 0;
-
-    while (*ptr && isdigit(*ptr)) {
-	val *= 10;
-	val += (*ptr - '0');
-	ptr++;
-    }
-    return (val);
-}
-
-
-/*
- * Set default values for globals.
- *
- * Should be of form "NULIBOPT=..."
- *   verbose		: default to verbose output
- *   interactive	: default to interactive mode when overwriting
- *   type=xxx		: set storage type to ProDOS type "xxx"
- *   aux=xxxx		: set aux storage type to 4-byte hex number "xxxx"
- */
-void GetDefaults(options)
-char *options;
-{
-    char *envptr;
-    int off, idx, pt;
-    int len = strlen(options);
-    char type[5];
-
-    /* set program default values */
-    verbose = FALSE;	/* silent mode */
-    interact = FALSE;	/* don't ask questions */
-    doSubdir = TRUE;	/* process subdirectories unless told not to */
-    dopack = TRUE;	/* don't pack unless told to */
-    doExpand = FALSE;	/* don't expand archived filenames */
-    doMessages = FALSE;	/* do comments instead of data */
-    packMethod = 0x0002;/* ShrinkIt LZW */
-    transfrom = -1;	/* no text translation */
-    transto = -1;
-    defFileType = (fourbyt) 0;	/* NON */
-    defAuxType = (fourbyt) 0;	/* $0000 */
-
-    /* read from global envir var */
-    if (envptr = getenv(ENVAR)) {
-	if (strc(envptr, "verbose") >= 0) {
-	    verbose = TRUE;
-	}
-	if (strc(envptr, "interactive") >= 0) {
-	    interact = TRUE;
-	}
-	if ((off = strc(envptr, "compress=")) >= 0) {
-	    off += 9;
-	    if (off+1 > strlen(envptr)) {
-		fprintf(stderr, "Error with 'compress=n' in NULIBOPT var\n");
-		Quit (-1);
-	    }
-	    packMethod = atoi(envptr+off);
-	}
-	if ((off = strc(envptr, "type=")) >= 0) {
-	    off += 5;
-	    if (off+3 > strlen(envptr)) {
-		fprintf(stderr, "Error with 'type=xxx' in NULIBOPT var\n");
-		Quit (-1);
-	    }
-	    strncpy(type, envptr+off, 3);
-	    type[3] = '\0';
-	    for (idx = 0; idx < 256; idx++)  /* scan for file type */
-		if (!strcasecmp(FT[idx], type)) {
-		    defFileType = (fourbyt) idx;
-		    break;  /* out of for */
-		}
-	}
-	if ((off = strc(envptr, "aux=")) >= 0) {
-	    off += 4;
-	    if (off+4 > strlen(envptr)) {
-		fprintf(stderr, "Error with 'aux=$xxxx' in NULIBOPT var\n");
-		Quit (-1);
-	    }
-	    strncpy(type, envptr+off, 4);
-	    type[4] = '\0';
-	    sscanf(type, "%x", &defAuxType);
-	}
-    }
-
-    /* handle command line suboption string */
-    for (pt = 1; pt < len; pt++) {  /* skip option char */
-	switch(options[pt]) {
-	case '+':	/* expand */
-	    doExpand = TRUE;
-	    break;
-	case 'a':	/* ARC/ZOO output format */
-	    /* do nothing */
-	    break;
-	case 'c':	/* compress method */
-	    packMethod = OptNum(&options[pt+1]);
-	    while (pt < len && isdigit(options[pt+1]))  /* advance to next */
-		pt++;
-	    dopack = TRUE;
-	    break;
-	case 'f':	/* filetype specified */
-	    strncpy(type, &options[pt+1], 3);
-	    type[3] = '\0';
-	    for (idx = 0; idx < 256; idx++)  /* scan for file type */
-		if (!strcasecmp(FT[idx], type)) {
-		    defFileType = (fourbyt) idx;
-		    break;  /* out of for */
-		}
-
-	    pt += strlen(type);
-	    if (options[pt+1] == '/') {  /* auxtype specification */
-		pt++;
-		strncpy(type, &options[pt+1], 4);
-		type[4] = '\0';
-		sscanf(type, "%lx", &defAuxType);
-		pt += strlen(type);
-	    }
-	    break;
-	case 'i':	/* interactive overwrites */
-	    interact = TRUE;
-	    break;
-	case 'm':	/* do messages instead of data */
-	    doMessages = TRUE;
-	    break;
-	case 'n':	/* help with numbers */
-	    /* do nothing */
-	    break;
-	case 'r':	/* don't recursively descend subdir */
-	    doSubdir = FALSE;
-	    break;
-	case 's':	/* store method */
-	    packMethod = OptNum(&options[pt+1]);
-	    while (pt < len && isdigit(options[pt+1]))  /* advance to next */
-		pt++;
-	    dopack = FALSE;
-	    break;
-	case 't':	/* how to translate text? */
-	    transfrom = OptNum(&options[pt+1]);
-	    while (pt < len && isdigit(options[pt+1]))
-		pt++;
-	    break;
-	case 'u':	/* don't use compression */
-	    dopack = FALSE;  /* this doesn't matter, but FALSE may be faster */
-	    packMethod = 0x0000;  /* archive w/o compression */
-	    break;
-	case 'v':	/* verbose mode */
-	    verbose = TRUE;
-	    break;
-	case 'w':	/* help on people */
-	    /* do nothing */
-	    break;
-	case 'x':	/* extract BLU files */
-	    /* do nothing */
-	    break;
-	case 'z':	/* in view files */
-	    /* do nothing */
-	    break;
-	default:	/* unknown */
-	    fprintf(stderr, "%s: unknown subopt '%c'\n", prgName, options[pt]);
-	    break;  /* do nothing */
-	}
-    }  /* for */
-}
-
-
-#ifdef APW
-/*
- * Expand a ProDOS filename using APW wildcard calls (even if the file doesn't
- * exist).
- *
- * Returns a pointer to a buffer holding the filename.
- */
-char *ExpandFilename(filename)
-char *filename;
-{
-    char *ptr;
-
-    c2pstr(filename);
-    if (!(*filename)) {
-	printf("Internal error: can't expand null filename\n");
-	Quit (-1);
-    }
-
-    INIT_WILDCARD(filename, 0);
-    ToolErrChk();
-    p2cstr(filename);
-
-    NEXT_WILDCARD(tmpNameBuf);
-    p2cstr(tmpNameBuf);
-    if (strlen(tmpNameBuf))  /* found it */
-	return(tmpNameBuf);
-    else {
-	/* file does not exist; expand path */
-	strcpy(tmpNameBuf, filename);
-	ptr = RINDEX(tmpNameBuf, '/');	/* remove filename */
-	if (!ptr)  /* filename only */
-	    return (filename);
-
-	*ptr = '\0';
-	if (!strlen(tmpNameBuf)) {  /* something weird... */
-	    printf("Unable to expand '%s'\n", filename);
-	    Quit (-1);
-	}
-
-	c2pstr(tmpNameBuf);
-	INIT_WILDCARD(tmpNameBuf, 0);
-	ToolErrChk();
-
-	NEXT_WILDCARD(tmpNameBuf);
-	p2cstr(tmpNameBuf);
-	if (!strlen(tmpNameBuf))  {
-	    printf("Unable to fully expand '%s'\n", filename);
-	    Quit (-1);
-	}
-
-	strcat(tmpNameBuf, RINDEX(filename, '/'));
-	return (tmpNameBuf);
-    }
-}
-#endif /* APW */
-
-
-/*
- * Parse args, call functions.
- */
-main(argc, argv)
-int argc;
-char **argv;
-{
-    char *filename;  /* hold expanded archive file name */
-    int idx;
-
-    filename = (char *) Malloc(MAXFILENAME);
-    CheckMach();  /* check compiler options, and set HiLo */
-
-    if (argc < 2) {  /* no arguments supplied */
-	Usage(argv[0]);
-	Quit (0);
-    }
-
-    if (argv[1][0] == '-') {  /* skip initial dashes */
-	argv[1]++;
-    }
-    for (idx = 0; argv[1][idx]; idx++)	/* conv opts to lower case */
-	if (isupper(argv[1][idx]))
-	    argv[1][idx] = tolower(argv[1][idx]);
-
-    if (argc < 3) {  /* no archive file specified; show help screen */
-	if (argv[1][0] == 'h')  /* could be HS, HN, or HW */
-	    Help(argv[0], argv[1]);
-	else			/* not 'H' option; show generic help scrn */
-	    Help(argv[0], "h");
-	Quit (0);
-    }
-
-#ifdef APW
-    strcpy(filename, ExpandFilename(argv[2]));
-#else
-    strcpy(filename, argv[2]);
-#endif
-    GetDefaults(argv[1]);  /* get defaults, process suboption string */
-
-    pakbuf = (onebyt *) Malloc(PAKBUFSIZ);  /* allocate global pack buf */
-    switch (argv[1][0]) {
-    case 'a':  /* add */
-    case 'c':  /* create */
-    case 'm':  /* move */
-	NuAdd(filename, argc-3, argv+3, argv[1]);  /* NuAdd will read */
-	break;
-#ifndef NO_BLU
-    case 'b':  /* Binary II operations */
-	NuBNY(filename, argc-3, argv+3, argv[1]);
-	break;
-#endif
-    case 'd':  /* delete */
-	NuDelete(filename, argc-3, argv+3, argv[1]);
-	break;
-    case 'f':  /* freshen */
-    case 'u':  /* update */
-	NuUpdate(filename, argc-3, argv+3, argv[1]);
-	break;
-    case 'i':  /* verify integrity */
-	NuTest(filename, argv[1]);
-	break;
-    case 't':  /* table of contents */
-    case 'v':  /* verbose output */
-	NuView(filename, argv[1]);
-	break;
-    case 'e':  /* extract */
-    case 'x':
-    case 'p':
-	NuExtract(filename, argc-3, argv+3, argv[1]);
-	break;
-    default:   /* need help */
-	fprintf(stderr, "%s: unknown option '%c'\n", argv[0], argv[1][0]);
-	break;
-    }
-
-    free (filename);
-    free (pakbuf);
-    Quit (0);
-}
-
=nupak.c
-/*
- * nupak.c - interface to the compression routines
- *
- * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "Compress"
-#endif
-
-#include "nudefs.h"
-#include <stdio.h>
-/*#include <fcntl.h>*/	/* "nucomp.h" includes <fcntl.h> for us */
-#include "nuread.h"	/* need THblock */
-#include "nucomp.h"	/* includes "nucompfn.h" + "types.h" */
-
-#ifdef MSDOS  /* for file I/O */
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <errno.h>
-#endif
-
-#include "nupak.h"
-#include "nuetc.h"
-
-#define CONVSIZ	1024
-
-long packedSize;  /* global - size of file after packing */
-onebyt lastseen;  /* used in crlf(); must be set by caller */
-
-
-/*
- * Make a little spinning thing.
- *
- * This just lets the user know that the whole thing hasn't stalled on him.
- * Prints a character, then backspaces so that the next thing will overwrite
- * it.
- *
- * Currently called by FCopy(), unpak_SHK(), pak_SHK()
- */
-void Spin()
-{
-    static char *sp = "/-\\|";
-    static int posn = 0;
-
-    posn++;
-    if ((posn < 0) || (posn > 3))
-	posn = 0;
-    putchar(sp[posn]);
-    putchar('\b');
-    fflush(stdout);
-}
-
-
-/*
- * Convert the end-of-line terminator between systems.
- *
- * Compile-time defines determine the value that things are translated to;
- * the value of "translate" determines what they are translated from.  This
- * will write the contents of the buffer to the passed file descriptor,
- * altering bytes as necessary.  Max buffer size is 64K.  Note that the
- * syntax is the same as for write();
- *
- * This would have been a lot easier without IBM...  lastseen is the last
- * character seen (used only in CRLF translations).  This needs to be set
- * by the caller (FCopy(), extract_files()).
- *
- * The putc_ncr() procedure in nusq.c does its own processing; this was
- * somewhat unavoidable.
- *
- * BUGS: This proc will have to be re-written.  It would be nice to be
- * able to pack files with a CRLF translation, not just unpack... but you
- * can't just do buffer writes for that.  It'll take some work, and will
- * probably appear in the next version.
- */
-unsigned int crlf(dstfd, buffer, length)
-int dstfd;
-onebyt *buffer;
-unsigned int length;
-{
-    register BOOLEAN doconv;
-    register onebyt *bptr = buffer;
-    register unsigned int idx;
-    static char *procName = "crlf";
-    unsigned int partial;   /* size for partial read/write */
-    onebyt tobuf[2048];
-    onebyt *toptr;
-    int conv;
-    unsigned int origlength = length;
-
-    if ((transfrom == -1) && (transto == -1)) {  /* no translation necessary */
-	return (write(dstfd, buffer, length));
-    }
-    if (transfrom < -1 || transfrom > 2) {
-	fprintf(stderr, "%s: unknown translation type %d\n",
-							prgName, transfrom);
-	fprintf(stderr, "%s: assuming conversion 0 (from CR)\n", prgName);
-	transfrom = 0;
-    }
-    if (transto < -1 || transto > 2) {
-	fprintf(stderr, "%s: unknown translation type %d\n",
-							prgName, transto);
-	fprintf(stderr, "%s: assuming conversion 0 (to CR)\n", prgName);
-	transto = 0;
-    }
-
-    /* macro defs for system-dependent actions */
-#ifdef UNIX
-# define DEFCONVFROM	if (*bptr == 0x0a)  /* LF */ \
-			    doconv = TRUE
-#  define DEFCONVTO	*(toptr++) = 0x0a
-#else
-# ifdef APW
-#  define DEFCONVFROM	if (*bptr == 0x0d)  /* CR */ \
-			    doconv = TRUE
-#  define DEFCONVTO	*(toptr++) = 0x0d
-# endif
-# ifdef MSDOS
-#  define DEFCONVFROM	if ((*bptr == 0x0a) && (lastseen == 0x0d)) { \
-			    doconv = TRUE; \
-			    toptr--;  /*already put CR; back up over it*/ \
-			} \
-			lastseen = *bptr
-#  define DEFCONVTO	*(toptr++) = 0x0d; \
-			*(toptr++) = 0x0a
-# endif
-# ifndef APW
-# ifndef MSDOS
-#  define DEFCONVFROM	if (*bptr == 0x0a)  /* LF */ \
-			    doconv = TRUE
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-
-    while (length != 0) {
-	if (length > CONVSIZ) {
-	    partial = CONVSIZ;
-	    length -= CONVSIZ;
-	} else {
-	    partial = length;
-	    length = 0;
-	}
-
-	/* uses an explicit flag rather than "continue" for clarity... */
-	toptr = tobuf;
-	for (idx = partial; idx > 0; idx--, bptr++) {
-	    doconv = FALSE;
-	    switch (transfrom) {
-	    case -1:  /* convert from current system's terminator */
-		DEFCONVFROM;
-		break;
-	    case 0:
-		if (*bptr == 0x0d)  /* CR */
-		    doconv = TRUE;
-		break;
-	    case 1:
-		if (*bptr == 0x0a)  /* LF */
-		    doconv = TRUE;
-		break;
-	    case 2:
-		if ((*bptr == 0x0a) && (lastseen == 0x0d)) {
-		    doconv = TRUE;
-		    toptr--;  /*already outputed CR; back up over it*/
-		}
-		lastseen = *bptr;
-		break;
-	    }
-
-
-	    if (doconv) {
-		switch (transto) {
-		case -1:  /* convert to current system's terminator */
-		    DEFCONVTO;
-		    break;
-		case 0:
-		    *(toptr++) = 0x0d;
-		    break;
-		case 1:
-		    *(toptr++) = 0x0a;
-		    break;
-		case 2:
-		    *(toptr++) = 0x0d;
-		    *(toptr++) = 0x0a;
-		    break;
-		}
-	    } else {
-		*(toptr++) = *bptr;
-	    }
-	} /* for loop */
-		    
-	if (write(dstfd, tobuf, (toptr-tobuf)) != (toptr-tobuf))
-	    Fatal("Dest write failed", procName);
-    }  /* while loop */
-    return (origlength);
-}
-
-
-/*
- * Read a file, and place in another file at current posn.  We can't read more
- * than PAKBUFSIZ at a time, so for some files it will have to be broken down
- * into pieces.  Note PAKBUFSIZ is expected to be an int (defined in nupak.h),
- * and can't be any larger than read() can handle (64K... unsigned 16-bit int).
- *
- * The transl option is present for NuUpdate and NuDelete, which have to
- * copy old records to a new archive w/o performing translation.
- */
-void FCopy(srcfd, dstfd, length, copybuf, transl)
-int srcfd;    /* source file descriptor (must be open & seek()ed) */
-int dstfd;    /* destination file descriptor (must be open & seek()ed) */
-fourbyt length; /* number of bytes to copy */
-onebyt *copybuf;
-BOOLEAN transl;  /* maybe do text translation? */
-{
-    unsigned int partial;   /* size for partial read/write */
-    static char *procName = "FCopy";
-
-    if (transl) lastseen = '\0';
-    while (length != 0L) {
-	if (length > (long) PAKBUFSIZ) {
-	    partial = (unsigned int) PAKBUFSIZ;
-	    length -= (long) PAKBUFSIZ;
-	    if (verbose) Spin();
-	} else {
-	    partial = (unsigned int) length;
-	    length = 0L;
-	}
-
-	if (read(srcfd, copybuf, partial) != partial)
-	    Fatal("Source read failed", procName);
-	if (transl) {  /* do text translation if user wants it */
-	    if (crlf(dstfd, copybuf, partial) != partial)
-		Fatal("Dest write failed (c)", procName);
-	} else {  /* NEVER do translation */
-	    if (write(dstfd, copybuf, partial) != partial)
-		Fatal("Dest write failed (w)", procName);
-	}
-    }
-}
-
-
-/*
- * Add a range of bytes from one file into another, packing them.
- *
- * Set up stuff, then call the appropriate pack routine.  Returns the actual
- * algorithm used (thread_format), since the compression algorithm could
- * fail, storing the file in uncompressed format instead.  The packed length
- * is stored in a global variable.
- *
- * Since we're only using version 0 records, we don't need to propagate the
- * thread_crc.
- *
- * Compression routines must do the following:
- * - compress data from one file descriptor to another, given two seeked
- *   file descriptors and a length value.  They may not rely on EOF conditions
- *   for either file.
- * - return the packing method actually used.  If they cope with failure
- *   by starting over with something different, the successful method should
- *   be returned.  Failure may be handled in the switch statement below.
- */
-twobyt PackFile(srcfd, dstfd, thread_eof, thread_format, buffer)
-int srcfd;    /* source file descriptor (must be open & seek()ed) */
-int dstfd;    /* destination file descriptor (must be open & seek()ed) */
-fourbyt thread_eof; /* size of input */
-int thread_format; /* how to pack the bytes */
-onebyt *buffer; /* alloc in main prog so we don't have to each time */
-{
-    long length = (long) thread_eof;
-    twobyt retval = thread_format;  /* default = successful pack */
-    long srcposn, dstposn;
-    static char *procName = "PackFile";
-
-    switch (thread_format) {
-    case 0x0000:  /* uncompressed */
-	if (verbose) { printf("storing...", thread_format);  fflush(stdout); }
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	packedSize = length;
-	break;
-
-    case 0x0001:  /* SQUeeze */
-	if (verbose) {
-	    printf("[can't squeeze; storing]...");
-	    fflush(stdout);
-	} else {
-	    printf("WARNING: can't squeeze; files stored uncompressed\n");
-	}
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	packedSize = length;
-	retval = 0x0000;  /* uncompressed */
-	break;
-
-    case 0x0002:  /* LZW (ShrinkIt) */
-	if (verbose) { printf("shrinking...");  fflush(stdout); }
-	/* packedSize set by pak_SHK */
-	retval = pak_SHK(srcfd, dstfd, length, buffer);
-	break;
-    case 0x0003:  /* LZW II (ShrinkIt) */
-	if (verbose) {
-	    printf("[can't do LZW II; storing]...");
-	    fflush(stdout);
-	} else {
-	    printf("WARNING: can't do LZW II; files stored uncompressed\n");
-	}
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	packedSize = length;
-	retval = 0x0000;  /* uncompressed */
-	break;
-    case 0x0004:  /* UNIX 12-bit compress */
-#ifdef NO_UCOMP
-	if (verbose) {
-	    printf("[can't do 12-bit UNIX compress; storing]...");
-	    fflush(stdout);
-	} else {
-	    printf(
-	    "WARNING: can't do 12-bit compress; files stored uncompressed\n");
-	}
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	packedSize = length;
-	retval = 0x0000;  /* uncompressed */
-#else
-	maxbits = 12;	/* global compress parameter */
-	if (verbose) { printf("compressing...");  fflush(stdout); }
-	/* packedSize set by compress() */
-	if (u_compress(srcfd, dstfd, length) == OK)
-	    retval = 0x0004;
-	else
-	    retval = 0x0004;	/* FIX this */
-#endif
-	break;
-
-    case 0x0005:  /* UNIX 16-bit compress */
-#ifdef NO_UCOMP
-	if (verbose) {
-	    printf("[can't do 16-bit UNIX compress; storing]...");
-	    fflush(stdout);
-	} else {
-	    printf(
-	    "WARNING: can't do 16-bit compress; files stored uncompressed\n");
-	}
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	packedSize = length;
-	retval = 0x0000;  /* uncompressed */
-#else
-	maxbits = 16;	/* global compress parameter */
-	if (verbose) { printf("compressing...");  fflush(stdout); }
-	/* packedSize set by compress() */
-	srcposn = lseek(srcfd, 0L, S_REL);	/* save posn */
-	dstposn = lseek(dstfd, 0L, S_REL);
-	if (u_compress(srcfd, dstfd, length) == OK) {
-	    /* compress succeeded */
-	    retval = 0x0005;
-	} else {
-	    /* compression failed */
-	    if (verbose) { printf("storing..."); fflush(stdout); }
-	    lseek(srcfd, srcposn, S_ABS);	/* reposn files */
-	    lseek(dstfd, dstposn, S_ABS);
-	    FCopy(srcfd, dstfd, length, buffer, TRUE);
-	    packedSize = length;
-	    retval = 0x0000;
-	}
-#endif
-	break;
-
-    default:
-	fprintf(stderr, "\nUnknown compression method %d\n", thread_format);
-	fprintf(stderr, "Aborting.\n");
-	Quit(-1);
-    }
-
-    return (retval);
-}
-
-
-/*
- * Extract a range of bytes from one file into another, unpacking them.
- *
- * (hacked to unpack disks, also.  Forces the thread_eof to be the total
- *  size of the disk, since ShrinkIt doesn't really define it, esp for DOS 3.3
- *  disks).
- *
- * Set up stuff, then call the appropriate unpack routine.  Leaves the srcfd
- * positioned past the data to be unpacked; the calling routine should not
- * have to do any seeks.
- *
- * Returns TRUE if able to unpack, FALSE if not able to.  Note that srcfd
- * WILL be seeked even if the compression method is not handled.
- *
- * New uncompression routines should have the following characteristics:
- * - they should be able to uncompress a range of bytes from one file
- *   to another given two seeked file descriptors and a length parameter.
- * - they should return TRUE if they succeed and FALSE otherwise.  Special
- *   condition codes can be handled in the switch statement below.
- */
-int UnpackFile(srcfd, dstfd, THptr, thread_format, buffer)
-int srcfd;	/* source file descriptor (must be open & lseek()ed) */
-int dstfd;	/* destination file descriptor (must be open & lseek()ed) */
-THblock *THptr;	/* pointer to thread structure */
-int thread_format; /* how to unpack the bytes (NOT THptr->thread_format) */
-onebyt *buffer;
-{
-    long length;
-    fourbyt thread_eof,		/* #of bytes to output */
-	    comp_thread_eof;	/* #of bytes in source */
-    twobyt thread_crc;
-    BOOLEAN retval = TRUE;  /* default to success */
-    static char *procName = "UnpackFile";
-
-    thread_eof = THptr->thread_eof;
-    comp_thread_eof = THptr->comp_thread_eof;
-    thread_crc = THptr->thread_crc;	/* never used? */
-    length = (long) comp_thread_eof;	/* type checking goes easier */
-
-    switch (thread_format) {
-    case 0x0000:  /* uncompressed */
-	if (verbose) { printf("extracting...", thread_format); fflush(stdout);}
-	FCopy(srcfd, dstfd, length, buffer, TRUE);
-	break;
-
-    case 0x0001:  /* unSQUeeze */
-#ifdef NO_BLU
-	if (verbose) {
-	    printf("[can't unsqueeze - aborting]...");
-	    fflush(stdout);
-	} else {
-	    printf("ERROR: can't unsqueeze; 'squ' files not extracted\n");
-	}
-	lseek(srcfd, length, S_REL);  /* set file posn */
-	retval = FALSE;
-#else
-	if (verbose) { printf("unsqueezing..."); fflush(stdout); }
-	unpak_SQU(srcfd, dstfd, length);  /* thread_eof not needed */
-#endif
-	break;
-
-    case 0x0002:  /* LZW (ShrinkIt) */
-	if (verbose) { printf("unshrinking (I)..."); fflush(stdout); }
-	unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, FALSE);
-	break;
-
-    case 0x0003:  /* LZW II (ShrinkIt) */
-#ifdef TRY_II
-	if (verbose) { printf("unshrinking (II)..."); fflush(stdout); }
-	unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, TRUE);
-#else
-	if (verbose) {
-	    printf("[can't unshrink type II - aborting]...");
-	    fflush(stdout);
-	} else {
-	    printf(
-		"ERROR: can't unshrink type II; 'sh2' files not extracted\n");
-	}
-	lseek(srcfd, length, S_REL);  /* set file posn */
-	retval = FALSE;
-#endif
-	break;
-
-    case 0x0004:  /* 12-bit UNIX compress */
-#ifdef NO_UCOMP
-	if (verbose) {
-	    printf("[can't undo 12-bit UNIX compress - aborting]...");
-	    fflush(stdout);
-	} else {
-	    printf(
-	"ERROR: can't undo 12-bit UNIX compress; 'u12' files not extracted\n");
-	}
-	lseek(srcfd, length, S_REL);  /* set file posn */
-	retval = FALSE;
-#else
-	if (verbose) { printf("uncompressing..."); fflush(stdout); }
-	if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK)
-	    retval = FALSE;
-#endif
-	break;
-
-    case 0x0005:  /* 16-bit UNIX compress */
-#ifdef NO_UCOMP
-	if (verbose) {
-	    printf("[can't undo 16-bit UNIX compress - aborting]...");
-	    fflush(stdout);
-	} else {
-	    printf(
-	"ERROR: can't undo 16-bit UNIX compress; 'u16' files not extracted\n");
-	}
-	lseek(srcfd, length, S_REL);  /* set file posn */
-	retval = FALSE;
-#else
-	if (verbose) { printf("uncompressing..."); fflush(stdout); }
-	if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK)
-	    retval = FALSE;
-#endif
-	break;
-
-    default:
-	fprintf(stderr, "Unknown uncompression method %d\n", thread_format);
-	lseek(srcfd, length, S_REL);  /* set file posn */
-	retval = FALSE;
-	break;
-    }
-
-    return (retval);
-}
-
+ END OF ARCHIVE