twb@rolex.UUCP (Tom Bereiter) (12/07/88)
[StuffIt Utility for UN*X] After seeing several requests for a version of Stuffit for UN*X I thought I'd post the following: --- #! /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 the files: # README # Makefile # sit.h # sit.c # updcrc.c # macbinfilt.c # This archive created: Tue Dec 6 07:45:06 1988 # By: Roger L. Long (bytebug@dhw68k.cts.com) # export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(1209 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' XThis shar file contains the source to "sit" a UNIX utility which produces XStuffit archives for downloading to the mac. As a bonus I've also included X"macbinfilt", a filter which takes articles from comp.binaries.mac, puts the Xparts in the correct order, and throws out all the "noise" lines. X XTo use the sit code you need the getopt(3) library routine and the compress(1) Xutility, both of which most everyone seems to have by now. X XThere is not much original code here: everything is reverse engineered from Xthe unsit utility by Alan Weber. The updcrc.c file is exactly the same file Xfrom the unsit package. X XI've tested the code on both BSD and SYSV machines. Both machines were big Xendian so byte order problems may still be lurking. X XWhen you transfer archives to your mac be sure to use "binary" mode. In Xorder for Suffit to recognize your downloaded file it must have a type of X"SIT!". If your communication program doesn't allow you to specify the type Xyou'll need to ResEdit it in. It should be quite simple to modify sit.c Xto put a MacBinary header on the archive. X XAs with everything in the modern world: use at your own risk. X X--Tom Bereiter X ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb SHAR_EOF if test 1209 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 1209 characters)' fi fi # end of overwriting check echo shar: extracting "'Makefile'" '(67 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' Xall: sit macbinfilt X Xsit: sit.o updcrc.o X cc -o sit sit.o updcrc.o SHAR_EOF if test 67 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 67 characters)' fi fi # end of overwriting check echo shar: extracting "'sit.h'" '(1834 characters)' if test -f 'sit.h' then echo shar: will not over-write existing file "'sit.h'" else sed 's/^X//' << \SHAR_EOF > 'sit.h' X X/* sit.h: contains declarations for SIT headers */ X Xtypedef struct sitHdr { /* 22 bytes */ X u_char sig1[4]; /* = 'SIT!' -- for verification */ X u_char numFiles[2]; /* number of files in archive */ X u_char arcLen[4]; /* length of entire archive incl. */ X u_char sig2[4]; /* = 'rLau' -- for verification */ X u_char version; /* version number */ X char reserved[7]; X}; X Xtypedef struct fileHdr { /* 112 bytes */ X u_char compRMethod; /* rsrc fork compression method */ X u_char compDMethod; /* data fork compression method */ X u_char fName[64]; /* a STR63 */ X char fType[4]; /* file type */ X char fCreator[4]; /* creator... */ X char FndrFlags[2]; /* copy of Finder flags */ X char cDate[4]; /* creation date */ X char mDate[4]; /* !restored-compat w/backup prgms */ X u_char rLen[4]; /* decom rsrc length */ X u_char dLen[4]; /* decomp data length */ X u_char cRLen[4]; /* compressed lengths */ X u_char cDLen[4]; X u_char rsrcCRC[2]; /* crc of rsrc fork */ X u_char dataCRC[2]; /* crc of data fork */ X char reserved[6]; X u_char hdrCRC[2]; /* crc of file header */ X}; X X/* file format is: X sitArchiveHdr X file1Hdr X file1RsrcFork X file1DataFork X file2Hdr X file2RsrcFork X file2DataFork X . X . X . X fileNHdr X fileNRsrcFork X fileNDataFork X*/ X X X X/* compression methods */ X#define noComp 0 /* just read each byte and write it to archive */ X#define repComp 1 /* RLE compression */ X#define lpzComp 2 /* LZW compression */ X#define hufComp 3 /* Huffman compression */ X X/* all other numbers are reserved */ X X/* X * the format of a *.info file made by xbin X */ Xstruct infohdr { X char res0; X char name[64]; /* 2 (a str 63) */ X char type[4]; /* 65 */ X char creator[4]; /* 69 */ X char flag[2]; /* 73 */ X char res1[8]; X char dlen[4]; /* 83 */ X char rlen[4]; /* 87 */ X char ctime[4]; /* 91 */ X char mtime[4]; /* 95 */ X}; SHAR_EOF if test 1834 -ne "`wc -c < 'sit.h'`" then echo shar: error transmitting "'sit.h'" '(should have been 1834 characters)' fi fi # end of overwriting check echo shar: extracting "'sit.c'" '(6063 characters)' if test -f 'sit.c' then echo shar: will not over-write existing file "'sit.c'" else sed 's/^X//' << \SHAR_EOF > 'sit.c' X/* X * sit - Stuffit for UNIX X * Puts unix data files into stuffit archive suitable for downloading X * to a Mac. Automatically processes files output from xbin. X * X * Reverse engineered from unsit by Allan G. Weber, which was based on X * macput, which was based on ... X * Just like unsit this uses the host's version of compress to do the work. X * X * Examples: X * 1) take collection of UNIX text files and make them LSC text files X * when uncompressed on the mac: X * sit -u -T TEXT -C KAHL file ... X * 2) Process output from xbin: X * xbin file1 (produces FileOne.{info,rsrc,data}) X * sit file1 X * X * Tom Bereiter X * ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb X */ X#define BSD X X#include <sys/types.h> X#include <sys/stat.h> X#include <stdio.h> X#include "sit.h" X#ifdef BSD X#include <sys/time.h> X#include <sys/timeb.h> X#else X#include <time.h> Xextern long timezone; X#endif X X#ifndef min X#define min(a,b) ((a)<(b)?(a):(b)) X#endif X X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */ X#define TIMEDIFF 0x7c25b080 X Xstruct sitHdr sh; Xstruct fileHdr fh; X Xchar buf[BUFSIZ]; Xchar *defoutfile = "archive.sit"; Xint ofd; Xushort crc; Xint clen; Xint rmfiles; Xint unixf; Xchar *Creator, *Type; X Xusage() { fprintf(stderr,"Usage: sit file\n"); } Xextern char *optarg; Xextern int optind; X Xmain(argc,argv) char **argv; { X int i,n; X int total, nfiles; X int c; X X while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF) X switch (c) { X case 'r': X rmfiles++; /* remove files when done */ X break; X case 'o': /* specify output file */ X defoutfile = optarg; X break; X case 'u': /* unix file -- change '\n' to '\r' */ X unixf++; X break; X case 'C': /* set Mac creator */ X Creator = optarg; X break; X case 'T': /* set Mac file type */ X Type = optarg; X break; X case '?': X usage(); X exit(1); X } X X if ((ofd=creat(defoutfile,0644))<0) { X perror(defoutfile); X exit(1); X } X /* empty header, will seek back and fill in later */ X write(ofd,&sh,sizeof sh); X X for (i=optind; i<argc; i++) { X n = put_file(argv[i]); X if (n) { X total += n; X nfiles++; X } X } X lseek(ofd,0,0); X X total += sizeof(sh); X /* header header */ X strncpy(sh.sig1,"SIT!",4); X cp2(nfiles,sh.numFiles); X cp4(total,sh.arcLen); X strncpy(sh.sig2,"rLau",4); X sh.version = 1; X X write(ofd,&sh,sizeof sh); X} X Xput_file(name) Xchar name[]; X{ X struct stat st; X struct infohdr ih; X int i,n,fd; X long fpos1, fpos2; X char nbuf[256], *p; X int fork=0; X long tdiff; X struct tm *tp; X#ifdef BSD X struct timeb tbuf; X#else X long bs; X#endif X X fpos1 = lseek(ofd,0,1); /* remember where we are */ X /* write empty header, will seek back and fill in later */ X bzero(&fh,sizeof fh); X write(ofd,&fh,sizeof fh); X X /* look for resource fork */ X strcpy(nbuf,name); X strcat(nbuf,".rsrc"); X if (stat(nbuf,&st)>=0 && st.st_size) { /* resource fork exists */ X dofork(nbuf); X cp4(st.st_size,fh.rLen); X cp4(clen,fh.cRLen); X cp2(crc,fh.rsrcCRC); X fh.compRMethod = lpzComp; X fork++; X } X if (rmfiles) unlink(nbuf); /* ignore errors */ X X /* look for data fork */ X st.st_size = 0; X strcpy(nbuf,name); X if (stat(nbuf,&st)<0) { /* first try plain name */ X strcat(nbuf,".data"); X stat(nbuf,&st); X } X if (st.st_size) { /* data fork exists */ X dofork(nbuf); X cp4(st.st_size,fh.dLen); X cp4(clen,fh.cDLen); X cp2(crc,fh.dataCRC); X fh.compDMethod = lpzComp; X fork++; X } X if (fork == 0) { X fprintf(stderr,"%s: no data or resource files\n",name); X return 0; X } X if (rmfiles) unlink(nbuf); /* ignore errors */ X X /* look for .info file */ X strcpy(nbuf,name); X strcat(nbuf,".info"); X if ((fd=open(nbuf,0))>=0 && read(fd,&ih,sizeof(ih))==sizeof(ih)) { X strncpy(fh.fName, ih.name,64); X strncpy(fh.fType, ih.type, 4); X strncpy(fh.fCreator, ih.creator, 4); X strncpy(fh.FndrFlags, ih.flag, 2); X strncpy(fh.cDate, ih.ctime, 4); X strncpy(fh.mDate, ih.mtime, 4); X } X else { /* no info file so fake it */ X strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63); X /* default to LSC text file */ X strncpy(fh.fType, Type ? Type : "TEXT", 4); X strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4); X /* convert unix file time to mac time format */ X#ifdef BSD X ftime(&tbuf); X tp = localtime(&tbuf.time); X tdiff = TIMEDIFF - tbuf.timezone * 60; X if (tp->tm_isdst) X tdiff += 60 * 60; X#else X /* I hope this is right! -andy */ X time(&bs); X tp = localtime(&bs); X tdiff = TIMEDIFF - timezone; X if (tp->tm_isdst) X tdiff += 60 * 60; X#endif X cp4(st.st_ctime + tdiff, fh.cDate); X cp4(st.st_mtime + tdiff, fh.mDate); X } X close(fd); X if (rmfiles) unlink(nbuf); /* ignore errors */ X X crc = updcrc(0,&fh,(sizeof fh)-2); X cp2(crc, fh.hdrCRC); X X fpos2 = lseek(ofd,0,1); /* remember where we are */ X lseek(ofd,fpos1,0); /* seek back over file(s) and header */ X write(ofd,&fh,sizeof fh); /* write back header */ X fpos2=lseek(ofd,fpos2,0); /* seek forward file */ X X return (fpos2 - fpos1); X} X Xdofork(name) Xchar name[]; X{ X FILE *fs; X int n, fd, ufd; X char *p; X X if ((fd=open(name,0))<0) { X perror(name); X return 0; X } X if (unixf) /* build conversion file */ X if ((ufd=creat("sit+temp",0644))<0) { X perror("sit+temp"); X return 0; X } X /* do crc of file: */ X crc = 0; X while ((n=read(fd,buf,BUFSIZ))>0) { X if (unixf) { /* convert '\n' to '\r' */ X for (p=buf; p<&buf[n]; p++) X if (*p == '\n') *p = '\r'; X write(ufd,buf,n); X } X crc = updcrc(crc,buf,n); X } X close(fd); X /* X * open pipe to compress file X * If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy X * with the conversion done. Otherwise, 'sit+temp' is just a link to X * the input file. X */ X if (unixf) X close(ufd); X else link(name,"sit+temp"); X fs = popen("compress -c -n -b 14 sit+temp","r"); X if (fs == NULL) { X perror(name); X return 0; X } X /* write out compressed file */ X clen = 0; X while ((n=fread(buf,1,BUFSIZ,fs))>0) { X write(ofd,buf,n); X clen += n; X } X pclose(fs); X unlink("sit+temp"); X} X Xcp2(x,dest) Xunsigned short x; Xchar dest[]; X{ X dest[0] = x>>8; X dest[1] = x; X} X Xcp4(x,dest) Xunsigned long x; Xchar dest[]; X{ X dest[0] = x>>24; X dest[1] = x>>16; X dest[2] = x>>8; X dest[3] = x; X} SHAR_EOF if test 6063 -ne "`wc -c < 'sit.c'`" then echo shar: error transmitting "'sit.c'" '(should have been 6063 characters)' fi fi # end of overwriting check echo shar: extracting "'updcrc.c'" '(5848 characters)' if test -f 'updcrc.c' then echo shar: will not over-write existing file "'updcrc.c'" else sed 's/^X//' << \SHAR_EOF > 'updcrc.c' X/* updcrc(3), crc(1) - calculate crc polynomials X * X * Calculate, intelligently, the CRC of a dataset incrementally given a X * buffer full at a time. X * X * Usage: X * newcrc = updcrc( oldcrc, bufadr, buflen ) X * unsigned int oldcrc, buflen; X * char *bufadr; X * X * Compiling with -DTEST creates a program to print the CRC of stdin to stdout. X * Compile with -DMAKETAB to print values for crctab to stdout. If you change X * the CRC polynomial parameters, be sure to do this and change X * crctab's initial value. X * X * Notes: X * Regards the data stream as an integer whose MSB is the MSB of the first X * byte recieved. This number is 'divided' (using xor instead of subtraction) X * by the crc-polynomial P. X * XMODEM does things a little differently, essentially treating the LSB of X * the first data byte as the MSB of the integer. Define SWAPPED to make X * things behave in this manner. X * X * Author: Mark G. Mendel, 7/86 X * UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm X */ X X/* The CRC polynomial. X * These 4 values define the crc-polynomial. X * If you change them, you must change crctab[]'s initial value to what is X * printed by initcrctab() [see 'compile with -DMAKETAB' above]. X */ X /* Value used by: CITT XMODEM ARC */ X#define P 0xA001 /* the poly: 0x1021 0x1021 A001 */ X#define INIT_CRC 0L /* init value: -1 0 0 */ X#define SWAPPED /* bit order: undef defined defined */ X#define W 16 /* bits in CRC:16 16 16 */ X X /* data type that holds a W-bit unsigned integer */ X#if W <= 16 X# define WTYPE unsigned short X#else X# define WTYPE unsigned long X#endif X X /* the number of bits per char: don't change it. */ X#define B 8 X Xstatic WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ { X0x0, 0xc0c1, 0xc181, 0x140, 0xc301, 0x3c0, 0x280, 0xc241, X0xc601, 0x6c0, 0x780, 0xc741, 0x500, 0xc5c1, 0xc481, 0x440, X0xcc01, 0xcc0, 0xd80, 0xcd41, 0xf00, 0xcfc1, 0xce81, 0xe40, X0xa00, 0xcac1, 0xcb81, 0xb40, 0xc901, 0x9c0, 0x880, 0xc841, X0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, X0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, X0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, X0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, X0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, X0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, X0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, X0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, X0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, X0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, X0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, X0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, X0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, X0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, X0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, X0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, X0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, X0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, X0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, X0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, X0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, X0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, X0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, X0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, X0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, X0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, X0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, X0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, X} ; X XWTYPE Xupdcrc( icrc, icp, icnt ) X WTYPE icrc; X unsigned char *icp; X int icnt; X{ X register WTYPE crc = icrc; X register unsigned char *cp = icp; X register int cnt = icnt; X X while( cnt-- ) { X#ifndef SWAPPED X crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++]; X#else X crc = (crc>>B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++]; X#endif SWAPPED X } X X return( crc ); X} X X#ifdef MAKETAB X X#include <stdio.h> Xmain() X{ X initcrctab(); X} X Xinitcrctab() X{ X register int b, i; X WTYPE v; X X X for( b = 0; b <= (1<<B)-1; ++b ) { X#ifndef SWAPPED X for( v = b<<(W-B), i = B; --i >= 0; ) X v = v & ((WTYPE)1<<(W-1)) ? (v<<1)^P : v<<1; X#else X for( v = b, i = B; --i >= 0; ) X v = v & 1 ? (v>>1)^P : v>>1; X#endif X crctab[b] = v; X X printf( "0x%lx,", v & ((1L<<W)-1L)); X if( (b&7) == 7 ) X printf("\n" ); X else X printf(" "); X } X} X#endif X X#ifdef TEST X X#include <stdio.h> X#include <fcntl.h> X X#define MAXBUF 4096 X X X Xmain( ac, av ) X int ac; char **av; X{ X int fd; X int nr; X int i; X char buf[MAXBUF]; X WTYPE crc, crc2; X X fd = 0; X if( ac > 1 ) X if( (fd = open( av[1], O_RDONLY )) < 0 ) { X perror( av[1] ); X exit( -1 ); X } X crc = crc2 = INIT_CRC; X X while( (nr = read( fd, buf, MAXBUF )) > 0 ) { X crc = updcrc( crc, buf, nr ); X } X X if( nr != 0 ) X perror( "reading" ); X else { X printf( "%lx\n", crc ); X } X X#ifdef MAGICCHECK X /* tack one's complement of crc onto data stream, and X continue crc calculation. Should get a constant (magic number) X dependent only on P, not the data. X */ X crc2 = crc ^ -1L; X for( nr = W-B; nr >= 0; nr -= B ) { X buf[0] = (crc2 >> nr); X crc = updcrc(crc, buf, 1); X } X X /* crc should now equal magic */ X buf[0] = buf[1] = buf[2] = buf[3] = 0; X printf( "magic test: %lx =?= %lx\n", crc, updcrc(-1, buf, W/B)); X#endif MAGICCHECK X} X X#endif SHAR_EOF if test 5848 -ne "`wc -c < 'updcrc.c'`" then echo shar: error transmitting "'updcrc.c'" '(should have been 5848 characters)' fi fi # end of overwriting check echo shar: extracting "'macbinfilt.c'" '(3638 characters)' if test -f 'macbinfilt.c' then echo shar: will not over-write existing file "'macbinfilt.c'" else sed 's/^X//' << \SHAR_EOF > 'macbinfilt.c' X/* X * macbinfilt -- filters usenet articles from comp.binaries.mac into a form X * suitable for xbin to decode. Will rearange parts of file if they are not X * in order. Strips out all extraneous lines. X * Does all of this by making many bold assumtions--but it's worked so far. X * X * Only works on one article at a time. All files on the input line are X * considered parts of the same article. X * X * If you have the sysV regualar expression routines (regcmp, regex) then X * define HAVE_REGCMP for a more robust pattern match. X * X * --Tom Bereiter X * ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb X */ X#include <stdio.h> X Xint cur_part,part,divert_part; Xint max_part; X#define IBUFSZ 512 Xchar ibuf[IBUFSZ]; Xchar pname[80]; XFILE *ofs=stdout; XFILE *saveofs; XFILE *parts[100]; X X#ifdef HAVE_REGCMP X#define EXP ".*[Pp][Aa][Rr][Tt][ \t]*([0-9]+)$0[ \t]*[Oo][Ff][ \t]*([0-9]+)$1" X#else X#define EXP "part %d of %d" X#endif Xchar *exp; X Xmain(argc,argv) char **argv[]; { X FILE *fs; X int i,rc=0; X X#ifdef HAVE_REGCMP X exp = (char *)regcmp(EXP,0); X#else X exp = EXP; X#endif X X fputs("(This file must be converted with BinHex 4.0)\n\n",ofs); X X if (argc == 1) X filter(stdin); X else while (--argc) { X if ((fs=fopen(*++argv,"r"))==NULL) { X perror(*argv); exit(-1); } X filter(fs); X fclose(fs); X } X /* add any remaining parts */ X for (i=cur_part+1; i<=max_part; i++) X if (parts[i]) X putpart(i); X else { X fprintf(stderr,"Missing part %d\n",i); X rc = -1; X } X exit(rc); X} X X/* valid xbin chars + '\n' and '\r' */ X#define Btst(i) (bmap[i>>3] & (1<<(i&07))) Xchar bmap[]={0x00,0x24,0x00,0x00,0xfe,0x3f,0x7f,0x07, X 0xff,0x7f,0x7f,0x0f,0x7f,0x3f,0x07,0x00}; X X/* filter out extraneous lines and look for lines of the form: X * part n of m X * A line is considered valid if it has only valid xbin characters and is X * either greater than 60 characters or ends in a ':' X */ X Xfilter(fs) FILE *fs; { X register char *p,*inp; X Xreget: X while ((inp=fgets(ibuf,IBUFSZ,fs))) { X for (p=inp; *p; p++) X if (Btst(*p) == 0) { /* invalid character */ X checkparts(inp); X goto reget; X } X if (p-inp > 60 || inp[(p-inp)-2]==':') /* arbitrary max or end */ X fputs(ibuf,ofs); X } X if (divert_part) /* diversion in progress */ X end_oseq(); X} X Xcheckparts(str) char *str; { X char *p; X char num0[40], num1[40]; X X#ifdef HAVE_REGEXP X if (regex(exp, str, num0,num1)!=NULL) { X part = atoi(num0); X max_part = atoi(num1); Xfprintf(stderr,"part %d of %d\n",part,max_part); X dopart(); X } X#else X for (p=str; *p; p++) /* rescan for 'part' string */ X if (*p==exp[0]) X if (sscanf(p,exp,&part,&max_part) == 2) { X dopart(); X break; X } X#endif X} X Xdopart() { X if (divert_part) { /* diversion in progress */ X if (part == divert_part) /* another mention of current part */ X return; X end_oseq(); X } X if (part == cur_part+1) /* OK: next in sequence */ X cur_part = part; X else if (part > cur_part) /* out of sequence */ X oseq(); X else /* "can't" happen */ X fprintf(stderr,"Part %d unexpected\n",part); X} X X/* part out of sequence */ Xoseq() { X int i; X X /* try and fill in gap */ X for (i=cur_part+1; i<part; i++) X if (parts[i]) { X putpart(i); X cur_part = i; X } X else goto isgap; X /* all missing parts restored -- continue */ X return; Xisgap: X /* start diversion */ X divert_part = part; X saveofs = ofs; X sprintf(pname,"part%d",part); X if ((ofs = fopen(pname,"w+")) == NULL) { X perror(pname); exit(-1); } X parts[part] = ofs; X} Xend_oseq() { X divert_part = 0; X ofs = saveofs; X} X Xputpart(n) { X FILE *fs; X register int c; X X fs = parts[n]; X rewind(fs); X while ((c=getc(fs))!=EOF) X putc(c,ofs); X fclose(fs); X sprintf(pname,"part%d",n); X unlink(pname); X} SHAR_EOF if test 3638 -ne "`wc -c < 'macbinfilt.c'`" then echo shar: error transmitting "'macbinfilt.c'" '(should have been 3638 characters)' fi fi # end of overwriting check # End of shell archive exit 0 ---