stu@jpusa1.UUCP (Stu Heiss) (09/30/86)
#! /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}