kevin@kosman.UUCP (Kevin O'Gorman) (06/30/87)
I hope this belongs in this newsgroup: it is a source intended to run on a UNIX box, but is in service of Macintosh users. This little program was originally scarfed from usenet as an unmoderated source. It has been improved by making it go through lint a bit better, by making it take more styles of input, by making it more correct, and by adding a man page. There is no makefile because it makes okay with just 'make comb'. The program takes one or more files from mail or usenet postings, trims headers, commentary and signatures, and attempts to rebuild the original BinHex output. I have had good results using it myself. I then Red Ryder the stuff onto my Mac, and BinHex usually works just fine. ...ihnp4 ---\ Kevin O'Gorman ...allegra --- philabs!hhb --- kosman!kevin Anarm Software Systems ...decvax --/ 17 Wierimus Lane Voice: (201) 666-1734 Hillsdale, NJ 07642 --- #! /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: # comb.1 # comb.c # This archive created: Sun May 3 08:58:51 1987 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'comb.1'" '(1208 characters)' if test -f 'comb.1' then echo shar: "will not over-write existing file 'comb.1'" else sed 's/^X//' << \SHAR_EOF > 'comb.1' X.TH COMB 1 X.SH NAME Xcomb \- combine and trim BinHex files X.SH SYNOPSIS X.B "comb [-m] [-q] filename [filename]..." X.SH DESCRIPTION XA hex file (output of the BinHex program) is rebuilt from inputs that may have Xmail headers, English text, signatures, and other stuff that needs to be Xremoved to restore the original file. The file may have been split into Xhunks for transmission, in which case there is by default one hunk per file. XWith the \fB-m\fR flag, the hunks have been combined in a single "mail" file, Xfrom which headers and other additions must be trimmed. X.PP XThe resulting BinHex file is sent to the standard output. Lines which are Xremoved are output on standard error unless the \fB-q\fR flag is used. X.SH DIAGNOSTICS XExit code 0 is returned on success, 1 for error in the inputs, and 2 for Xan error on the command line. XMessages are intended to be self-explanatory. X.SH BUGS XThe code assumes it can determine what is hex code by checking for a few XEnglish words and any white space. Lines with neither are taken to begin Xa hex hunk, and the hunk continues as long as the lines stay the same Xlength. X.PP XThere is no checking of the contents of the line, and the checksums are not Xexamined. X SHAR_EOF if test 1208 -ne "`wc -c < 'comb.1'`" then echo shar: "error transmitting 'comb.1'" '(should have been 1208 characters)' fi fi echo shar: "extracting 'comb.c'" '(9267 characters)' if test -f 'comb.c' then echo shar: "will not over-write existing file 'comb.c'" else sed 's/^X//' << \SHAR_EOF > 'comb.c' X/* comb - prepare binhex files from usenet or mail X X Modified by Kevin O'Gorman to clean it up a bit and to make it work Xcorrectly on a single input file (just to trim the trash and check for Xtermination), and on those rare cases where the last line is the same Xlength as all the others (i.e. the final ':' is the 64th char of a line). X X Also made it a bit cleaner: no gotos, no longer assume (FILE *) is the Xsame cast as (char *), lint complaints are minimal, tests the number of Xarguments more closely. X X There is one preprocessor flag, DEBUG. If this is defined, you get Xmore verbose output than normal, showing what comb thinks it's doing at Xvarious points. With ksh, I can use X CFLAGS=-DEBUG make comb Xor X make comb Xdepending on what I want. X X Original comments follow: X X*/ X/* X comb - combine split binhex files X usage: X comb file1 .. fileN > result ; xbin result X comb -m file > result ; xbin result X compile: cc -o comb comb.c X X binhex files often come across the net split into multiple parts. I Xgot sick of re-combining them by hand. comb is a quick hack that takes Xas its arguments a set of files which are the parts Xof a binhex file. It splits out the binhex file to standard output. XIf the parts have been combined into a single file already, with mail Xheaders and such in between, the "-m" flag can be used. The text that Xdoesn't look like binhex goes to standard output, unless the "-q" (for Xquiet) flag is specified. X It's real ugly (even has gotos!), but hey, it works. X Author: Greg Dudek X Usenet: {linus, ihnp4, allegra, decvax, floyd}!utcsri!dudek X*/ X X#include <stdio.h> X#define min(a,b) (a<b?a:b) X#define index strchr X#ifdef DEBUG X#define EBUG X#endif X X#ifdef EBUG X#define debug(x) x X#else X#define debug(x) /**/ X#endif X Xint verbose=1; Xint mailfile = 0; /* file contains multiple parts */ Xint gotend = 0; /* found apparent end of binhex data */ Xint eof = 0; /* found at least 1 eof (only used if mailfile) */ Xextern int substr(); /* defined later */ X Xmain(argc,argv) Xchar **argv; X{ X int l,i,fnum, curline; X char inline[256]; X char inline2[256]; X FILE *fd; X X if (argc <= 1) { X fprintf(stderr,"Usage: %s [-q] [-m] file1 [..fileN]\n",argv[0]); X exit(2); X } X X fnum=1; X /* get flags */ X while (argv[fnum][0]=='-' && (argc > 1)) { X switch (argv[fnum][1]) { X case 'm': X mailfile=1; X break; X case 'q': X verbose=0; X break; X case 'v': X verbose=1; X break; X default: X fprintf(stderr,"Unknown option -%c ignored\n",argv[fnum][1]); X break; X } X fnum++; X argc--; X } X X if (argc <= 1) { X fprintf(stderr,"Cannot find a file in the arguments.\n"); X exit(3); X } X if (mailfile && argc != 2) { X fprintf(stderr, X "Mail option -m only works with one file; others ignored.\n"); X argc = 2; X } X X fd = (FILE *) NULL; /* kludgey flag saying need to open a file */ X inline[0] = '\0'; /* kludgey flag saying have not seen any hex */ X X /* loop here once per file (or if -m, per hunk ) */ X for ( ; (mailfile && !eof) || (argc > 1); ) { X X /* make sure the right file is open */ X if (fd == (FILE *) NULL || !mailfile) { /* first time, or !-m */ X if (fd == (FILE *) NULL) fd = fopen(argv[fnum],"r"); X else fd = freopen(argv[fnum++],"r",fd); X if (fd==(FILE *)NULL) { X perror(argv[fnum]); X exit(3); X } X argc--; X fnum++; X }; X X /* find the beginning of a hunk: the rules depend on whether this is X the first one or not. X */ X if (inline[0] == '\0') { X /* rules for the first hunk are easiest */ X for ( ;; ) { X if (fgets(inline,80,fd) == NULL) { X fprintf(stderr,"No hunk in the first file at all.\n"); X perror(argv[fnum - 1]); X exit(3); X } X if (strncmp(inline,"(This file",10)==0) { X printf("%s",inline); /* send the "This file..." line */ X X /* send the blank line */ X if (fgets(inline,80,fd) == NULL) { X perror(argv[fnum - 1]); X exit(3); X } X printf("%s",inline); X X /* send the first "real" line, assume it's full length */ X if (fgets(inline,80,fd) == NULL) { X perror(argv[fnum - 1]); X exit(3); X } X printf("%s",inline); X X l = strlen(inline); /* record what "full length" means */ X break; /* leave the loop with setup done */ X } X else { X if (verbose) fprintf(stderr,"%s",inline); /* continue */ X } X } X } X else { X /* rules for finding later hunks involve some guesses */ X X X /* only consider first 500 lines of each file for data start */ X for (curline=1; curline<500; curline++){ X if (fgets(inline,90,fd)==NULL) { X debug(printf("eof (argc=%d)\n",argc)); X eof = 1; X break; X } X X /* is the line the right length? */ X if (strlen(inline)!=l) { X if (verbose) fprintf(stderr,"%s",inline); X debug(printf("Bad length %d != %d\n",strlen(inline),l)); X continue; X } X X /* we don't expect binhex to contain these lines, just in case X we fluked out on line length X */ X if ((substr(inline,"here")) || X (substr(inline,"From")) || X (substr(inline,"CUT")) || X (substr(inline,"end")) || X (substr(inline,"Path")) || X (substr(inline,"cut")) ) { X if (verbose) fprintf(stderr,"%s",inline); X debug(printf("Has English\n")); X continue; X } X X /* we also don't expect white-space in any line */ X if ((substr(inline," ")) || X (substr(inline,"\t")) ) { X if (verbose) fprintf(stderr,"%s",inline); X debug(printf("Has White Space\n")); X continue; X } X X /* get another line, see if lengths match */ X if (fgets(inline2,80,fd)==NULL) { X fprintf(stderr,"%s",inline); X eof = 1; X break; X } X /* check it for the keywords too */ X if ((strlen(inline)==strlen(inline2)) && X ( ! ( (substr(inline2,"here")) || X (substr(inline2,"From")) || X (substr(inline2,"CUT")) || X (substr(inline2,"end")) || X (substr(inline2,"Path")) || X (substr(inline2,"cut")) || X (substr(inline2," ")) || X (substr(inline2,"\t")) ))) { X X /* Okay, we're convinced */ X /* spit the 2 lines */ X printf("%s",inline); X strcpy(inline,inline2); X break; X } X else { X fprintf(stderr,"%s",inline); X fprintf(stderr,"%s",inline2); X debug(printf("Second line is bad\n")); X } X } /* end of 500-line scan */ X if (curline >= 500) { X debug(printf(stderr,"Over 500 lines and no hunk found.\n")); X eof = 1; /* a slight misnomer, but is gets us out */ X } X } /* end of looking for a hunk (if/else) */ X /* at this point, one of the following cases should be true: X eof is set -- ran off the end of the current file X inline contains the next valid line of hex data X */ X X /* Take any more lines of the right length */ X for ( ; ; ) { X if (fgets(inline,80,fd)==NULL) { X eof = 1; X break; X } X i = strlen(inline); X while (inline[i-1]=='\n') i--; X if (inline[i-1]==':') { X gotend = 1; /* end of stuff */ X printf("%s",inline); X break; X } X if (strlen(inline)!=l) { X fprintf(stderr,"%s",inline); X break; X } X else printf("%s",inline); X } /* done replicating lines; 'inline' contains the short one */ X X if (gotend) break; X X if (!mailfile) { X /* throw away rest of file */ X while (verbose && (fgets(inline,80,fd) != NULL)) { X fprintf(stderr,"%s",inline); X } X } X } /* end of hunk loop. exit with gotend, please. */ X X while (verbose & (fgets(inline,80,fd) != NULL)) { X fprintf(stderr,"%s",inline); X } X X if (argc != 1) { X fprintf(stderr,"Ended before the last file: %d left.\n",argc-1); X exit(1); X } X X if (!gotend) { X fprintf(stderr,"File didn't seem to end properly\n"); X exit(1); X } X X exit(0); X /*NOTREACHED*/ X } X Xint Xsubstr(s,t) Xchar *s, *t; X{ X extern char *index(); X while ((s=index(s,*t))!=0) { X if (strncmp(s,t,(min(strlen(s),strlen(t))))==0) return(1); X s++; X } X return(0); X } SHAR_EOF if test 9267 -ne "`wc -c < 'comb.c'`" then echo shar: "error transmitting 'comb.c'" '(should have been 9267 characters)' fi fi exit 0 # End of shell archive ---