[comp.sys.mac] bhcomb.c

straka@ihlpf.UUCP (02/17/87)

A while ago, some code was posted which stripped out file header info from
netnews Mac binaries, leaving a clean, downloadable file suitable for
BinHex.  The author admitted that it was a bit of a hack, as it "even
used gotos".

I took a fresh look at the problem, and came up with the following code.
It is rather simple, but given simple stdin, stdout, stderr, and one
BinHex file per invocation, it seems pretty robust.  (and NO gotos!)

A typical invocation might look like:

	bhcomb <camera[1-5].net >camera 2>camera.doc || echo ^G bhcomb Failed!

It was developed under SYS V.2.  Use it in good health.

Please excuse me if this doesn't really belong in unmoderated comp.sys.mac.
(It isn't that big.)

Rich Straka     ihnp4!ihlpf!straka

------------------------------cut here ---8<----8<----8<------------------
/*	bhcomb.c: combine and strip header information from BinHexed files.
	assumes the following structure:

	several lines of unrelated header
	(This file must be converted by BinHex 4.0)
	:123456789012345678901234567890123456789012345678901234567890123
	1234567890123456789012345678901234567890123456789012345678901234
	.
	.
	.
	1234567890123456789012345678901234567890123456789012345678901234
	1234...4321:
	several lines of unrelated footer

	Additional unrelated headers and/or footers may be present
	within the data stream.
	The actual data is prepended with "(This file... BinHex 4.0)"
	   and an extra blank line.
	The actual data begins with a framing ":" (not checked)
	The actual data must end with a framing ":"
	All data lines (except the last) are of the same length (default=64).
	The last data line is of random length, and ends with the ":".
	Certain characters are never seen within the BinHex portion:
		nothing < \012
		nothing > \012, yet < \040
		no spaces
		no . / ; < = > ? O g n o s t u v w x y z { } characters
		no | ~ \ ] ^ _ characters
		nothing > \176

	Data is gathered through stdin.
	Good data is sent to stdout.
	Bad data and diagnostics are sent to stderr.

	A shell line (or procedure) of the following form is recommednded:
	  bhcomb <camera[1-5].net >camera 2>camera.doc || echo ^G bhcomb Failed!

	BUGS:
		More than one BinHexed file per invocation ignores all
		  but the first file.
		Does not check for additional ":"s inside of the valid
		  portion of the data.
*/

#include <stdio.h>
#include <string.h>
#define	LENGTH	64			/* LENGTH = default BinHex line
					     length = 64
					*/
main(argc,argv)
{
int valid=0, started=0, lth;
					/* started = "we have started
					     collecting valid BinHex data"
					   valid = "the last line encountered
					     was a valid BinHex line"
					   lth = line length
					*/
char inline[256];
while (gets (inline) >0)
	{
	if (strncmp (inline,"(This file must be converted with BinHex 4.0)",45)==0)
		{
		if (started != 0)	/* Have we already started? */
					/* If so, something is wrong! */
			{
			started=0;	/* Unused hook for multiple files */
			fprintf(stderr,"%s\n",inline);		  /* Print it */
			fprintf(stderr,"More than one BinHex file!");  /*ERROR*/
			exit (1);
			}
		else
			{
			printf("%s\n",inline);
			gets (inline);		/* read dummy blank line */
			printf("\n");		/* put out dummy blank line */
			valid=1;		/* This line of data is valid */
			started=1;		/* We started data gathering
			*/
			}
		}
	else
		{
		lth=strlen (inline);
		if (badchars (inline,lth) != 0)	/* Do we have illegal chars? */
			{
			fprintf(stderr,"%s\n",inline);	/* Put to stderr */
			valid=0;			/* Line not valid */
			}
		else
			{				/* All chars OK */
			if (strlen (inline) != LENGTH)	/* if bad line length */
				{
				if (valid!=1)	/*not expecting last line with :*/
					{
					fprintf(stderr,"%s\n",inline); /*bad line*/
					valid=0;	/* Line not valid */
					}
				else			/*expecting last line with : */
					{
					if (findcolon (inline) == 0)
					/* if colon at end of line */
						{
						printf("%s\n",inline); /* last line */
						started=2;	/* FINISHED */
						exit (0);    /* NORMAL EXIT */
						}
					else
						{
						fprintf(stderr,"%s\n",inline);
						valid=0;	/* bad line */
						}
					}
				}
			else
				{
				printf("%s\n",inline);		/* Good line */
				valid=1;
				}
			}
		}
	}
fprintf(stderr,"Improper EOF; no ending colon!\n");  /* should never get here */
exit (2);
}

badchars(lptr,length)			/* Look for illegal characters */
char *lptr;
int length;
{
int badchar, p;
char c;
c='a';
badchar=0;
for (p=0;p<length;p++)
	{
	c=lptr[p];
	if (c < '\n')            {badchar=1; break;}
	if (c > '\n' && c < '!') {badchar=1; break;}
	if (c > '-' && c < 0)    {badchar=1; break;}
	if (c > ':' && c < '@')  {badchar=1; break;}
	if (c == 'O')            {badchar=1; break;}
	if (c > '[' && c < '`')  {badchar=1; break;}
	if (c == 'g')            {badchar=1; break;}
	if (c > 'n' && c < 'o')  {badchar=1; break;}
	if (c >  's')            {badchar=1; break;}
	}
return (badchar);
}

findcolon(lptr)			/* Look for : at end of line */
char *lptr;
{
int p;
p=strlen(lptr);
while (lptr[p--]=='\n') ;	/* get rid of all possible trailing \n_s */
if (lptr[p]==':')
	{
	return (0);
	}
else
	{
	return (1);
	}
}
------------------------------cut here ---8<----8<----8<------------------
-- 
Rich Straka     ihnp4!ihlpf!straka