[comp.binaries.apple2] NuLib v2.1.1 NuFX archiver for UNIX or APW shar format 5/5

fadden@cory.Berkeley.EDU (Andy McFadden) (11/09/89)

NuLib part 5/5
-----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	nusq.c
#	nuview.c
# This archive created: Thu Nov  9 01:07:48 1989
# By:	Andy McFadden ()
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'nusq.c'" '(7091 characters)'
if test -f 'nusq.c'
then
	echo shar: "will not over-write existing file 'nusq.c'"
else
cat << \!Funky!Stuff! > 'nusq.c'
/*
 * nusq.c - Huffman squeeze/unsqueeze routines
 *	    Based on sq3/usq2 by Don Elton
 *
 * By Andy McFadden (fadden@cory.berkeley.edu)
 * NuLib v2.1  November 1989  Freeware (distribute, don't sell)
 */

#include "nudefs.h"
#include <stdio.h>
#include <fcntl.h>

#ifdef MSDOS     /* For file IO */
# include <io.h>
# include <sys\types.h>
# include <sys\stat.h>
# include <errno.h>
#endif

#include "nuetc.h"

/*
 * usq.c - undo Huffman coding
 * Adapated from code By Marcel J.E. Mol
 *
 * Squeezed file format:
 *     2 bytes MAGIC
 *     2 bytes dummy ???  (maybe CRC or checksum; not checked)
 *     filename ended by \0
 *
 *     2 bytes node count
 *     node count node values, each 2 bytes
 *     squeezed data per byte
 *
 * NuFX SQueezed format includes only the node count, node values, and
 *   the data.  The BLU routines are expected to strip off the MAGIC,
 *   checksum, and filename before calling this.
 */

/*char *copyright = "@(#) usq.c  2.1 18/06/88  (c) M.J.E. Mol";*/
#define BUFSIZE 128
#define MAGIC	0xff76		       /* Squeezed file magic */
#define DLE 0x90		       /* repeat byte flag */
#define NOHIST 0		       /* no relevant history */
#define INREP 1 		       /* sending a repeated value */
#define SPEOF 256		       /* special endfile token */
#define NUMVALS 257		       /* 256 data values plus SPEOF */

/* global variable declarations */
char *sfn;			       /* squeezed file name */
struct nd {			       /* decoding tree */
    int child[2];		       /* left, right */
} node[NUMVALS];		       /* use large buffer */
int state;			       /* repeat unpacking state */
int bpos;			       /* last bit position read */
int curin;			       /* last byte value read */
int numnodes;			       /* number of nodes in decode tree */

static unsigned char fromc;	/* for use in text translation */
static BOOLEAN trbool;		/* BOOLEAN version of transfrom */


/* Get an integer from the input stream */
static twobyt get_int(f)
FILE *f;
{
    twobyt val;

    val = (twobyt)getc(f);
    val += (twobyt)getc(f) << 8;
    return (val);
}


static int getc_usq(f) 		       /* get byte from squeezed file */
FILE *f;			       /* file containing squeezed data */
{
    register short i;		       /* tree index */

    /* follow bit stream in tree to a leaf */
    for (i=0; (i <= 0x7fff) && (i>=0); )/* work down(up?) from root */
    {
	 if (++bpos > 7) {
	      if ((curin=getc(f)) == EOF)
		   return(EOF);
	      bpos = 0;

	      /* move a level deeper in tree */
	      i = node[i].child[1 & curin];
	 }
	 else i = node[i].child[1 & (curin >>= 1)];
    }

    /* decode fake node index to original data value */
    i = -(i + 1);

    /* decode special endfile token to normal EOF */
    return ((i==SPEOF) ? EOF : i);
}


/*  putc-ncr -- decode non-repeat compression.	Bytes are passed one
 *		at a time in coded format, and are written out uncoded.
 *		The data is stored normally, except that runs of more
 *		than two characters are represented as:
 *
 *			 <char> <DLE> <count>
 *
 *		With a special case that a count of zero indicates a DLE
 *		as data, not as a repeat marker.
 */
static void putc_ncr(c, t)	       /* put NCR coded bytes */
unsigned char c;		       /* next byte of stream */
FILE *t;			       /* file to receive data */
{
    static int lastc;	      /* last character seen */

    /* if converting line terminators, do so now */
    if (trbool && (c == fromc))
#ifdef UNIX
	c = 0x0a;
#else
# ifdef APW
	c = 0x0d;
# else
	c = 0x0d;  /* No CRLF stuff in unSQueeze... sorry */
# endif
#endif

    switch (state) {		       /* action depends on our state */
	case NOHIST:		       /* no previous history */
	    if (c==DLE) 	       /* if starting a series */
		 state = INREP;        /* then remember it next time */
	    else putc(lastc=c, t);     /* else nothing unusual */
	    return;

	case INREP:		       /* in a repeat */
	    if (c)		       /* if count is nonzero */
		while (--c)	       /* then repeatedly ... */
		    putc(lastc, t);    /* ... output the byte */
	    else putc(DLE, t);	       /* else output DLE as data */
	    state = NOHIST;	       /* back to no history */
	    return;

	default:
	    fprintf(stderr, "%s: bad NCR unpacking state (%d)",
				prgName, state);
    }
}


static int init_usq(f) 		       /* initialize Huffman unsqueezing */
FILE *f;			       /* file containing squeezed data */
{
    register int i;		       /* node index */

    switch (transfrom) {
    case -1:  /* no translation */
	trbool = 0;
	break;
    case 0:  /* from ProDOS */
	trbool = 1;
	fromc = 0x0d;
	break;
    case 1:  /* from UNIX */
	trbool = 1;
	fromc = 0x0a;
	break;
    case 2:  /* from MS-DOS... this needs fixing */
	trbool = 1;
	fromc = 0x0a;  /* just turn LFs into whatever... */
	break;
    default:  /* unknown */
	fprintf(stderr, "%s: unknown translation type %d\n", prgName, trbool);
	fprintf(stderr, "%s: assuming conversion from CR\n", prgName);
	trbool = 1;  /* should just ignore flag, but other procs do this */
	fromc = 0x0d;
	break;
    }

    bpos = 99;			       /* force initial read */
    numnodes = get_int(f);	       /* get number of nodes */

    if (numnodes<0 || numnodes>=NUMVALS) {
	 fprintf(stderr, "%s: usq: archived file has invalid decode tree\n",
							prgName);
	 return (-1);
    }

    /* initialize for possible empty tree (SPEOF only) */
    node[0].child[0] = -(SPEOF + 1);
    node[0].child[1] = -(SPEOF + 1);

    for (i=0; i<numnodes; ++i) {	/* get decoding tree from file */
	 node[i].child[0] = get_int(f);
	 node[i].child[1] = get_int(f);
    }

    return (0);
}


/*
 * Unsqueeze a file
 */
static int unsqueeze(sfp, dfp)
FILE *sfp, *dfp;
{
    register int i;
    register int c;			/* one char of stream */

    state = NOHIST;		       /* initial repeat unpacking state */

    if (init_usq(sfp))		       /* init unsqueeze algorithm */
	return 1;
    while ((c=getc_usq(sfp)) != EOF)   /* and unsqueeze file */
	 putc_ncr(c, dfp);

    return (0);			       /* file is okay */
}


/*
 * main entrance to unsqueeze
 *
 * We reset the file posn to where it should be according to "length"; note
 * that "length" is not actually used by the unsqueeze routines.  We have
 * do to this because fdopen() sticks about 8K or so in a buffer...
 */
void unpak_SQU(srcfd, dstfd, length)
int srcfd, dstfd;
long length;  /* #of bytes we're expected to read */
{
    FILE *srcfp, *dstfp;		/* File pointers for squ/dest file */
    long finalposn;
    static char *procName = "unpak_SQU";

    finalposn = lseek(srcfd, 0L, S_REL) + length;  /* where we should end up */
    if ((srcfp = fdopen(srcfd, "r")) == NULL)
	Fatal("Can't fdopen() archive", procName);
    if ((dstfp = fdopen(dstfd, "w")) == NULL)
	Fatal("Can't fdopen() dest file", procName);

    unsqueeze(srcfp, dstfp);  /* unsqueeze the file */
    fflush(srcfp);  /* (this isn't really necessary) */
    fflush(dstfp);  /* This is *very* necessary */

    if (lseek(srcfd, finalposn, S_ABS) < 0)  /* set file posn back */
	Fatal("Can't reset final posn", procName);
    /* note that this makes things work even if unSQueezing failed */
}

!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'nuview.c'" '(13399 characters)'
if test -f 'nuview.c'
then
	echo shar: "will not over-write existing file 'nuview.c'"
else
cat << \!Funky!Stuff! > 'nuview.c'
/*
 * nuview.c - prints the contents of a NuFX archive
 *
 * By Andy McFadden (fadden@cory.berkeley.edu)
 * NuLib v2.1  November 1989  Freeware (distribute, don't sell)
 */

#include "nudefs.h"
#include <stdio.h>
#ifdef BSD43
# include <strings.h>
#else  /* SYSV, APW, MSC */
# include <string.h>
#endif

#ifdef APW
# include <shell.h>
#endif

#include "nuview.h"
#include "nuread.h"
#include "nuetc.h"


/*
 * String definitions for NuView
 */
/* unknown value msg */
char *unknownStr = "[ unknown ]";

/* weekDay values */
char *WD[8] = { "[ null ]", "Sunday", "Monday", "Tuesday", "Wednesday",
		"Thursday", "Friday", "Saturday" };

/* month values */
char *MO[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
		"Aug", "Sep", "Oct", "Nov", "Dec" };

/* thread_class */
/*#define TCn 4*/
char *TC[TCn] = { "Message_thread", "Control_thread", "Data_thread",
		"Sparse_thread" };

/*#define TKn 3  /* max #of thread_kinds in a thread_class */
char *TK[TCn][TKn] = {
		{ "ASCII text", "<undef>", "<undef>" },
		{ "Create directory", "<undef>", "<undef>" },
		{ "File data_fork", "Disk image", "File resource_fork" },
		{ "<undef>", "<undef>", "<undef>" } };

/* thread_format */
/*#define TFn 3*/
char *TF[TFn] = { "Uncompressed", "SQueezed (SQ/USQ)",
		"Dynamic LZW (ShrinkIt)" };

/* quick thread_format */
/*#define QTFn 3*/
char *QTF[QTFn] = { "unc", "squ", "shk" };

/* file_sys_id */
/*#define FIDn 12*/
char *FID[FIDn] = { "Reserved ($00)", "ProDOS/SOS", "DOS 3.3", "DOS 3.2",
		"Apple II Pascal", "Macintosh (HFS)", "Macintosh (MFS)",
		"LISA file system", "Apple CP/M", "Reserved ($09)", "MS-DOS",
		"High-Sierra/ISO 9660" };

/* storage_type */
/*#define STn 14*/
char *ST[STn] = { "Standard file ($00)", "Standard file ($01)",
		"Standard file ($02)", "Standard file ($03)", "??? ($04)",
		"Extended file ($05)", "??? ($06)", "??? ($07)", "??? ($08)",
		"??? ($09)", "??? ($0a)", "??? ($0b)", "??? ($0c)",
		"Subdirectory ($0d)" };

/* file type names */
char *FT[256] = {
	"NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "CHR",
	"PIC", "BA3", "DA3", "WPD", "SOS", "$0D", "$0E", "DIR",
	"RPD", "RPI", "$12", "OUT", "$14", "RPT", "$16", "$17",
	"$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F",
	"$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27",
	"$28", "$29", "$2A", "$2B", "$2C", "$2D", "$2E", "$2F",
	"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37",
	"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F",
	"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
	"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F",
	"$50", "$51", "$52", "$53", "$54", "$55", "$56", "$57",
	"$58", "$59", "$5A", "$5B", "$5C", "$5D", "$5E", "$5F",
	"PRE", "$61", "$62", "$63", "$64", "$65", "$66", "$67",
	"$68", "$69", "$6A", "NIO", "$6C", "DVR", "$6E", "HDV",
	"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77",
	"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F",
	"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
	"$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F",
	"$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97",
	"$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F",
	"WPF", "MAC", "HLP", "DAT", "$A4", "LEX", "$A6", "$A7",
	"$A8", "$A9", "$AA", "GSB", "ARC", "$AD", "$AE", "$AF",
	"SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "STR", "TSF",
	"NDA", "CDA", "TOL", "DRV", "$BC", "FST", "$BE", "DOC",
	"PNT", "SCR", "ANI", "$C3", "$C4", "$C5", "$C6", "$C7",
	"FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF",
	"$D0", "$D1", "$D2", "$D3", "$D4", "$D5", "$D6", "$D7",
	"$D8", "$D9", "$DA", "$DB", "$DC", "DDD", "$DE", "$DF",
	"LBR", "$E1", "ATI", "$E3", "$E4", "$E5", "$E6", "$E7",
	"$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "$EE", "PAS",
	"CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7",
	"$F8", "IMG", "INT", "IVR", "BAS", "VAR", "REL", "SYS" };


/*
 * NuView program
 */

/* print date from Time structure */
char *PrintDate(tptr, brief)
Time *tptr;
BOOLEAN brief;
{
    static char buf[64];  /* holds final date string; must be static */
    char buf2[64];  /* space to hold string while building it */

    /* check for validity */
    if ( (tptr->day > 30) || (tptr->month > 11) || (tptr->hour > 24) ||
	(tptr->minute > 59) ) {
	strcpy(buf, "   <invalid>   ");
	return (buf);
    }

    /* only print weekDay if one was stored and if we're in FULL mode */
    if (!brief && tptr->weekDay) {
	(void) sprintf(buf, "%s, ", WD[tptr->weekDay]);
    } else {
	buf[0] = '\0';
    }
    (void) sprintf(buf2, "%.2d-%s-%.2d %.2d:%.2d",
	(tptr->day)+1, MO[tptr->month], tptr->year,
	tptr->hour, tptr->minute);
    (void) strcat(buf, buf2);
    if (!brief) {  /* add seconds to long output */
	(void) sprintf(buf2, ":%.2d", tptr->second);
	(void) strcat(buf, buf2);
    }
    return (buf);
}


/*
 * Dump contents of the threads (used by FULL view mode)
 */
static void DumpThreads(RNodePtr)
RNode *RNodePtr;
{
    int i;
    fourbyt count = RNodePtr->RHptr->total_threads;
    static char ind[4] = "   ";  /* indentation */
    THblock *THptr;
    TNode *TNodePtr;

    /* go through all threads, printing as we go */
    TNodePtr = RNodePtr->TNodePtr;
    for (i = 0; (fourbyt) i < count; i++) {
	if (TNodePtr == (TNode *) NULL) {
	    fprintf(stderr, "WARNING: fewer threads than expected\n");
	    return;
	}
	THptr = TNodePtr->THptr;

	printf("%s --> Information for thread %d\n", ind, i);
	printf("%s thread_class: %s\n", ind, THptr->thread_class < TCn ?
		TC[THptr->thread_class] : unknownStr);
	printf("%s thread_format: %s\n", ind, THptr->thread_format < TFn ?
		TF[THptr->thread_format] : unknownStr);
	printf("%s thread_kind: %s ($%.2X)\n", ind,
		(THptr->thread_kind < TKn && THptr->thread_class < TCn) ?
		TK[THptr->thread_class][THptr->thread_kind] : unknownStr,
		THptr->thread_kind);
	printf("%s thread_eof: %lu   ", ind, THptr->thread_eof);
	printf("comp_thread_eof: %lu\n", THptr->comp_thread_eof);
	printf("%s * position within file: %ld\n", ind, TNodePtr->fileposn);

	TNodePtr = TNodePtr->TNext;
    }
    /* after all info printed, show sum total of thread lengths */
    printf("%s * total thread_eof: %lu   ", ind, RNodePtr->unc_len);
    printf("total comp_thread_eof: %lu\n", RNodePtr->comp_len);
}


/*
 * Scan contents of the threads for certain things (for PROSHK view mode)
 * Returns 65535 as error code (-1 in an unsigned short)
 */
static twobyt ScanThreads(RNodePtr, format)
RNode *RNodePtr;
twobyt *format;
{
    int i;
    fourbyt count = RNodePtr->RHptr->total_threads;
    THblock *THptr;
    TNode *TNodePtr;

    *format = 65535;  /* default = error */
    TNodePtr = RNodePtr->TNodePtr;
    for (i = 0; (fourbyt) i < count; i++) {
	if (TNodePtr == (TNode *) NULL) {
	    fprintf(stderr, "WARNING: fewer threads than expected\n");
	    return (65535);
	}
	THptr = TNodePtr->THptr;

	if (THptr->thread_class == 2) {  /* data thread? */
	    *format = THptr->thread_format;
	    return (THptr->thread_kind);
	}
    }
    return (65535);  /* no data thread found */
}


/*
 * View archive contents
 *
 * Format types:
 *     T: NAMEONLY - Brief output of filenames only (good for pipes)
 *     V: PROSHK - ProDOS ShrinkIt format
 *     Z: FULL - Fully detailed output
 */
void NuView(filename, options)
char *filename;
char *options;
{
    ListHdr *archive;
    MHblock *MHptr;
    RHblock *RHptr;
    RNode *RNodePtr;
    outtype prtform;
    int rec;
    char tmpbuf[64];  /* temporary buffer for sprintf + printf */
    twobyt format, datakind;  /* PROSHK */
    int percent;  /* PROSHK */
#ifdef APW  /* kill "not used" messages */
    char *ptr;
#endif
    static char *procName = "NuView";

    /* process options ourselves */
    switch (options[0]) {
    case 't':
	if (INDEX(options+1, 'v')) prtform = PROSHK;  /* -tv is same as -v */
	if (INDEX(options+1, 'z')) prtform = FULL;
	else prtform = NAMEONLY;
	break;
    case 'v':
	prtform = PROSHK;
	break;
    default:
	fprintf(stderr, "NuView internal error: unknown output format\n");
	Quit (-1);
    }

    archive = NuRead(filename);
    MHptr = archive->MHptr;

    /* Print master header info */
    if (prtform == NAMEONLY) {
	/* don't print any info from master hedaer for NAMEONLY */
    } else if (prtform == PROSHK) {
#ifdef APW
	/* strip partial paths from APW filename (if any) */
	ptr = RINDEX(archive->arc_name, '/');
	printf(" %-15.15s ", ptr ? ptr+1 : archive->arc_name);
#else
	printf(" %-15.15s ", archive->arc_name);
#endif
	printf("Created:%s   ", PrintDate(&MHptr->arc_create_when, TRUE));
	printf("Mod:%s     ", PrintDate(&MHptr->arc_mod_when, TRUE));
	printf("Recs:%5lu\n\n", MHptr->total_records);
	printf(" Name                  Kind  Typ  Auxtyp Archived");
	printf("        Fmat Size  Un-Length\n");
	printf("-------------------------------------------------") ;
	printf("----------------------------\n");
    } else if (prtform == FULL) {
	printf("Now processing archive '%s'\n", archive->arc_name);
	printf("---> Master header information:\n");
	printf("master ID: '%.6s'     ", MHptr->ID);
	printf("master_crc: $%.4X\n", MHptr->master_crc);
	printf("total_records: %lu\n", MHptr->total_records);
	printf("created: %s   ", PrintDate(&MHptr->arc_create_when, FALSE));
	printf("mod: %s\n", PrintDate(&MHptr->arc_mod_when, FALSE));
    } else {
	printf("NuView internal error: undefined output format\n");
	Quit (-1);
    }

    /* Print record info */
    RNodePtr = archive->RNodePtr;
    for (rec = 0; (fourbyt) rec < MHptr->total_records; rec++) {
	if (RNodePtr == (RNode *) NULL) {
	    fprintf(stderr, "WARNING: fewer records than expected\n");
	    return;
	}
	RHptr = RNodePtr->RHptr;

	if (prtform == NAMEONLY) {
	    printf("%.79s\n", RNodePtr->filename);  /* max 79 chars */
	} else if (prtform == PROSHK) {
	    printf("%c", (RHptr->access == 0xE3L || RHptr->access == 0xC3L) ?
		' ' : '+');
	    printf("%-21.21s ", RNodePtr->filename);
	    datakind = ScanThreads(RNodePtr, &format);	/* data_thread info */
	    if (datakind == 65535) {  /* no data thread... */
		printf("????  ");
		printf("%s  ", RHptr->file_type < 256L ? FT[RHptr->file_type] :
			"???");
		printf("$%.4X  ", (twobyt) RHptr->extra_type);
	    } else if (datakind == 1) {  /* disk */
		printf("Disk  ");
		printf("---  ");
		(void) sprintf(tmpbuf, "%dk", (twobyt) RHptr->extra_type / 2);
		printf("%-5s  ", tmpbuf);
	    } else {  /* must be a file */
		printf("File  ");
		printf("%s  ", RHptr->file_type < 256L ? FT[RHptr->file_type] :
			"???");
		printf("$%.4X  ", (twobyt) RHptr->extra_type);
	    }
	    printf("%s  ", PrintDate(&RHptr->archive_when, TRUE));
	    printf("%s  ", format < QTFn ? QTF[format] : "???");

	    /* figure out the percent size, and format it appropriately */
	    if (!RNodePtr->unc_len && !RNodePtr->comp_len) {
		printf("100%%  ");  /* file is 0 bytes long */
	    } else if ((!RNodePtr->unc_len && RNodePtr->comp_len) ||
			(RNodePtr->unc_len && !RNodePtr->comp_len)) {
		printf("---   ");  /* something weird happened */
	    } else if (RNodePtr->unc_len < RNodePtr->comp_len) {
		printf(">100%% ");  /* compression failed?!? */
	    } else {  /* compute from sum of thread lengths (use only data?) */
		percent = (((float) RNodePtr->comp_len /
			(float) RNodePtr->unc_len) * 100.0) /*+ 0.5*/ ;
		(void) sprintf(tmpbuf, "%.2d%%", percent);
		printf("%-4s  ", tmpbuf);
	    }
	    if (!RNodePtr->unc_len && RNodePtr->comp_len)  /* weird */
		printf("    ????\n");
	    else
		printf("%8ld\n", RNodePtr->unc_len);
	} else if (prtform == FULL) {
	    printf("\n---> Information for record %d:\n", rec);
	    printf("Filename: (%d) '%s'\n",
					RNodePtr->namelen, RNodePtr->filename);
	    printf("header ID: '%.4s'   ", RHptr->ID);
	    printf("header_crc: $%.4X\n", RHptr->header_crc);
	    printf("attrib_count: %u   ", RHptr->attrib_count);
	    printf("version_number: %u   ", RHptr->version_number);
	    printf("total_threads: %lu\n", RHptr->total_threads);
	    printf("file_sys_id: %s   ", RHptr->file_sys_id < FIDn ?
		FID[RHptr->file_sys_id] : unknownStr);
	    printf("sep: '%c'   ", (onebyt) RHptr->file_sys_info);
	    printf("sparse: %s (%u)\n", (onebyt) RHptr->file_sys_info >> 8 ?
		"Yes" : "No", (onebyt) RHptr->file_sys_info >> 8);
	    if (RHptr->file_sys_id == 0x0001) {  /* ProDOS-specific */
		printf("access: %s ($%.8lX)   ", (RHptr->access == 0xE3L ||
		RHptr->access == 0xC3L) ? "Unlocked" : "Locked", RHptr->access);
		printf("file_type: %s ($%.8lX)\n", RHptr->file_type < 256L ?
		    FT[RHptr->file_type] : "???", RHptr->file_type);
	    } else {  /* all other filesystems */
		printf("access: $%.8lX", RHptr->access);
		printf("file_type: $%.8lX\n", RHptr->file_type);
	    }
	    printf("extra_type: $%.8lX   ", RHptr->extra_type);
	    printf("storage_type: %s\n", RHptr->storage_type < STn ?
		ST[RHptr->storage_type] : unknownStr);
	    printf("created: %s   ", PrintDate(&RHptr->create_when, FALSE));
	    printf("mod: %s\n", PrintDate(&RHptr->mod_when, FALSE));
	    printf("archived: %s\n", PrintDate(&RHptr->archive_when,
		    FALSE));
	    /* future expansion... */
	} else {
	    printf("NuView internal error: undefined output format\n");
	    Quit (-1);
	}

	/* Print thread info */
	if (prtform == FULL) DumpThreads(RNodePtr);
	RNodePtr = RNodePtr->RNext;  /* advance to next record */
#ifdef APW
	if (STOP()) Quit (1);  /* check for OA-period */
#endif
    }
    if (prtform == FULL)
	printf("\n*** end of file position: %ld\n", archive->nextposn);
}
!Funky!Stuff!
fi  # end of overwriting check
exit 0
#	End of shell archive