home *** CD-ROM | disk | FTP | other *** search
- From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
- Newsgroups: comp.sources.apple2
- Subject: v001SRC036: Nulib - Archive Library Tools (Unix) 05/10
- Message-ID: <May.1.18.11.35.1991.23506@yoko.rutgers.edu>
- Date: 1 May 91 22:11:37 GMT
- Approved: jac@paul.rutgers.edu
-
-
- 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
-