arc.shar.04
Stu Heiss
stu at jpusa1.UUCP
Wed Oct 1 06:51:53 AEST 1986
#! /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:
# arcsq.c
# arcsvc.c
# arctst.c
# arcunix.c
# arcunp.c
# arcusq.c
# marc.c
# tm_to_time.c
# xarc.c
# This archive created: Tue Sep 30 11:44:45 1986
# By: stu (JPUSA - Chicago, IL)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "x - 'arcsq.c'"
if test -f 'arcsq.c'
then
echo shar: "will not over-write existing file 'arcsq.c'"
else
sed 's/^X//' << \SHAR_EOFarcsq.c > 'arcsq.c'
X/* ARC - Archive utility - ARCSQ
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This file contains the routines used to squeeze a file
X when placing it in an archive.
X
X Language:
X Computer Innovations Optimizing C86
X
X Programming notes:
X Most of the routines used for the Huffman squeezing algorithm
X were lifted from the SQ program by Dick Greenlaw, as adapted
X to CI-C86 by Robert J. Beilstein.
X*/
X#include <stdio.h>
X
X#define int16size 16 /* 16 bits */
X
X/* stuff for Huffman squeezing */
X
X#define TRUE 1
X#define FALSE 0
X#define ERROR (-1)
X#define SPEOF 256 /* special endfile token */
X#define NOCHILD -1 /* marks end of path through tree */
X#define NUMVALS 257 /* 256 data values plus SPEOF*/
X#define NUMNODES (NUMVALS+NUMVALS-1) /* number of nodes */
X#define MAXCOUNT (unsigned) 65535 /* biggest unsigned integer */
X
X/* The following array of structures are the nodes of the
X binary trees. The first NUMVALS nodes become the leaves of the
X final tree and represent the values of the data bytes being
X encoded and the special endfile, SPEOF.
X The remaining nodes become the internal nodes of the final tree.
X*/
X
Xstruct nd /* shared by unsqueezer */
X{ unsigned weight; /* number of appearances */
X int tdepth; /* length on longest path in tree */
X int lchild, rchild; /* indices to next level */
X} node[NUMNODES]; /* use large buffer */
X
Xstatic int dctreehd; /* index to head of final tree */
X
X/* This is the encoding table:
X The bit strings have first bit in low bit.
X Note that counts were scaled so code fits unsigned integer.
X*/
X
Xstatic int codelen[NUMVALS]; /* number of bits in code */
Xstatic unsigned code[NUMVALS]; /* code itself, right adjusted */
Xstatic unsigned tcode; /* temporary code value */
Xstatic long valcount[NUMVALS]; /* actual count of times seen */
X
X/* Variables used by encoding process */
X
Xstatic int curin; /* value currently being encoded */
Xstatic int cbitsrem; /* # of code string bits left */
Xstatic unsigned ccode; /* current code right justified */
X
Xinit_sq() /* prepare for scanning pass */
X{
X int i; /* node index */
X
X /* Initialize all nodes to single element binary trees
X with zero weight and depth.
X */
X
X for(i=0; i<NUMNODES; ++i)
X { node[i].weight = 0;
X node[i].tdepth = 0;
X node[i].lchild = NOCHILD;
X node[i].rchild = NOCHILD;
X }
X
X for(i=0; i<NUMVALS; i++)
X valcount[i] = 0;
X}
X
Xscan_sq(c) /* add a byte to the tables */
Xint c; /* byte to add */
X{
X unsigned *wp; /* speeds up weight counting */
X
X /* Build frequency info in tree */
X
X if(c == EOF) /* it's traditional */
X c = SPEOF; /* dumb, but traditional */
X
X if(*(wp = &node[c].weight) != MAXCOUNT)
X ++(*wp); /* bump weight counter */
X
X valcount[c]++; /* bump byte counter */
X}
X
Xlong pred_sq() /* predict size of squeezed file */
X{
X int i;
X int btlist[NUMVALS]; /* list of intermediate b-trees */
X int listlen; /* length of btlist */
X unsigned ceiling; /* limit for scaling */
X long size = 0; /* predicted size */
X int numnodes; /* # of nodes in simplified tree */
X
X scan_sq(EOF); /* signal end of input */
X
X ceiling = MAXCOUNT;
X
X /* Keep trying to scale and encode */
X
X do
X { scale(ceiling);
X ceiling /= 2; /* in case we rescale */
X
X /* Build list of single node binary trees having
X leaves for the input values with non-zero counts
X */
X
X for(i=listlen=0; i<NUMVALS; ++i)
X { if(node[i].weight != 0)
X { node[i].tdepth = 0;
X btlist[listlen++] = i;
X }
X }
X
X /* Arrange list of trees into a heap with the entry
X indexing the node with the least weight at the top.
X */
X
X heap(btlist,listlen);
X
X /* Convert the list of trees to a single decoding tree */
X
X bld_tree(btlist,listlen);
X
X /* Initialize the encoding table */
X
X init_enc();
X
X /* Try to build encoding table.
X Fail if any code is > 16 bits long.
X */
X } while(buildenc(0,dctreehd) == ERROR);
X
X /* Initialize encoding variables */
X
X cbitsrem = 0; /* force initial read */
X curin = 0; /* anything but endfile */
X
X for(i=0; i<NUMVALS; i++) /* add bits for each code */
X size += valcount[i] * codelen[i];
X
X size = (size+7)/8; /* reduce to number of bytes */
X
X numnodes = dctreehd<NUMVALS ? 0 : dctreehd-(NUMVALS-1);
X
X size += int16size + 2*numnodes*int16size;
X
X return size;
X}
X
X/* The count of number of occurrances of each input value
X have already been prevented from exceeding MAXCOUNT.
X Now we must scale them so that their sum doesn't exceed
X ceiling and yet no non-zero count can become zero.
X This scaling prevents errors in the weights of the
X interior nodes of the Huffman tree and also ensures that
X the codes will fit in an unsigned integer. Rescaling is
X used if necessary to limit the code length.
X*/
X
Xstatic scale(ceil)
Xunsigned ceil; /* upper limit on total weight */
X{
X register int i,c;
X int ovflw, divisor;
X unsigned w, sum;
X unsigned char increased; /* flag */
X
X do
X { for(i=sum=ovflw=0; i<NUMVALS; ++i)
X { if(node[i].weight > (ceil-sum))
X ++ovflw;
X sum += node[i].weight;
X }
X
X divisor = ovflw + 1;
X
X /* Ensure no non-zero values are lost */
X
X increased = FALSE;
X for(i=0; i<NUMVALS; ++i)
X { w = node[i].weight;
X if(w<divisor && w!=0)
X { /* Don't fail to provide a code if it's used at all */
X
X node[i].weight = divisor;
X increased = TRUE;
X }
X }
X } while(increased);
X
X /* Scaling factor choosen, now scale */
X
X if(divisor>1)
X for(i=0; i<NUMVALS; ++i)
X node[i].weight /= divisor;
X}
X
X/* heap() and adjust() maintain a list of binary trees as a
X heap with the top indexing the binary tree on the list
X which has the least weight or, in case of equal weights,
X least depth in its longest path. The depth part is not
X strictly necessary, but tends to avoid long codes which
X might provoke rescaling.
X*/
X
Xstatic heap(list,length)
Xint list[], length;
X{
X register int i;
X
X for(i=(length-2)/2; i>=0; --i)
X adjust(list,i,length-1);
X}
X
X/* Make a heap from a heap with a new top */
X
Xstatic adjust(list,top,bottom)
Xint list[], top, bottom;
X{
X register int k, temp;
X
X k = 2 * top + 1; /* left child of top */
X temp = list[top]; /* remember root node of top tree */
X
X if(k<=bottom)
X { if(k<bottom && cmptrees(list[k],list[k+1]))
X ++k;
X
X /* k indexes "smaller" child (in heap of trees) of top */
X /* now make top index "smaller" of old top and smallest child */
X
X if(cmptrees(temp,list[k]))
X { list[top] = list[k];
X list[k] = temp;
X
X /* Make the changed list a heap */
X
X adjust(list,k,bottom); /* recursive */
X }
X }
X}
X
X/* Compare two trees, if a > b return true, else return false.
X Note comparison rules in previous comments.
X*/
X
Xstatic cmptrees(a,b)
Xint a, b; /* root nodes of trees */
X{
X if(node[a].weight > node[b].weight)
X return TRUE;
X if(node[a].weight == node[b].weight)
X if(node[a].tdepth > node[b].tdepth)
X return TRUE;
X return FALSE;
X}
X
X/* HUFFMAN ALGORITHM: develops the single element trees
X into a single binary tree by forming subtrees rooted in
X interior nodes having weights equal to the sum of weights of all
X their descendents and having depth counts indicating the
X depth of their longest paths.
X
X When all trees have been formed into a single tree satisfying
X the heap property (on weight, with depth as a tie breaker)
X then the binary code assigned to a leaf (value to be encoded)
X is then the series of left (0) and right (1)
X paths leading from the root to the leaf.
X Note that trees are removed from the heaped list by
X moving the last element over the top element and
X reheaping the shorter list.
X*/
X
Xstatic bld_tree(list,len)
Xint list[];
Xint len;
X{
X register int freenode; /* next free node in tree */
X register struct nd *frnp; /* free node pointer */
X int lch, rch; /* temps for left, right children */
X int i;
X
X /* Initialize index to next available (non-leaf) node.
X Lower numbered nodes correspond to leaves (data values).
X */
X
X freenode = NUMVALS;
X
X while(len>1)
X { /* Take from list two btrees with least weight
X and build an interior node pointing to them.
X This forms a new tree.
X */
X
X lch = list[0]; /* This one will be left child */
X
X /* delete top (least) tree from the list of trees */
X
X list[0] = list[--len];
X adjust(list,0,len-1);
X
X /* Take new top (least) tree. Reuse list slot later */
X
X rch = list[0]; /* This one will be right child */
X
X /* Form new tree from the two least trees using
X a free node as root. Put the new tree in the list.
X */
X
X frnp = &node[freenode]; /* address of next free node */
X list[0] = freenode++; /* put at top for now */
X frnp->lchild = lch;
X frnp->rchild = rch;
X frnp->weight = node[lch].weight + node[rch].weight;
X frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth);
X
X /* reheap list to get least tree at top */
X
X adjust(list,0,len-1);
X }
X dctreehd = list[0]; /* head of final tree */
X}
X
Xstatic maxchar(a,b)
X{
X return a>b ? a : b;
X}
X
Xstatic init_enc()
X{
X register int i;
X
X /* Initialize encoding table */
X
X for(i=0; i<NUMVALS; ++i)
X codelen[i] = 0;
X}
X
X/* Recursive routine to walk the indicated subtree and level
X and maintain the current path code in bstree. When a leaf
X is found the entire code string and length are put into
X the encoding table entry for the leaf's data value .
X
X Returns ERROR if codes are too long.
X*/
X
Xstatic int buildenc(level,root)
Xint level; /* level of tree being examined, from zero */
Xint root; /* root of subtree is also data value if leaf */
X{
X register int l, r;
X
X l = node[root].lchild;
X r = node[root].rchild;
X
X if(l==NOCHILD && r==NOCHILD)
X { /* Leaf. Previous path determines bit string
X code of length level (bits 0 to level - 1).
X Ensures unused code bits are zero.
X */
X
X codelen[root] = level;
X code[root] = tcode & (((unsigned)~0) >> (16-level));
X return (level>16) ? ERROR : NULL;
X }
X
X else
X { if(l!=NOCHILD)
X { /* Clear path bit and continue deeper */
X
X tcode &= ~(1 << level);
X if(buildenc(level+1,l)==ERROR)
X return ERROR; /* pass back bad statuses */
X }
X if(r!=NOCHILD)
X { /* Set path bit and continue deeper */
X
X tcode |= 1 << level;
X if(buildenc(level+1,r)==ERROR)
X return ERROR; /* pass back bad statuses */
X }
X }
X return NULL; /* it worked if we reach here */
X}
X
Xstatic put_int(n,f) /* output an integer */
Xint n; /* integer to output */
XFILE *f; /* file to put it to */
X{
X putc_pak(n&0xff,f); /* first the low byte */
X putc_pak(n>>8,f); /* then the high byte */
X}
X
X/* Write out the header of the compressed file */
X
Xstatic long wrt_head(ob)
XFILE *ob;
X{
X register int l,r;
X int i, k;
X int numnodes; /* # of nodes in simplified tree */
X
X /* Write out a simplified decoding tree. Only the interior
X nodes are written. When a child is a leaf index
X (representing a data value) it is recoded as
X -(index + 1) to distinguish it from interior indexes
X which are recoded as positive indexes in the new tree.
X
X Note that this tree will be empty for an empty file.
X */
X
X numnodes = dctreehd<NUMVALS ? 0 : dctreehd-(NUMVALS-1);
X put_int(numnodes,ob);
X
X for(k=0, i=dctreehd; k<numnodes; ++k, --i)
X { l = node[i].lchild;
X r = node[i].rchild;
X l = l<NUMVALS ? -(l+1) : dctreehd-l;
X r = r<NUMVALS ? -(r+1) : dctreehd-r;
X put_int(l,ob);
X put_int(r,ob);
X }
X
X return int16size + numnodes*2*int16size;
X}
X
X/* Get an encoded byte or EOF. Reads from specified stream AS NEEDED.
X
X There are two unsynchronized bit-byte relationships here.
X The input stream bytes are converted to bit strings of
X various lengths via the static variables named c...
X These bit strings are concatenated without padding to
X become the stream of encoded result bytes, which this
X function returns one at a time. The EOF (end of file) is
X converted to SPEOF for convenience and encoded like any
X other input value. True EOF is returned after that.
X*/
X
Xstatic int gethuff(ib) /* Returns bytes except for EOF */
XFILE *ib;
X{
X int rbyte; /* Result byte value */
X int need, take; /* numbers of bits */
X
X rbyte = 0;
X need = 8; /* build one byte per call */
X
X /* Loop to build a byte of encoded data.
X Initialization forces read the first time.
X */
X
Xloop:
X if(cbitsrem>=need) /* if current code is big enough */
X { if(need==0)
X return rbyte;
X
X rbyte |= ccode << (8-need); /* take what we need */
X ccode >>= need; /* and leave the rest */
X cbitsrem -= need;
X return rbyte & 0xff;
X }
X
X /* We need more than current code */
X
X if(cbitsrem>0)
X { rbyte |= ccode << (8-need); /* take what there is */
X need -= cbitsrem;
X }
X
X /* No more bits in current code string */
X
X if(curin==SPEOF)
X { /* The end of file token has been encoded. If
X result byte has data return it and do EOF next time.
X */
X
X cbitsrem = 0;
X return (need==8) ? EOF : rbyte + 0;
X }
X
X /* Get an input byte */
X
X if((curin=getc_ncr(ib)) == EOF)
X curin = SPEOF; /* convenient for encoding */
X
X ccode = code[curin]; /* get the new byte's code */
X cbitsrem = codelen[curin];
X
X goto loop;
X}
X
X/* This routine is used to perform the actual squeeze operation. It can
X only be called after the file has been scanned. It returns the true
X length of the squeezed entry.
X*/
X
Xlong file_sq(f,t) /* squeeze a file into an archive */
XFILE *f; /* file to squeeze */
XFILE *t; /* archive to receive file */
X{
X int c; /* one byte of squeezed data */
X long size; /* size after squeezing */
X
X size = wrt_head(t); /* write out the decode tree */
X
X while((c=gethuff(f))!=EOF)
X { putc_pak(c,t);
X size++;
X }
X
X return size; /* report true size */
X}
SHAR_EOFarcsq.c
if test 16237 -ne "`wc -c < 'arcsq.c'`"
then
echo shar: "error transmitting 'arcsq.c'" '(should have been 16237 characters)'
fi
fi
echo shar: "x - 'arcsvc.c'"
if test -f 'arcsvc.c'
then
echo shar: "will not over-write existing file 'arcsvc.c'"
else
sed 's/^X//' << \SHAR_EOFarcsvc.c > 'arcsvc.c'
X/* ARC - Archive utility - ARCSVC
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This file contains service routines needed to maintain an archive.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xopenarc(chg) /* open archive */
Xint chg; /* true to open for changes */
X{
X FILE *fopen(); /* file opener */
X
X if(!(arc=fopen(arcname,"r")))
X { if(chg)
X printf("Creating new archive: %s\n",arcname);
X else abort("Cannot read archive: %s",arcname);
X }
X
X if(chg) /* if opening for changes */
X if(!(new=fopen(newname,"w")))
X abort("Cannot create archive copy: %s",newname);
X}
X
Xclosearc(chg) /* close an archive */
Xint chg; /* true if archive was changed */
X{
X if(arc) /* if we had an initial archive */
X fclose(arc); /* then close it */
X
X if(chg) /* if things have changed */
X {
X#if unix
X fclose(new); /* close the new copy */
X setstamp(newname,arcdate,arctime);/* archive matches newest file */
X#else
X setstamp(new,arcdate,arctime);/* archive matches newest file */
X fclose(new); /* close the new copy */
X#endif
X
X if(arc) /* if we had an original archive */
X { if(keepbak) /* if a backup is wanted */
X { unlink(bakname); /* erase any old copies */
X if(rename(arcname,bakname))
X abort("Cannot rename %s to %s",arcname,bakname);
X printf("Keeping backup archive: %s\n",bakname);
X }
X else if(unlink(arcname))
X abort("Cannot delete old archive: %s",arcname);
X }
X
X if(rename(newname,arcname))
X abort("Cannot rename %s to %s",newname,arcname);
X }
X}
X
X/* CRC computation logic
X
X The logic for this method of calculating the CRC 16 bit polynomial
X is taken from an article by David Schwaderer in the April 1985
X issue of PC Tech Journal.
X*/
X
Xstatic int crctab[] = /* CRC lookup table */
X{ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
X};
Xint addcrc(crc,c) /* update a CRC check */
Xint crc; /* running CRC value */
Xunsigned char c; /* character to add */
X{
X#if unix
X return (0xffff & (((crc>>8)&0x00ff) ^ crctab[(crc^c)&0x00ff]));
X#else
X return ((crc>>8)&0x00ff) ^ crctab[(crc^c)&0x00ff];
X#endif
X}
SHAR_EOFarcsvc.c
if test 4920 -ne "`wc -c < 'arcsvc.c'`"
then
echo shar: "error transmitting 'arcsvc.c'" '(should have been 4920 characters)'
fi
fi
echo shar: "x - 'arctst.c'"
if test -f 'arctst.c'
then
echo shar: "will not over-write existing file 'arctst.c'"
else
sed 's/^X//' << \SHAR_EOFarctst.c > 'arctst.c'
X/* ARC - Archive utility - ARCTST
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This file contains the routines used to test archive integrity.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xtstarc() /* test integrity of an archive */
X{
X struct heads hdr; /* file header */
X long arcsize, ftell(); /* archive size */
X
X openarc(0); /* open archive for reading */
X fseek(arc,0L,2); /* move to end of archive */
X arcsize = ftell(arc); /* see how big it is */
X fseek(arc,0L,0); /* return to top of archive */
X
X while(readhdr(&hdr,arc))
X { if(ftell(arc)+hdr.size>arcsize)
X { printf("Archive truncated in file %s\n",hdr.name);
X nerrs++;
X break;
X }
X
X else
X { printf("Testing file: %-12s ",hdr.name);
X if(unpack(arc,NULL,&hdr))
X nerrs++;
X else printf("okay\n");
X }
X }
X
X if(nerrs<1)
X printf("No errors detected\n");
X else if(nerrs==1)
X printf("One error detected\n");
X else printf("%d errors detected\n",nerrs);
X}
SHAR_EOFarctst.c
if test 1342 -ne "`wc -c < 'arctst.c'`"
then
echo shar: "error transmitting 'arctst.c'" '(should have been 1342 characters)'
fi
fi
echo shar: "x - 'arcunix.c'"
if test -f 'arcunix.c'
then
echo shar: "will not over-write existing file 'arcunix.c'"
else
sed 's/^X//' << \SHAR_EOFarcunix.c > 'arcunix.c'
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/errno.h>
X#include <time.h>
X#include "arc.h"
X
Xchar *index(), *rindex(), *xalloc(), *malloc(), *realloc();
Xextern char *Progname;
Xextern int nerrs;
X
X#if m68000
Xtypedef long int dos_long_t;
Xtypedef short int dos_int_t;
X#define doshdrsize (FNLEN + sizeof(dos_long_t) + sizeof(dos_int_t) + \
X sizeof(dos_int_t) + sizeof(dos_int_t) + sizeof(dos_long_t))
X#define odoshdrsize (doshdrsize - sizeof(dos_long_t))
X#define dos2long(x) ((unsigned char)(x)[0] + ((unsigned char)(x)[1]<<8) + \
X ((unsigned char)(x)[2]<<16) + ((unsigned char)(x)[3]<<24))
X#define dos2int(x) (0xffff & ((unsigned char)(x)[0]+((unsigned char)(x)[1]<<8)))
X#define long2dos(x,l) ((x)[0]=(char)((l)&0xff), (x)[1]=(char)((l)>>8&0xff),\
X (x)[2]=(char)((l)>>16&0xff), (x)[3]=(char)((l)>>24&0xff))
X#define int2dos(x,i) ((x)[0]=(char)((i)&0xff), (x)[1]=(char)((i)>>8&0xff))
X
X/* urdhdr -- read a new-style dos header; munge to unix header */
Xurdhdr(hdr,f)
Xstruct heads *hdr;
XFILE *f;
X{
X _urdhdr(hdr,f,doshdrsize);
X}
X/* urdohdr -- read an old-style dos header; munge to unix header */
Xurdohdr(hdr,f)
Xstruct heads *hdr;
XFILE *f;
X{
X _urdhdr(hdr,f,odoshdrsize);
X}
Xstatic _urdhdr(hdr,f,size)
Xstruct heads *hdr;
XFILE *f;
Xint size;
X{
X char doshdr[doshdrsize];
X char *s = doshdr;
X
X fread(doshdr,size,1,f);
X memcpy(hdr->name,s,sizeof(hdr->name)); s += FNLEN;
X/*printf("\nurdhdr: name=0x%x,'%.12s'0x%x",doshdr,hdr->name,s);*/
X hdr->size = dos2long(s); s += sizeof(dos_long_t);
X/*printf(" size=%ld,0x%x",hdr->size,s);*/
X hdr->date = dos2int(s); s += sizeof(dos_int_t);
X/*printf(" date=%d,0x%x",hdr->date,s);*/
X hdr->time = dos2int(s); s += sizeof(dos_int_t);
X/*printf(" time=%d,0x%x",hdr->time,s);*/
X hdr->crc = dos2int(s); s += sizeof(dos_int_t);
X/*printf(" crc=%d,0x%x",hdr->crc,s);*/
X if(size == doshdrsize) hdr->length = dos2long(s);
X/*if(size == doshdrsize) printf(" length=%d\n",hdr->length);*/
X}
X/* uwrhdr -- write a dos header; munge from unix header */
Xuwrhdr(hdr,f)
Xstruct heads *hdr;
XFILE *f;
X{
X char doshdr[doshdrsize];
X char *s = doshdr;
X
X memcpy(s,hdr->name,FNLEN); s += FNLEN;
X long2dos(s, hdr->size); s += sizeof(dos_long_t);
X int2dos(s, hdr->date); s += sizeof(dos_int_t);
X int2dos(s, hdr->time); s += sizeof(dos_int_t);
X int2dos(s, hdr->crc); s += sizeof(dos_int_t);
X long2dos(s, hdr->length); s += sizeof(dos_long_t);
X fwrite(doshdr,sizeof(doshdr),1,f);
X}
X#endif
X
X/*
X * makefnam -- replace any extension in base with extension in ext, save in buf
X */
Xchar *makefnam(base,ext,buf)
Xchar *base,*ext,*buf;
X{
X char *s;
X strcpy(buf, base);
X if((base = rindex(buf, '/')) == NULL)
X base = buf;
X if((s = index(base,'.')) != NULL) *s = '\0';
X if((s = rindex(ext,'.')) != NULL) strcat(buf,s);
X else {
X strcat(buf,".");strcat(buf,ext);
X }
X return(buf);
X}
X
Xchar *lower(str)
Xchar *str;
X{
X char *s;
X for(s = str; *s; ++s)
X if(isupper(*s)) *s = tolower(*s);
X return(str);
X}
X
Xchar *upper(str)
Xchar *str;
X{
X char *s;
X for(s = str; *s; ++s)
X if(islower(*s)) *s = toupper(*s);
X return(str);
X}
X
X/*
X * kludge; assume we wont run out of memory
X */
Xunsigned coreleft()
X{
X return(5120); /* always enough */
X}
X
X/*
X * dir -- glob pattern, if speced, and repeatedly return matches
X * NOTE: return nulstr, NOT NULL, on no match
X */
Xchar *dir(pattern,mode) /* get files, one by one */
Xchar *pattern; /* template, or NULL */
Xint mode; /* search mode bits */
X{
X static FILE *fp = NULL;
X static char nulstr[] = "";
X static char buf[1025];
X char *s, *fgets();
X extern FILE *popen();
X
X if(fp == NULL && pattern == NULL)
X return(nulstr);
X if (pattern) {
X if(fp) pclose(fp);
X sprintf(buf,"echo %s | tr ' ' '\012'",pattern);
X fp = popen(buf,"r");
X if (fp == NULL)
X abort("dir(): cant glob %s",pattern);
X }
X if(fgets(buf,sizeof(buf),fp) == NULL) {
X pclose(fp);
X fp = NULL;
X return(nulstr);
X }
X if((s = index(buf,'\n')) != NULL) *s = '\0';
X if((s = rindex(buf,'/')) == NULL)
X s = buf;
X else
X ++s;
X if(legalize(s))
X return(nulstr);
X pattern = xalloc(strlen(s)+1);
X strcpy(pattern, s);
X return(pattern);
X}
X
Xstatic legalize(name)
Xchar *name;
X{
X char *dot = index(name,'.');
X if(dot && ((dot-name > 8) || index(dot+1,'.'))) {
X fprintf(stderr,"%s: unix name '%s' not legal as dos name; skipping this pattern\n",Progname,name);
X ++nerrs;
X return(1);
X }
X if((dot && strlen(dot+1) > 3) ||
X (!dot && strlen(name) > 12)) {
Xtruncate:
X fprintf(stderr,"%s: Warning: truncating name '%s' to ",Progname,name);
X if(dot) dot[4] = '\0';
X else name[12] = '\0';
X fprintf(stderr,"'%s'\n",name);
X }
X return(0);
X}
X
Xsetmem(buf,len,c)
Xchar *buf,c;
Xint len;
X{
X while(len--)
X *buf++ = c;
X}
X
Xrename(from, to)
Xchar *from, *to;
X{
X if(link(from, to))
X return(-1);
X return(unlink(from));
X}
X
X/*
X * setstamp -- convert dos time to unix tm and update access, modify times
X */
Xsetstamp(path,date,time) /* set a file's date/time stamp */
Xchar *path; /* file to set stamp on */
Xunsigned int date, time; /* desired date, time */
X{
X extern time_t tm_to_time ();
X struct tm t;
X struct {
X time_t a,m;
X } ut;
X
X int yr = (date >> 9) & 0x7f; /* dissect the date */
X int mo = (date >> 5) & 0x0f;
X int dy = date & 0x1f;
X
X int hr = (time >> 11) & 0x1f; /* dissect the time */
X int mm = (time >> 5) & 0x3f;
X int ss = (time & 0x1f) * 2;
X
X t.tm_year = (yr + 80) % 100;
X t.tm_mon = mo - 1;
X t.tm_mday = dy;
X t.tm_hour = hr;
X t.tm_min = mm;
X t.tm_sec = ss;
X ut.a = ut.m = tm_to_time(&t);
X if(utime(path, &ut)) {
X fprintf(stderr, "%s: cant set utime ",Progname);
X perror(path);
X }
X}
X
X/*
X * setstamp -- get modify time and convert dos time
X */
Xgetstamp(path,date,time) /* get a file's date/time stamp */
Xchar *path; /* file to get stamp from */
Xunsigned int *date, *time; /* storage for the stamp */
X{
X struct stat sbuf;
X if(stat(path, &sbuf)) {
X fprintf(stderr, "%s: cant stat ",Progname);
X perror(path);
X *date = *time = 0;
X }
X else {
X struct tm *localtime();
X struct tm *t = localtime(&sbuf.st_mtime);
X int yr = t->tm_year - 80;
X int mo = t->tm_mon + 1;
X int dy = t->tm_mday;
X int hr = t->tm_hour;
X int mm = t->tm_min;
X int ss = t->tm_sec;
X *date = (yr<<9)+(mo<<5)+dy;
X *time = (hr<<11)+(mm<<5)+ss;
X }
X}
X
X/*
X * xalloc -- malloc with error checking
X */
Xchar *xalloc(n)
Xunsigned n;
X{
X char *s = malloc(n);
X if(s == NULL)
X outofmem();
X return(s);
X}
X
X/*
X * xrealloc -- realloc with error checking
X */
Xchar *xrealloc(s,n)
Xchar *s;
Xunsigned n;
X{
X s = realloc(s,n);
X if(s == NULL)
X outofmem();
X return(s);
X}
Xstatic outofmem()
X{
X Fatal("out of memory",ENOMEM);
X}
Xstatic Fatal(s,code)
Xchar *s;
Xint code;
X{
X fprintf(stderr,"\n%s: fatal error\n%s\n",Progname,s);
X exit(code);
X}
Xabort(a,b,c,d,e)
X{
X char buf[100];
X sprintf(buf,a,b,c,d,e);
X Fatal(buf,1);
X}
SHAR_EOFarcunix.c
if test 6866 -ne "`wc -c < 'arcunix.c'`"
then
echo shar: "error transmitting 'arcunix.c'" '(should have been 6866 characters)'
fi
fi
echo shar: "x - 'arcunp.c'"
if test -f 'arcunp.c'
then
echo shar: "will not over-write existing file 'arcunp.c'"
else
sed 's/^X//' << \SHAR_EOFarcunp.c > 'arcunp.c'
X/* ARC - Archive utility - ARCUNP
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This file contains the routines used to expand a file
X when taking it out of an archive.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
X/* stuff for repeat unpacking */
X
X#define DLE 0x90 /* repeat byte flag */
X
Xstatic int state; /* repeat unpacking state */
X
X/* repeat unpacking states */
X
X#define NOHIST 0 /* no relevant history */
X#define INREP 1 /* sending a repeated value */
X
Xstatic int crcval; /* CRC check value */
Xstatic long size; /* bytes to read */
X
Xint unpack(f,t,hdr) /* unpack an archive entry */
XFILE *f, *t; /* source, destination */
Xstruct heads *hdr; /* pointer to file header data */
X{
X int c; /* one char of stream */
X
X /* setups common to all methods */
X
X crcval = 0; /* reset CRC check value */
X size = hdr->size; /* set input byte counter */
X state = NOHIST; /* initial repeat unpacking state */
X setcode(); /* set up for decoding */
X
X /* use whatever method is appropriate */
X
X switch(hdrver) /* choose proper unpack method */
X {
X case 1: /* standard packing */
X case 2:
X while((c=getc_unp(f))!=EOF)
X putc_unp(c,t);
X break;
X
X case 3: /* non-repeat packing */
X while((c=getc_unp(f))!=EOF)
X putc_ncr(c,t);
X break;
X
X case 4: /* Huffman squeezing */
X init_usq(f);
X while((c=getc_usq(f))!=EOF)
X putc_ncr(c,t);
X break;
X
X case 5: /* Lempel-Zev compression */
X init_ucr(0);
X while((c=getc_ucr(f))!=EOF)
X putc_unp(c,t);
X break;
X
X case 6: /* Lempel-Zev plus non-repeat */
X init_ucr(0);
X while((c=getc_ucr(f))!=EOF)
X putc_ncr(c,t);
X break;
X
X case 7: /* L-Z plus ncr with new hash */
X init_ucr(1);
X while((c=getc_ucr(f))!=EOF)
X putc_ncr(c,t);
X break;
X
X case 8: /* dynamic Lempel-Zev */
X decomp(f,t);
X break;
X
X default: /* unknown method */
X if(warn)
X { printf("I don't know how to unpack file %s\n",hdr->name);
X printf("I think you need a newer version of ARC\n");
X nerrs++;
X }
X fseek(f,hdr->size,1); /* skip over bad file */
X return 1; /* note defective file */
X }
X
X /* cleanups common to all methods */
X
X if(crcval!=hdr->crc)
X { if(warn)
X { printf("WARNING: File %s fails CRC check\n",hdr->name);
X nerrs++;
X }
X return 1; /* note defective file */
X }
X return 0; /* file is okay */
X}
X
X/* This routine is used to put bytes in the output file. It also
X performs various housekeeping functions, such as maintaining the
X CRC check value.
X*/
X
Xstatic putc_unp(c,t) /* output an unpacked byte */
Xchar c; /* byte to output */
XFILE *t; /* file to output to */
X{
X crcval = addcrc(crcval,c); /* update the CRC check value */
X putc_tst(c,t);
X}
X
X/* This routine is used to decode non-repeat compression. Bytes are
X passed one at a time in coded format, and are written out uncoded.
X The data is stored normally, except that runs of more than two
X characters are represented as:
X
X <char> <DLE> <count>
X
X With a special case that a count of zero indicates a DLE as data,
X not as a repeat marker.
X*/
X
Xputc_ncr(c,t) /* put NCR coded bytes */
Xunsigned char c; /* next byte of stream */
XFILE *t; /* file to receive data */
X{
X static int lastc; /* last character seen */
X
X switch(state) /* action depends on our state */
X {
X case NOHIST: /* no previous history */
X if(c==DLE) /* if starting a series */
X state = INREP; /* then remember it next time */
X else putc_unp(lastc=c,t); /* else nothing unusual */
X return;
X
X case INREP: /* in a repeat */
X if(c) /* if count is nonzero */
X while(--c) /* then repeatedly ... */
X putc_unp(lastc,t); /* ... output the byte */
X else putc_unp(DLE,t); /* else output DLE as data */
X state = NOHIST; /* back to no history */
X return;
X
X default:
X abort("Bad NCR unpacking state (%d)",state);
X }
X}
X
X/* This routine provides low-level byte input from an archive. This
X routine MUST be used, as end-of-file is simulated at the end of
X the archive entry.
X*/
X
Xint getc_unp(f) /* get a byte from an archive */
XFILE *f; /* archive file to read */
X{
X if(!size) /* if no data left */
X return EOF; /* then pretend end of file */
X
X size--; /* deduct from input counter */
X return code(fgetc(f)); /* and return next decoded byte */
X}
SHAR_EOFarcunp.c
if test 5857 -ne "`wc -c < 'arcunp.c'`"
then
echo shar: "error transmitting 'arcunp.c'" '(should have been 5857 characters)'
fi
fi
echo shar: "x - 'arcusq.c'"
if test -f 'arcusq.c'
then
echo shar: "will not over-write existing file 'arcusq.c'"
else
sed 's/^X//' << \SHAR_EOFarcusq.c > 'arcusq.c'
X/* ARC - Archive utility - ARCUSQ
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This file contains the routines used to expand a file
X which was packed using Huffman squeezing.
X
X Most of this code is taken from an USQ program by Richard
X Greenlaw, which was adapted to CI-C86 by Robert J. Beilstein.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
X/* stuff for Huffman unsqueezing */
X
X#define ERROR (-1)
X
X#define SPEOF 256 /* special endfile token */
X#define NUMVALS 257 /* 256 data values plus SPEOF */
X
Xextern struct nd /* decoding tree */
X{ int child[2]; /* left, right */
X} node[NUMVALS]; /* use large buffer */
X
Xstatic int bpos; /* last bit position read */
Xstatic int curin; /* last byte value read */
Xstatic int numnodes; /* number of nodes in decode tree */
X
Xstatic int get_int(f) /* get an integer */
XFILE *f; /* file to get it from */
X{
X return getc_unp(f) | (getc_unp(f)<<8);
X}
X
Xinit_usq(f) /* initialize Huffman unsqueezing */
XFILE *f; /* file containing squeezed data */
X{
X int i; /* node index */
X
X bpos = 99; /* force initial read */
X
X numnodes = get_int(f);
X
X if(numnodes<0 || numnodes>=NUMVALS)
X abort("File has an invalid decode tree");
X
X /* initialize for possible empty tree (SPEOF only) */
X
X node[0].child[0] = -(SPEOF + 1);
X node[0].child[1] = -(SPEOF + 1);
X
X for(i=0; i<numnodes; ++i) /* get decoding tree from file */
X { node[i].child[0] = get_int(f);
X node[i].child[1] = get_int(f);
X }
X}
X
Xint getc_usq(f) /* get byte from squeezed file */
XFILE *f; /* file containing squeezed data */
X{
X int i; /* tree index */
X
X /* follow bit stream in tree to a leaf */
X
X for(i=0; i>=0; ) /* work down(up?) from root */
X { if(++bpos>7)
X { if((curin=getc_unp(f)) == ERROR)
X return(ERROR);
X bpos = 0;
X
X /* move a level deeper in tree */
X i = node[i].child[1&curin];
X }
X else i = node[i].child[1 & (curin >>= 1)];
X }
X
X /* decode fake node index to original data value */
X
X i = -(i + 1);
X
X /* decode special endfile token to normal EOF */
X
X i = (i==SPEOF) ? EOF : i;
X return i;
X}
SHAR_EOFarcusq.c
if test 2744 -ne "`wc -c < 'arcusq.c'`"
then
echo shar: "error transmitting 'arcusq.c'" '(should have been 2744 characters)'
fi
fi
echo shar: "x - 'marc.c'"
if test -f 'marc.c'
then
echo shar: "will not over-write existing file 'marc.c'"
else
sed 's/^X//' << \SHAR_EOFmarc.c > 'marc.c'
X#define MAIN
X/* MARC - Archive merge utility
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This program is used to "merge" archives. That is, to move
X files from one archive to another with no data conversion.
X Please refer to the ARC source for a description of archives
X and archive formats.
X
X Instructions:
X Run this program with no arguments for complete instructions.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
XFILE *src; /* source archive */
X
Xchar srcname[STRLEN]; /* source archive name */
X
Xmain(nargs,arg) /* system entry point */
Xint nargs; /* number of arguments */
Xchar *arg[]; /* pointers to arguments */
X{
X char *makefnam(); /* filename fixup routine */
X static char *allf[] = {"*.*"}; /* phony arg to merge all files */
X
X if(nargs<3)
X { printf("MARC - Archive merger, %s\n",VERSION);
X printf("(C) COPYRIGHT 1985 by System Enhancement Associates;");
X printf(" ALL RIGHTS RESERVED\n\n");
X#if 0
X printf("Please refer all inquiries to:\n\n");
X printf(" System Enhancement Associates\n");
X printf(" 21 New Street, Wayne NJ 07470\n\n");
X printf("You may copy and distribute this program freely,");
X printf(" provided that:\n");
X printf(" 1) No fee is charged for such copying and");
X printf(" distribution, and\n");
X printf(" 2) It is distributed ONLY in its original,");
X printf(" unmodified state.\n\n");
X printf("If you like this program, and find it of use, then your");
X printf(" contribution will\n");
X printf("be appreciated. You may not use this product in a");
X printf(" commercial environment\n");
X printf("or a governmental organization without paying a license");
X printf(" fee of $35. Site\n");
X printf("licenses and commercial distribution licenses are");
X printf(" available. A program\n");
X printf("disk and printed documentation are available for $50.\n");
X printf("\nIf you fail to abide by the terms of this license, ");
X printf(" then your conscience\n");
X printf("will haunt you for the rest of your life.\n\n");
X#endif 0
X printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
X printf("Where: <tgtarc> is the archive to add files to,\n");
X printf(" <srcarc> is the archive to get files from, and\n");
X printf(" <filename> is zero or more file names to get.\n");
X return 1;
X }
X
X makefnam(arg[1],".ARC",arcname); /* fix up archive names */
X makefnam(arg[2],".ARC",srcname);
X#if unix
X makefnam(arg[1],".$$$",newname);
X#else
X makefnam(arg[1],".$$$$",newname);
X upper(arcname); upper(srcname); upper(newname);
X#endif
X
X arc = fopen(arcname,"r"); /* open the archives */
X if(!(src=fopen(srcname,"r")))
X abort("Cannot read source archive %s",srcname);
X if(!(new=fopen(newname,"w")))
X abort("Cannot create new archive %s",newname);
X
X if(!arc)
X printf("Creating new archive %s\n",arcname);
X
X if(nargs==3)
X merge(1,allf); /* merge all files */
X else merge(nargs-3,&arg[3]); /* merge selected files */
X
X if(arc) fclose(arc); /* close the archives */
X fclose(src);
X
X#if unix
X fclose(new);
X setstamp(newname,arcdate,arctime); /* new arc matches newest file */
X#else
X setstamp(new,arcdate,arctime); /* new arc matches newest file */
X fclose(new);
X#endif
X
X if(arc) /* make the switch */
X if(unlink(arcname))
X abort("Unable to delete old copy of %s",arcname);
X if(rename(newname,arcname))
X abort("Unable to rename %s to %s",newname,arcname);
X
X return nerrs;
X}
X
Xmerge(nargs,arg) /* merge two archives */
Xint nargs; /* number of filename templates */
Xchar *arg[]; /* pointers to names */
X{
X struct heads srch; /* source archive header */
X struct heads arch; /* target archive header */
X int gotsrc, gotarc; /* archive entry versions (0=end) */
X int copy; /* true to copy file from source */
X int n; /* index */
X
X gotsrc = gethdr(src,&srch); /* get first source file */
X gotarc = gethdr(arc,&arch); /* get first target file */
X
X while(gotsrc || gotarc) /* while more to merge */
X { if(strcmp(srch.name,arch.name)>0)
X { copyfile(arc,&arch,gotarc);
X gotarc = gethdr(arc,&arch);
X }
X
X else if(strcmp(srch.name,arch.name)<0)
X { copy = 0;
X for(n=0; n<nargs; n++)
X { if(match(srch.name,arg[n]))
X { copy = 1;
X break;
X }
X }
X if(copy) /* select source or target */
X { printf("Adding file: %s\n",srch.name);
X copyfile(src,&srch,gotsrc);
X }
X else fseek(src,srch.size,1);
X gotsrc = gethdr(src,&srch);
X }
X
X else /* duplicate names */
X { copy = 0;
X { if((srch.date>arch.date)
X || (srch.date==arch.date && srch.time>arch.time))
X { for(n=0; n<nargs; n++)
X { if(match(srch.name,arg[n]))
X { copy = 1;
X break;
X }
X }
X }
X }
X if(copy) /* select source or target */
X { printf("Updating file: %s\n",srch.name);
X copyfile(src,&srch,gotsrc);
X gotsrc = gethdr(src,&srch);
X if(gotarc)
X { fseek(arc,arch.size,1);
X gotarc = gethdr(arc,&arch);
X }
X }
X else
X { copyfile(arc,&arch,gotarc);
X gotarc = gethdr(arc,&arch);
X if(gotsrc)
X { fseek(src,srch.size,1);
X gotsrc = gethdr(src,&srch);
X }
X }
X }
X }
X
X hdrver = 0; /* end of archive marker */
X writehdr(&arch,new); /* mark the end of the archive */
X}
X
Xint gethdr(f,hdr) /* special read header for merge */
XFILE *f; /* file to read from */
Xstruct heads *hdr; /* storage for header */
X{
X char *i = hdr->name; /* string index */
X int n; /* index */
X
X for(n=0; n<FNLEN; n++) /* fill name field */
X *i++ = 0176; /* impossible high value */
X *--i = '\0'; /* properly end the name */
X
X hdrver = 0; /* reset header version */
X if(readhdr(hdr,f)) /* use normal reading logic */
X return hdrver; /* return the version */
X else return 0; /* or fake end of archive */
X}
X
Xcopyfile(f,hdr,ver) /* copy a file from an archive */
XFILE *f; /* archive to copy from */
Xstruct heads *hdr; /* header data for file */
Xint ver; /* header version */
X{
X hdrver = ver; /* set header version */
X writehdr(hdr,new); /* write out the header */
X filecopy(f,new,hdr->size); /* copy over the data */
X}
SHAR_EOFmarc.c
if test 8058 -ne "`wc -c < 'marc.c'`"
then
echo shar: "error transmitting 'marc.c'" '(should have been 8058 characters)'
fi
fi
echo shar: "x - 'tm_to_time.c'"
if test -f 'tm_to_time.c'
then
echo shar: "will not over-write existing file 'tm_to_time.c'"
else
sed 's/^X//' << \SHAR_EOFtm_to_time.c > 'tm_to_time.c'
X#include <sys/types.h>
X#include <time.h>
X
X/* Return 1 if `y' is a leap year, 0 otherwise.
X */
X
Xstatic int leap (y) int y; {
X y += 1900;
X if (y % 400 == 0)
X return (1);
X if (y % 100 == 0)
X return (0);
X return (y % 4 == 0);
X}
X
X/* Return the number of days between Jan 1, 1970 and the given
X * broken-down time.
X */
X
Xstatic int ndays (p) struct tm *p; {
X register n = p->tm_mday;
X register m, y;
X register char *md = "\37\34\37\36\37\36\37\37\36\37\36\37";
X
X for (y = 70; y < p->tm_year; ++y) {
X n += 365;
X if (leap (y)) ++n;
X }
X for (m = 0; m < p->tm_mon; ++m)
X n += md[m] + (m == 1 && leap (y));
X return (n);
X}
X
X/* Convert a broken-down time (such as returned by localtime())
X * back into a `time_t'.
X */
X
Xtime_t tm_to_time (tp) struct tm *tp; {
X register int m1, m2;
X time_t t;
X struct tm otm;
X
X t = (ndays (tp) - 1) * 86400L + tp->tm_hour * 3600L
X + tp->tm_min * 60 + tp->tm_sec;
X /*
X * Now the hard part -- correct for the time zone:
X */
X otm = *tp;
X tp = localtime (&t);
X m1 = tp->tm_hour * 60 + tp->tm_min;
X m2 = otm.tm_hour * 60 + otm.tm_min;
X t -= ((m1 - m2 + 720 + 1440) % 1440 - 720) * 60L;
X return (t);
X}
SHAR_EOFtm_to_time.c
if test 1188 -ne "`wc -c < 'tm_to_time.c'`"
then
echo shar: "error transmitting 'tm_to_time.c'" '(should have been 1188 characters)'
fi
fi
echo shar: "x - 'xarc.c'"
if test -f 'xarc.c'
then
echo shar: "will not over-write existing file 'xarc.c'"
else
sed 's/^X//' << \SHAR_EOFxarc.c > 'xarc.c'
X#define MAIN
X/* XARC - Archive extraction utility
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X By: Thom Henderson
X
X Description:
X This program is used to extract files from archives which were
X created using the ARC general archive maintenance program.
X Please refer to the ARC source for a description of archives
X and archive formats.
X
X Instructions:
X Run this program with no arguments for complete instructions.
X
X Programming notes:
X This is essentially a stripped down version of ARC, including only
X those routines required to extract files.
X
X Language:
X Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
Xmain(num,arg) /* system entry point */
Xint num; /* number of arguments */
Xchar *arg[]; /* pointers to arguments */
X{
X char *makefnam(); /* filename fixup routine */
X char buf[STRLEN]; /* fixed filename storage */
X char *d, *dir(); /* file directory stuff */
X int nomatch; /* true when no matching archive */
X int n; /* argument index */
X
X if(num<2)
X { printf("XARC - Archive extractor, %s\n",VERSION);
X printf("(C) COPYRIGHT 1985 by System Enhancement Associates;");
X printf(" ALL RIGHTS RESERVED\n\n");
X#if 0
X printf("Please refer all inquiries to:\n\n");
X printf(" System Enhancement Associates\n");
X printf(" 21 New Street, Wayne NJ 07470\n\n");
X printf("You may copy and distribute this program freely,");
X printf(" provided that:\n");
X printf(" 1) No fee is charged for such copying and");
X printf(" distribution, and\n");
X printf(" 2) It is distributed ONLY in its original,");
X printf(" unmodified state.\n\n");
X printf("If you like this program, and find it of use, then your");
X printf(" contribution will\n");
X printf("be appreciated. If you are using this product in a");
X printf(" commercial environment,\n");
X printf("then the contribution is not voluntary.\n\n");
X printf("If you fail to abide by the terms of this license, then");
X printf(" your conscience\n");
X printf("will haunt you for the rest of your life.\n\n");
X#endif
X printf("Usage: XARC <arcname> [<arcname>. . .]\n\n");
X printf("Where <arcname> is the name of an archive.");
X printf(" If no filename extension is\n");
X printf("supplied, then .ARC is assumed.\n");
X return 1;
X }
X
X for(n=1; n<num; n++) /* for each argument */
X { makefnam(arg[n],".ARC",buf);
X nomatch = 1;
X for(d=dir(buf,0); *d; d=dir(NULL,0))
X { makefnam(d,buf,arcname);
X printf("Archive: %s\n",arcname);
X extarc(); /* extract all files */
X free(d);
X nomatch = 0;
X }
X if(nomatch)
X printf("No such archive: %s\n",buf);
X }
X
X return nerrs;
X}
SHAR_EOFxarc.c
if test 3193 -ne "`wc -c < 'xarc.c'`"
then
echo shar: "error transmitting 'xarc.c'" '(should have been 3193 characters)'
fi
fi
exit 0
# End of shell archive
--
Stu Heiss {ihnp4!jpusa1!stu}
More information about the Comp.sources.unix
mailing list