[net.sources.mac] utility for split up binhex files : comb

dudek@utai.UUCP (12/18/86)

/*
    comb - combine split binhex files
    usage:
	comb file1 .. fileN > result ; xbin result
	comb -m file > result ; xbin result
    compile: cc -o comb comb.c

    binhex files often come across the net split into multiple parts.  I
got sick of re-combining them by hand.  comb is a quick hack that takes 
as its arguments a set of files which are the parts
of a binhex file.  It splits out the binhex file to standard output.
If the parts have been combined into a single file already, with mail
headers and such in between, the "-m" flag can be used.  The text that
doesn't look like binhex goes to standard output, unless the "-q" (for
quiet) flag is specified.
    It's real ugly (even has gotos!), but hey, it works.
    Author: Greg Dudek
    Usenet:	{linus, ihnp4, allegra, decvax, floyd}!utcsri!dudek
*/

#include <stdio.h>
#define min(a,b)	(a<b?a:b)

#ifdef DEBUG
#define EBUG
#endif

#ifdef EBUG
#define debug(x)	x
#else
#define debug(x)	/**/
#endif

int verbose=1;
int mailfile = 0;	/* file contains multiple parts */
int gotend = 0;		/* found apparent end of binhex data */
int eof = 0;		/* found at least 1 eof (only used if mailfile) */

main(argc,argv)
char **argv;
{
    int l,i,fnum, curline;
    char inline[256];
    char inline2[256];
    FILE *fd;

    if (argc <= 1) {
	fprintf(stderr,"Usage: %s [-q] [-m] file1 [..fileN]\n",argv[0]);
	exit(2);
	}

    fnum=1;
    /* get flags */
    while (argv[fnum][0]=='-') {
        switch (argv[fnum][1]) {
        case 'm':
            mailfile=1;
            break;
        case 'q':
            verbose=0;
            break;
        case 'v':
            verbose=1;
            break;
        default:
            fprintf(stderr,"Unknown option -%c ignored\n",argv[fnum][1]);
            break;
            }
        fnum++;
        }

    fd = fopen(argv[fnum],"r"); 
    if (fd==0) {
	perror(argv[fnum]);
	exit(3);
	}
    argc--;
    fnum++;
    for ( ;; ) {
        if (fgets(inline,80,fd)<=0) break;
        if (strncmp(inline,"(This file",10)==0) {
            printf("%s",inline);

            fgets(inline,80,fd);
            printf("%s",inline);

            fgets(inline,80,fd);
            printf("%s",inline);
            l = strlen(inline);
            for ( ; (fgets(inline,80,fd)>0) && (strlen(inline)==l); ) 
                printf("%s",inline);
            break;
            }
        else {
            if (verbose) fprintf(stderr,"%s",inline);
            }
        }
    if (!mailfile) {
        /* throw away rest of file */
        while (verbose && (fgets(inline,80,fd)>0)) {
            fprintf(stderr,"%s",inline);
            }
        }

    for ( ; (mailfile && !eof) || (argc-->1);  ) {
        if (!mailfile) fd = freopen(argv[fnum++],"r",fd);

	/* hack, hack.  jump here when in mailfile mode */
	/* instead of opening a new file		*/
fakenew:
        /* only consider first 500 lines of each file for data start */
        for (curline=1;curline<500;curline++) {
            if (fgets(inline,90,fd)<=0) {
                debug(printf("eof (argc=%d)\n",argc));
                eof = 1;
                break;
                }

	/* jump here if we already read 2 lines thinking the first was
	   the start of the binhex data, but that hypothesis failed.
	   We make the extra line look like we just read it, & jump here.
	*/
got1:

	    /* is the line the right length? */
            if (strlen(inline)!=l) {
                if (verbose) fprintf(stderr,"%s",inline);
                debug(printf("Bad length %d != %d\n",strlen(inline),l));
                continue;
                }

	    /* we don't expect binhex to contain these lines, just in case
		we fluked out on line length 
	    */
            if ((substr(inline,"here"))  ||
                (substr(inline,"From")) ||
                (substr(inline,"CUT")) ||
                (substr(inline,"end")) ||
                (substr(inline,"Path")) ||
                (substr(inline,"cut")) ) {
                if (verbose) fprintf(stderr,"%s",inline);
                debug(printf("Has English\n"));
                continue;
                }

            /* get another line, see if lengths match */
            if (fgets(inline2,80,fd)<=0) {
                eof = 1;
                break;
                }
	    /* check it for the keywords too */
            if ((strlen(inline)==strlen(inline2)) &&
                ( ! ((substr(inline2,"here"))  ||
                (substr(inline2,"From")) ||
                (substr(inline2,"CUT")) ||
                (substr(inline2,"end")) ||
                (substr(inline2,"Path")) ||
                (substr(inline2,"cut")) ))) {

                /* Okay, we're convinced 	*/
		/* spit the 2 lines		*/
                printf("%s",inline);
                printf("%s",inline2);
		/* Take any more lines of the right length */
                for ( ; ; ) {
                    if (fgets(inline,80,fd)<=0) {
                        eof = 1;
                        break;
                        }
                    if (strlen(inline)!=l) {
                        i = strlen(inline);
                        while (inline[i-1]=='\n') i--;
                        if (inline[i-1]==':') {
                            /* end of stuff */
                            gotend = 1;
                            printf("%s",inline);
                            }
                        break;
                        }
                    printf("%s",inline);
                    }
                }
            else {
                debug(printf("Second line is bad\n"));
                strcpy(inline,inline2);
                goto got1;
                }
            break;
            }
        if (mailfile && !eof) goto fakenew;
        while (verbose & (fgets(inline,80,fd)>0)) {
            fprintf(stderr,"%s",inline);
            }
        }
    if (!gotend) {
	fprintf(stderr,"File didn't seem to end properly\n");
	exit(1);
	}
    exit(0);
    }

substr(s,t)
char *s, *t;
{
    extern char *index();
    while ((s=index(s,*t))!=0) {
        if (strncmp(s,t,(min(strlen(s),strlen(t))))==0) return(1);
        s++;
        }
    return(0);
    }
-- 
	    Dept. of Computer Science (vision group)    University of Toronto
	    Usenet:	{linus, ihnp4, allegra, decvax, floyd}!utcsri!dudek
	    CSNET:	dudek@ai.toronto.edu
	    ARPA:	dudek%ai.toronto.edu@csnet-relay
	    DELPHI:     GDUDEK
	    Paper mail: 10 King's College Circle, Toronto, Canada