[comp.binaries.apple2] SCIIBIN: a binscii extracter in C

marcel@duteca (Marcel Mol) (05/17/89)

Here is a C program that views and extracts BINSCII files.
When viewing, it shows file names and attributes and which
part of how many parts the BINSCII file is.
It handles multiple file names on the command line, and
each file may contain several BINSCII files, so you
can directely feed the news articles to the program.

- Marcel


=========== CUT HERE ====================================
/* @(#) sciibin.c       1.0 03/03/89  */
/*************************************************************************
 **                                                                     **
 **  Name    :  sciibin                                                 **
 **  Author  :  Marcel J.E. Mol                                         **
 **  Date    :  06/03/89              (first release)                   **
 **  Version :  1.00                                                    **
 **  Files   :  sciibin.c       Main source file                        **
 **                                                                     **
 **  ------------------------- Revision List -------------------------  **
 **  Ver   Date       Name                   Remarks                    **
 **  1.00  06/03/89   Marcel Mol             First release              **
 **  1.10  27/03/89   Marcel Mol             Fished things up, error    **
 **                                          routine, linecount,        **
 **                                          all info fields filled in, **
 **                                          changed info layout.       **
 **  =================================================================  **
 **                                                                     **
 **  Compile as follows: cc cc sciibin.c -Oso sciibin                   **
 **                                                                     **
 **  Usage: sciibin [-hvtc] [-o<outputfile>] <infiles>                  **
 **                                                                     **
 **           -v show only info on file, do not create output.          **
 **           -t test file, do not create output.                       **
 **           -c do not check checksums.                                **
 **           -o create given filename instead of the one in            **
 **              binscii file. Use this only if the input files         **
 **              contain only one output file.                          **
 **           -h help.                                                  **
 **                                                                     **
 **                                                                     **
 **    Defining DEBUG gives some debug information.                     **
 **    Defining DEBUGALL gives input and output of the decode           **
 **    routine.                                                         **
 **                                                                     **
 **   This software is freeware. I can not be held responsible to       **
 **   any damage this program may coase you or anyone or anything else. **
 **                                                                     **
 ************************************************************************/


#include <stdio.h>
#include <sys/stat.h>

#define BUFLEN 256

/*
 * Global variables
 */
char buf[BUFLEN+1];
unsigned char dec[BUFLEN+1];
char alfabet[BUFLEN+1];
char outfilename[BUFLEN+1];

int outflag = 0;                /* the -o option                    */
int crcflag = 0;                /* the -c option                    */
int infoflag = 0;               /* the -v option                    */
int testflag = 0;               /* the -t option                    */
int makeoutput;                 /* ! (-t | -v)                      */
int crcok;                      /* -t | -c                          */
FILE *outfp;                    /* output file                      */

int namlen, filetype, numblocks; 
long filesize, startbyte, segmentlen;
int modyear, modmonth, modday, modhour, modmin;
int creyear, cremonth, creday, crehour, cremin;
int auxtype, stortype, access;
char * infilename;
int linecount;

char * progname;


/*
 * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
 *  NOTE: First srgument must be in range 0 to 255.
 *        Second argument is referenced twice.
 * 
 * Programmers may incorporate any or all code into their programs, 
 * giving proper credit within the source. Publication of the 
 * source routines is permitted so long as proper credit is given 
 * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, 
 * Omen Technology.
 */

 /* #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp) */
#define updcrc(cp, crc) ( (crctab[((crc >> 8) & 0xFF) ^ cp] ^ (crc << 8)) & 0xFFFF)


/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
static unsigned short crctab[256] = {
    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
};

char * filetypes[] = {
	"$00", "bad", "pcd", "ptx", "txt", "pda", "bin", "fnt",
	"fot", "ba3", "da3", "wpf", "sos", "$0D", "$0E", "dir",
	"rpd", "rpi", "$12", "$13", "$14", "$15", "$16", "$17",
	"$18", "adb", "awp", "asp", "$1C", "$1D", "$1E", "$1F",
	"$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27",
	"$28", "$29", "$2A", "$2B", "$2C", "$2D", "$2E", "$2F",
	"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37",
	"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F",
	"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
	"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F",
	"$50", "$51", "$52", "$53", "$54", "$55", "$56", "$57",
	"$58", "$59", "$5A", "$5B", "$5C", "$5D", "$5E", "$5F",
	"$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67",
	"$68", "$69", "$6A", "$6B", "$6C", "$6D", "$6E", "$6F",
	"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77",
	"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F",
	"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
	"$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F",
	"$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97",
	"$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F",
	"$A0", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7",
	"$A8", "$A9", "$AA", "$AB", "$AC", "$AD", "$AE", "$AF",
	"src", "obj", "lib", "s16", "rtl", "exe", "str", "tsf",
	"nda", "cda", "tol", "drv", "$BC", "$BD", "$BE", "doc",
	"pnt", "pic", "$C2", "$C3", "$C4", "$C5", "$C6", "$C7",
	"fon", "$C9", "$CA", "$CB", "$CC", "$CD", "$CE", "$CF",
	"$D0", "$D1", "$D2", "$D3", "$D4", "$D5", "$D6", "$D7",
	"$D8", "$D9", "$DA", "$DB", "$DC", "$DD", "$DE", "$DF",
	"$E0", "$E1", "$E2", "$E3", "$E4", "$E5", "$E6", "$E7",
	"$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "$EE", "pas",
	"cmd", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7",
	"$F8", "p16", "int", "ivr", "bas", "var", "rel", "sys",
    };

/*
ProDOS Filetypes

Num	Name	OS	Meaning
========================================================================
$00			typeless
$01	BAD	both	BAD blocks file
$02	PCD	SOS	Pascal CoDe file
$03	PTX	SOS	Pascal TeXt file
$04	TXT	both	ASCII text file
$05	PDA	SOS	Pascal DAta file
$06	BIN	both	BINary file
$07	CHR	SOS	CHaRacter font file
$08	PIC	both	PICture file
$09	BA3	SOS	Business BASIC (SOS) program file
$0A	DA3	SOS	Business BASIC (SOS) data file
$0B	WPD	SOS	Word Processor Document
$0C		SOS	SOS system file
$0D		SOS	SOS reserved file type
$0E		SOS	SOS reserved file type
$0F	DIR	Both	subDIRectory file
$10	RPD	SOS	RPS data file
$11	RPI	SOS	RPS index file
$12		SOS	Applefile diskcard file
$13		SOS	Applefile model file
$14		SOS	Applefile report format file
$15		SOS	Screen library file
$16		SOS	SOS reserved file type
$17		SOS	SOS reserved file type
$18		SOS	SOS reserved file type
$19	ADB	ProDOS	AppleWorks Database file
$1A	AWP	ProDOS	AppleWorks WordProcessing file
$1B	ASP	ProDOS	AppleWorks Spreadsheet file
$1C-$5F			Reserved
$60-$6F		ProDOS	PC Transporter (Applied Engineering) reserved filetypes
 $60	PRE	ProDOS	ProDOS preboot driver
 $61-$6A	ProDOS	Reserved
 $6B	NIO	ProDOS	PC Transporter BIOS and drivers
 $6C		ProDOS	Reserved
 $6D	DVR	ProDOS	PC Transporter device drivers
 $6E		ProDOS	Reserved
 $6F	HDV	ProDOS	MSDOS HardDisk Volume
$70-$9F			Reserved
$A0	WPF	ProDOS	WordPerfect document file
$A1	MAC	ProDOS	Macrofile
$A2	HLP	ProDOS	Help File
$A3	DAT	ProDOS	Data File
$A4			Reserved
$A5	LEX	ProDOS	Spelling dictionary
$A6-$AB			Reserved
$AC	ARC	ProDOS	General Purpose Archive file
$AD-$AF			Reserved
$B0	SRC	ProDOS	ORCA/M & APW source file
$B1	OBJ	ProDOS	ORCA/M & APW object file
$B2	LIB	ProDOS	ORCA/M & APW library file
$B3	S16	ProDOS	ProDOS16 system file
$B4	RTL	ProDOS	ProDOS16 runtime library
$B5	EXE	ProDOS	APW shell command file
$B6	STR	ProDOS	ProDOS16 startup init file
$B7	TSF	ProDOS	ProDOS16 temporary init file
$B8	NDA	ProDOS	ProDOS16 new desk accessory
$B9	CDA	ProDOS	ProDOS16 classic desk accessory
$BA	TOL	ProDOS	ProDOS16 toolset file
$BB	DRV	ProDOS	ProDOS16 driver file
$BC-$BE			Reserved for ProDOS16 load file
$BF	DOC	ProDOS	document file
$C0	PNT	ProDOS	//gs paint document
$C1	SCR	ProDOS	//gs screen file
$C2-$C7			Reserved
$C8	FNT	ProDOS	Printer font file
$C9		ProDOS	finder files
$CA		ProDOS	finder icons
$CB-$DF			Reserved
$E0	LBR	ProDOS	Apple archive library file
$E1			Unknown (unlisted)
$E2	ATI	ProDOS	Appletalk init file
$E3-$EE			Reserved
$EF	PAS	ProDOS	ProDOS Pascal file
$F0	CMD	ProDOS	added command file
$F1-$F8		ProDOS	User defined filetypes (popular ones include:)
 $F1	OVL	ProDOS	Overlay file
 $F2	DBF	ProDOS	Database file
 $F3	PAD	ProDOS	MouseWrite file
 $F4	MCR	ProDOS	AE Pro macro file
 $F5	ECP	ProDOS	ECP batch file
 $F6	DSC	ProDOS	description file
 $F7	TMP	ProDOS	temporary work file
 $F8	RSX	ProDOS	linkable object module
$F9	IMG	ProDOS	ProDOS image file
$FA	INT	ProDOS	Integer BASIC program
$FB	IVR	ProDOS	Integer BASIC variables file
$FC	BAS	ProDOS	AppleSoft BASIC program
$FD	VAR	ProDOS	AppleSoft BASIC variables file
$FE	REL	ProDOS	ProDOS EDASM relocatable object module file
$FF	SYS	ProDOS	ProDOS8 system file
*/


/*
 * function declarations
 */
sciibin();
getheader();
decode();
decodestring();
char *myfgets();
void usage();
void error();


char * copyright = "@(#) sciibin.c  1.1 27/03/89  (c) M.J.E. Mol";

main(argc, argv)
int argc;
char **argv;
{
    FILE *fp;
    int c;
    extern int optind;			/* For getopt */
    extern char * optarg;		/* For getopt */
    int  flag;				/* Flag for getopt */

    progname = *argv;

    while ((flag = getopt(argc, argv, "hvcto:")) != EOF) { /* Process options */
        switch (flag) {
            case 'v': infoflag = 1;	/* Want only info of file */
                      break;
            case 'h': usage();		/* Give help */
                      exit(0);
            case 'c': crcflag = 1;
                      break;
            case 't': testflag = 1;
                      break;
            case 'o': strcpy(outfilename, optarg);
                      outflag = 1;
                      break;
            default : fprintf(stderr, "%s: skipping unkown flag %c, use -h.\n",
                                    progname, flag);
                      break;
        }
    }

    makeoutput = !(testflag | infoflag);
    crcok = testflag | crcflag;
#if defined(DEBUG)
    fprintf(stderr, "make output: %d, crcok: %d\n", makeoutput, crcok);
#endif

    if (optind >= argc) {		/* No files given, use stdin */
        infilename = "stdin";
        linecount = 0;
        sciibin(stdin);
    }
    else
        while (optind < argc) {
            infilename = argv[optind];
            optind++;
            if ((fp = fopen(infilename, "r")) == NULL) {
                perror(infilename);
                continue;
            }
            linecount = 0;
            sciibin(fp);
            fclose(fp);
        }

    exit(0);

} /* main */



/*
 * Walk over the file processing all segments in it
 */
sciibin(fp)
FILE *fp;
{
    int processed = 0;          /* number of processed binscii segments     */
    int status = 0;             /* return codes of calls to decode          */

    while (myfgets(buf, BUFLEN, fp) != NULL) {
#if defined(DEBUG)
        fprintf(stderr, "(%s) get start:%s", infilename, buf);
#endif
        if (!strcmp(buf, "FiLeStArTfIlEsTaRt\n")) {
            if (!getheader(fp) && !infoflag) /* if header ok and not -v flag */
                status |= decode(fp);
            processed++;
        }
    }

    if (processed == 0) {
        error("not a binscii file");
        return 1;
    }

    return status;

} /* sciibin */



/*
 * Build the alfabet, get the output file info and open output file
 * if necessary.
 * Still contains lots of debug code to find out the header structure.
 *   (every bit is known now...)
 */
getheader(fp)
FILE *fp;
{
    register int i, j;
    register int crc = 0;
    struct stat statbuf;            /* must know if file exists         */
    char *iomod;                    /* write or readwrite a file        */

    /*
     * Get the alfabet
     */
    if (myfgets(buf, BUFLEN, fp) == NULL) {
        error("reading alfabet: unexpected end of file");
        return 1;
    }
#if defined(DEBUG)
    fprintf(stderr, "(%s) alfabet:%s", infilename, buf);
#endif
    if (strlen(buf) != 65) {
        error("alfabet corrupted");
        return 1;
    }

    /*
     * Process the alfabet
     */
    for (i = 0; i < BUFLEN; i++)
        alfabet[i] = 0xff;
    for (i = 0; i < 64; i++) {
        j = buf[i];
        if (alfabet[j] != 0xff)
            error("Warning: double character in alfabet");
        alfabet[j] = i;
    }
#if defined(DEBUG)
    for (i = 0; i < BUFLEN; i+=16) {
        fprintf(stderr, "(%s) alfabet[%3d] =", infilename, i);
        for (j = 0; j < 16; j++)
            fprintf(stderr, " %02X", alfabet[i+j]);
        putc('\n', stderr);
    }
#endif

    /*
     * Get the file header
     */
    if (myfgets(buf, BUFLEN, fp) == NULL) {
        error("reading fileheader: unexpected end of file");
        return 1;
    }
#if defined(DEBUG)
    fprintf(stderr, "(%s) fileheader:%s", infilename, buf);
#endif

    /*
     * Strip output filename if needed
     */
    if (!outflag) {
        namlen = *buf - 'A' + 1; /* IS +1 NEEDED ?? */
        strncpy(outfilename, buf+1, namlen);
    }
#if defined(DEBUG)
    fprintf(stderr, "(%s) filename:**%s**\n", infilename, outfilename);
    fprintf(stderr, "(%s) fileinfo:**%s**", infilename, buf+16);
#endif

    /*
     * Decode and process the file header information
     */
    if ((i = decodestring(buf+16, dec)) != 27)
        error("warning: corrupted file header length");
    for (i = 0; i < 24; i++) 
        crc = updcrc(dec[i], crc);
    if (crc != (dec[24] | (dec[25] << 8))) {
        if (crcok) 
            error("warning: CRC error in file header");
        else {
            error("error: CRC error in file header");
            return 1;
        }
    }
    filesize   = dec[0] + (dec[1]<<8) + (dec[2]<<16);/* Calculate file length */
    startbyte  = dec[3] + (dec[4]<<8) + (dec[5]<<16);
    access     = dec[6];
    filetype   = dec[7];
    auxtype    = dec[8] + (dec[9] << 8);
    stortype   = dec[10];
    numblocks  = dec[11] + (dec[12]<<8);
#define CRE 13          /* perhaps creation and modification date are swapped */
    creday     = dec[CRE] & 0x1f;
    cremonth   = ((dec[CRE+1] & 0x01) << 3) | (dec[CRE] >> 5);
    creyear    = dec[CRE+1] >>1;
    cremin     = dec[CRE+2] & 0x3f;
    crehour    = dec[CRE+3] & 0x1f;
#define MOD CRE+4
    modday     = dec[MOD] & 0x1f;
    modmonth   = ((dec[MOD+1] & 0x01) << 3) | (dec[MOD] >> 5);
    modyear    = dec[MOD+1] >>1;
    modmin     = dec[MOD+2] & 0x3f;
    modhour    = dec[MOD+3] & 0x1f;
    segmentlen = dec[21] + (dec[22]<<8) + (dec[23]<<16);

#define READ    0x01
#define WRITE   0x02
#define BACKUP  0x20
#define RENAME  0x40
#define DESTROY 0x80

    if (infoflag) {
        printf("%-15s  %3s aux: %04X ",
                   outfilename, filetypes[filetype], auxtype);
        putchar(access & READ    ? 'r' : '-');
        putchar(access & WRITE   ? 'w' : '-');
        putchar(access & RENAME  ? 'n' : '-');
        putchar(access & DESTROY ? 'd' : '-');
        putchar(access & BACKUP  ? 'b' : '-');
        switch (stortype) {
            case 0x0F : printf(" voldir"); break;
            case 0x0D : printf(" dir"); break;
            case 0x01 : printf(" seed"); break;
            case 0x02 : printf(" sap"); break;
            case 0x03 : printf(" tree"); break;
            default   : printf(" ???"); break;
        }
        printf(" %02d/%02d/%02d(%02d:%02d) -", modyear, modmonth, modday,
                                               modhour, modmin);
        printf(" %02d/%02d/%02d(%02d:%02d)\n", creyear, cremonth, creday,
                                               crehour, cremin);
        printf("Part %4d of %4d,", startbyte / 0x3000 + 1,
                                   (filesize + 0x2FFF) / 0x3000);
        printf(" bytes %7d to %7d of %7d bytes, %5d blocks\n",
                startbyte, startbyte+segmentlen, filesize, numblocks);
    }

    if (makeoutput) {
        iomod = (stat(outfilename, &statbuf) == 0) ? "r+" : "w"; 
        if ((outfp = fopen(outfilename, iomod)) == NULL) {
            error("unable to open output file");
            perror(outfilename);
            return 1;
        }
        fseek(outfp, startbyte, 0);
    }

    return 0;

} /* getheader */



/*
 * Do the actual decoding of the bin data.
 */
decode(fp)
FILE *fp;
{
    register int i;
    register int crc = 0;
    int len;

    crc = 0;
    while (segmentlen > 0) {     
        if (myfgets(buf, BUFLEN, fp) == NULL) {
            error("reading file: unexpected end of file");
            return 1;
        }
#if defined(DEBUG)
        fprintf(stderr, "(%s) data:%s", infilename, buf);
#endif
        if ((len = decodestring(buf, dec)) != 48)
            error("warning: corrupted line length");
        for (i = 0; i < 48; i++)
            crc = updcrc(dec[i], crc);
        if (makeoutput)
            for (i = 0; (i < len) && (segmentlen > 0); i++, segmentlen--)
                putc(dec[i], outfp);        /* COULD CR/NL TXT FILES */
        else
            segmentlen -= len;
#if defined(DEBUG)
        fprintf(stderr, "(%s) still need %d bytes\n", infilename, segmentlen);
#endif
    }

    /*
     * must be at end of segment now, with one remaining line containing
     * the crc check.
     */

    if (myfgets(buf, BUFLEN, fp) == NULL) {
        error("reading file crc: unexpected end of file");
        return 1;
    }
#if defined(DEBUG)
    fprintf(stderr, "(%s) crc:%s", infilename, buf);
#endif
    if ((len = decodestring(buf, dec)) != 3)
       error("warning: corrupted crc length");
    if (crc != (dec[0] | (dec[1] << 8))) {
        if (crcok)  
            error("warning: CRC error in file data");
        else {
            error("error: CRC error in file data");
            return 1;
        }
    }

    fclose(outfp);

    return 0;

} /* decode */


/*
 * Decode one string off scii characters to binary data, meanwhile
 * calculating crc.
 */
decodestring(in, out)
register char *in;
register unsigned char *out;
{
    register int len = 0;

#if defined(DEBUGALL)
    char *b;

    fprintf(stderr, "(%s) decode in: %s\n", infilename, in);
    b = in;
    while (*b) fprintf(stderr, ".%02X", alfabet[*b++]);
    putc('\n', stderr);
    b = out;
#endif
    while (strlen(in) > 3) {
        *out++ = ((alfabet[in[3]] << 2) | (alfabet[in[2]] >> 4)) & 0xFF;
        *out++ = ((alfabet[in[2]] << 4) | (alfabet[in[1]] >> 2)) & 0xFF;
        *out++ = ((alfabet[in[1]] << 6) | (alfabet[in[0]]))      & 0xFF;
        len += 3;
        in += 4;
    }
    *out = '\0';
    if (*in != '\0' && *in != '\n') 
        error("warning: line not ended by NULL or NEWLINE");
#if defined(DEBUGALL)
    fprintf(stderr, "(%s) decode out:\n", infilename);
    while (b != out) 
        fprintf(stderr, ".%02X", *b++);
    putc('\n', stderr);
#endif

    return len;

} /* decodestring */



char *myfgets(buf, len, fp)
char *buf;
int len;
FILE *fp;
{

    linecount++;
    return fgets(buf, len, fp);

} /* myfgets */



void usage()
{

    fprintf(stderr, "Usage: sciibin [-vtc] [-o<outputfile>] <infiles>\n\n");
    fprintf(stderr, "       -v show only info on file, do not create output.\n");
    fprintf(stderr, "       -t test file, do not create output.\n");
    fprintf(stderr, "       -c do not check checksums.\n");
    fprintf(stderr, "       -o create given filename instead of the one in\n");
    fprintf(stderr, "          binscii file. Use this only if the input files\n");
    fprintf(stderr, "          contain only one output file.\n");
    fprintf(stderr, "       -h this help message.\n");

} /* usage */



void error(str)
char *str;
{

    fprintf(stderr, "%s (%s, %d): %s\n", 
                    progname, infilename, linecount, str);

} /* error */
-- 
#########################################
# Marcel J.E. Mol                       # They hate you if your're clever
# Delft, University of Technology       # And they despise the fool
# The Netherlands                       # Till you're so fucking crazy
# UUCP: marcel@duteca.UUCP              # You can't follow the rules.
#       duteca!marcel                  	#
#########################################			 - Lennon

friedman@porthos.rutgers.edu (Gadi ) (05/17/89)

Thanks for the program, enclosed are fixes to get it to compiled
on our Sun4.  The 2 problems were some missing definitions,
and that chars can't store 0xff.

These are ed commands from diff:

NNNc means change line NNN to the Text
NNNa means add the text at line NNN. 

                                       Gadi

---------------------------------------------------------

401c
        if (alfabet[j] != 0x7f)

398c
        alfabet[i] = 0x7f;

42a
#include <sys/types.h>
-- 


uucp:   {ames,att,harvard,ucbvax,iuvax}!rutgers!aramis.rutgers.edu!friedman
arpa:   FRIEDMAN@ARAMIS.RUTGERS.EDU