[comp.sources.apple2] v001SRC028: Unix Archiving Tools

jac@paul.rutgers.edu (Jonathan A. Chandross) (02/17/91)

Submitted-by: marcel@duteca.tudelft.nl
Posting-number: Volume 1, Source:28
Archive-name: archive/unix/marcel/part2
Architecture: UNIX
Version-number: 1.00

This is part 2 of a 2 part posting.

=sciibin.c
-/* @(#) sciibin.c       3.01 12Feb91  */
-/*************************************************************************
- **                                                                     **
- **  Name    :  sciibin                                                 **
- **  Author  :  Marcel J.E. Mol                                         **
- **  Date    :  06Mar89               (first release)                   **
- **  Version :  2.00                                                    **
- **  Files   :  sciibin.c       Main source file                        **
- **  Purpose :  Extract or view BinSCII files                           **
- **                                                                     **
- **  ------------------------- Revision List -------------------------  **
- **  Ver   Date       Name                   Remarks                    **
- **  1.00  06Mar89   Marcel Mol      First release                      **
- **  1.10  27Mar89   Marcel Mol      Fished things up, error routine,   **
- **                                  linecount, all info fields filled  **
- **                                  in, changed info layout.           **
- **  2.00  03Jun89   Marcel Mol      Bug fixes: alphabet to unsigned    **
- **              (Dave Whitney)      char. Some OS's need types.h.      **
- **                                  Fixed CRE/MOD order.               **
- **                                  Output filenames can be wrong      **
- **                                  when multiple files are            **
- **                                  extracted. Made crc and file-      **
- **                                  type arrays in seperate includes   **
- **  3.00  22Mar90   Marcel Mol      Includeed ports of Bruce Kahn      **
- **     1.30  27 Feb 90 Bruce Kahn  Ported to AOS/VS C 4.01 and MSC 5.1 **
- **                                 Added explicit long definitions     **
- **                                 needed.                             **
- **                                 Redid layouts for dates to be US.   **
- **                                 Modified the open routines for MSC  **
- **                                 to include binary mode, not text.   **
- **                                 Changed the way 8 bit integers are  **
- **                                 handled (redone MM).                **
- **                                 Added getopt()  (see below MM).     **
- **  3.01  22Feb91   Marcel Mol      Fixed bug: only close output       **
- **                                  when output is generated.          **
- **  =================================================================  **
- **                                                                     **
- **  Compile as follows:                                                **
- **       If you don't have getopt, compile and link the given getopt.c **
- **                                                                     **
- **      UNIX:           cc sciibin.c -Oso sciibin                      **
- **                                                                     **
- **      MSC 5.1:        cl /c /Ox sciibin.c                            **
- **                              (add /DMSDOS, if MSC didn't do it)     **
- **                      link /CO /STACK:10000 sciibin;                 **
- **                                                                     **
- **      AOS/VS:         cc sciibin.c                                   **
- **                      ccl sciibin                                    **
- **                                                                     **
- **    Defining DEBUG gives some debug information.                     **
- **    Defining DEBUGALL gives input and output of the decode routine.  **
- **                                                                     **
- **  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.                                                  **
- **                                                                     **
- **                                                                     **
- **   This software is freeware. We can not be held responsible to      **
- **   any damage this program may coase you or anyone or anything else. **
- **                                                                     **
- **   Mail bugs to:      marcel@duteca.tudelft.nl                       **
- **                                                                     **
- ************************************************************************/
-
-
-#include <stdio.h>
-#include <sys/types.h>          /* keep sun OS happy                */
-#include <sys/stat.h>           /* mostly includes types.h ...      */
-#if defined(MSDOS)
-#include <memory.h>             /* For the memset function          */
-#endif
-#include "crc.h"
-#include "filetype.h"
-
-#define BUFLEN         256
-#define FILENAME_LEN    15
-#define BINSCII_HEADER  "FiLeStArTfIlEsTaRt\n"
-#define MAXSEGLEN      0x3000
-
-#if defined(INT8)
-typedef long int16;
-#else
-typedef int  int16;
-#endif
-
-/*                           ==> Expect int variables to be at least 16 bits
- * Global variables          ==>    and longs to be at least 32 bits
- *                           ==> If not, you have some work to do...
- */                              /* MSDOS has 16 bit ints. */
-char          buf[BUFLEN+1];
-unsigned char dec[BUFLEN+1];
-unsigned char alphabet[BUFLEN+1];   /* need $FF in alphabet              */
-char          outfilename[BUFLEN+1];
-
-
-unsigned char outflag = 0,      /* the -o option                    */
-              crcflag = 0,      /* the -c option                    */
-              infoflag = 0,     /* the -v option                    */
-              testflag = 0,     /* the -t option                    */
-              makeoutput,       /* ! (-t | -v)                      */
-              crcok;            /* -t | -c                          */
-FILE *outfp;                    /* output file                      */
-
-unsigned char  filetype, stortype,
-               file_access;               /* access -> file_access for MSDOS */
-unsigned char  modyear, modmonth, modday, modhour, modmin,
-               creyear, cremonth, creday, crehour, cremin;
-int            namlen, linecount,
-               numblocks, auxtype;
-long           filesize, startbyte, segmentlen;
-char * infilename;
-
-char * progname;
-
-
-/*
- * function declarations
- */
-int   main         ();
-int   sciibin      ();
-int   getheader    ();
-int   decode       ();
-int   decodestring ();
-char *myfgets      ();
-void  usage        ();
-void  error        ();
-
-
-char * copyright = "@(#) sciibin.c  3.01 12Feb91 (c) 1989, 1991 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':
-#if defined(MSDOS)
-                      memset(outfilename, NULL, FILENAME_LEN + 1);
-#endif
-                      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 (!strncmp(buf, BINSCII_HEADER, strlen(BINSCII_HEADER))) {
-            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 alphabet, 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 int16 crc = 0;
-    struct stat statbuf;            /* MUST know if file exists         */
-    char *iomod;                    /* write or readwrite a file        */
-
-    /*
-     * Get the alphabet
-     */
-    if (myfgets(buf, BUFLEN, fp) == NULL) {
-        error("reading alphabet: unexpected end of file");
-        return 1;
-    }
-
-#if defined(DEBUG)
-    fprintf(stderr, "(%s) alphabet:%s", infilename, buf);
-#endif
-
-    if (strlen(buf) != 65) {
-        error("alphabet corrupted");
-        return 1;
-    }
-
-    /*
-     * Process the alphabet
-     */
-    for (i = 0; i < BUFLEN; i++)
-        alphabet[i] = 0xff;
-
-    for (i = 0; i < 64; i++) {
-        j = buf[i];
-        if (alphabet[j] != 0xff)
-            error("Warning: double character in alphabet");
-        alphabet[j] = i;
-    }
-
-#if defined(DEBUG)
-    for (i = 0; i < BUFLEN; i+=16) {
-        fprintf(stderr, "(%s) alphabet[%3d] =", infilename, i);
-        for (j = 0; j < 16; j++)
-            fprintf(stderr, " %02X", alphabet[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
-
-    /*
-     * Extract output filename if needed
-     */
-    if (!outflag) {
-        namlen = *buf - 'A' + 1;              /* IS +1 NEEDED ?? */
-#if defined(MSDOS)
-        memset(outfilename, NULL, FILENAME_LEN + 1);
-#endif
-        strncpy(outfilename, buf+1, namlen);
-        outfilename[namlen] = '\0';
-    }
-
-#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+FILENAME_LEN+1, 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;
-        }
-    }
-
-    /* Calculate file length */
-    filesize   = dec[0] + (dec[1]<<8) + ((long) dec[2]<<16);
-    startbyte  = dec[3] + (dec[4]<<8) + ((long) dec[5]<<16);
-
-    /* Calculate file attributes and size */
-    file_access= dec[6];
-    filetype   = dec[7];
-    auxtype    = dec[8] + (dec[9] << 8);
-    stortype   = dec[10];
-    numblocks  = dec[11] + (dec[12]<<8);
-
-    /* Calculate creation and modification dates */
-#define MOD 13
-#define CRE 17          /* 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;
-    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) + ((long) dec[23]<<16);
-    if (segmentlen > MAXSEGLEN)
-            error("warning: segmentlen probably to long");
-
-#define READ    0x01
-#define WRITE   0x02
-#define BACKUP  0x20
-#define RENAME  0x40
-#define DESTROY 0x80
-
-    if (infoflag) {
-
-        /* Display the files name, type and auxtype */
-        printf("%-15s  %3s aux: $%04X ",
-                   outfilename, filetypes[filetype], auxtype);
-
-        /* Display the file access type */
-        putchar(file_access & READ    ? 'r' : '-');
-        putchar(file_access & WRITE   ? 'w' : '-');
-        putchar(file_access & RENAME  ? 'n' : '-');
-        putchar(file_access & DESTROY ? 'd' : '-');
-        putchar(file_access & BACKUP  ? 'b' : '-');
-
-        /* Display the type of file this is - ProDOS Specific */
-        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;
-        }
-
-        /* Display modification and creation information */
-        printf(" %02d/%02d/%02d(%02d:%02d) -", modmonth, modday, modyear,
-                                               modhour, modmin);
-        printf(" %02d/%02d/%02d(%02d:%02d)\n", cremonth, creday, creyear,
-                                               crehour, cremin);
-
-        /* Display segment information */
-        printf("Part %4d of %4d,", (int) (startbyte / MAXSEGLEN) + 1,
-                                  (int) ((filesize + MAXSEGLEN-1) / MAXSEGLEN));
-        printf(" bytes %7ld to %7ld of %7ld bytes, %5d blocks\n",
-                 startbyte, startbyte+segmentlen, filesize, numblocks);
-
-    } /* if (infoflag) */
-
-    if (makeoutput) {
-        /* will creating output, not just information so verify the access */
-#if defined(MSDOS)
-        iomod = (stat(outfilename, &statbuf) == 0) ? "r+b" : "wb";
-#else
-        iomod = (stat(outfilename, &statbuf) == 0) ? "r+" : "w";
-#endif
-        if ((outfp = fopen(outfilename, iomod)) == NULL) {
-            error("unable to open output file");
-            perror(outfilename);
-            return 1;
-        }
-        fseek(outfp, startbyte, 0);
-    } /* if (makeoutput) */
-
-    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;
-        }
-    }
-
-    if (makeoutput)
-        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", alphabet[*b++]);
-    putc('\n', stderr);
-    b = out;
-#endif
-
-    while (strlen(in) > 3) {
-        *out++ = ((alphabet[in[3]] << 2) | (alphabet[in[2]] >> 4)) & 0xFF;
-        *out++ = ((alphabet[in[2]] << 4) | (alphabet[in[1]] >> 2)) & 0xFF;
-        *out++ = ((alphabet[in[1]] << 6) | (alphabet[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, "%s\n\n", copyright);
-    fprintf(stderr, "Usage: sciibin [-vtch] [-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 */
-
=unblu.c
-/* @(#) unblu.c       2.2 18/06/89  */
-/*************************************************************************
- **                                                                     **
- **  Name    :  unblu                                                   **
- **  Author  :  Marcel J.E. Mol                                         **
- **  Date    :  10/05/88              (first release)                   **
- **  Version :  2.20                                                    **
- **  Files   :  unblu.c         Main source file                        **
- **                                                                     **
- **  ------------------------- Revision List -------------------------  **
- **  Ver   Date       Name                   Remarks                    **
- **  1.00  10/05/88   Marcel Mol             Raw copy of a basic program**
- **  2.00  03/06/88   Marcel Mol             Rewrite after blu info     **
- **                                          was send to the net        **
- **  2.10  18/06/88   Marcel Mol             Added filetype texts       **
- **  2.20  23/09/88   Marcel Mol             Show mod and creation time **
- **                                                                     **
- **  =================================================================  **
- **                                                                     **
- **  Compile as follows: cc unblu.c -Oso unblu                          **
- **                                                                     **
- **  Usage: unblu [-vh] <arcfile> [<files-toextract>]                   **
- **                                                                     **
- ************************************************************************/
-
- /************************************************************************
- **                                                                     **
- **  NAME                                                               **
- **     unblu -   Extract files from an apple binary ][ archive.        **
- **                                                                     **
- **                                                                     **
- **  SYNOPSIS                                                           **
- **     unblu [-vh] arcfile [files-to-extract]                          **
- **                                                                     **
- **                                                                     **
- **  DESCRIPTION                                                        **
- **     Unblu list the contents of a binary ][ archive (the -v option)  **
- **     or extracts the listed files from the archive (without the      **
- **     -v option). If no files are listed, the comlete archive is      **
- **     extracted or listed.                                            **
- **     The -h option gives a help message on the usage of unblu.       **
- **                                                                     **
- **  AUTHOR                                                             **
- **     Marcel J.E. Mol                                                 **
- **                                                                     **
- **  BUGS                                                               **
- **     Mail bugs to:      marcel@duteca.tudelft.nl                     **
- **                                                                     **
- ************************************************************************/
-
-char * copyright = "@(#) unblu.c  2.2 18/06/89  (c) M.J.E. Mol";
-#include <stdio.h>
-#include <fcntl.h>
-#include "filetype.h"
-
-#define BUFSIZE 128                 /* Blu block length */
-#define DEBUG
-
-/* Global variables */
-char * progname;
-char * blufile;
-int    verbose   = 0;
-
-
-/* Function declarations */
-void main ();
-void unblu ();
-void process_file ();
-void extract_file ();
-void print_global_info ();
-int  want ();
-void usage ();
-void printhelp ();
-
-
-void main(argc, argv)
-int     argc;
-char ** argv;
-{
-    int  flag;				/* Flag for getopt */
-    int  bfd;				/* File descriptor for blu file */
-    extern int optind;			/* For getopt */
-    extern char * optarg;		/* For getopt */
-
-    progname = argv[0];
-    while ((flag = getopt(argc, argv, "vh")) != EOF) { /* Process options */
-        switch (flag) {
-            case 'v': verbose = 1;	/* Want only listing of archive */
-                      break;
-            case 'h': usage();		/* Give help */
-		      printhelp();
-                      exit(0);
-            default : fprintf(stderr, "%s: skipping unkown flag %c.\n",
-                                    progname, flag);
-                      break;
-        }
-    }
-
-    if (optind >= argc) {		/* No archive given */
-        usage();
-        exit(1);
-    }
-
-    blufile = argv[optind++];		/* Get archive name */
-    if ((bfd = open(blufile, O_RDONLY)) == -1) {
-        perror(blufile);
-        exit(2);
-    }
-
-    unblu(bfd, &argv[optind]);		/* Process wanted files */
-
-    close(bfd);
-
-    exit(0);
-
-} /* main */
-
-
-/*
- * unblu -- process a binary II file fd, and process the filenames 
- *          listed in wated. If wanted is \0, all files are processed.
- */
-void unblu(fd, wanted)
-int     fd;
-char ** wanted;
-{
-    unsigned char buf[BUFSIZE];
-    int  firstblock = 1;	/* First block needs special processing */
-    int  tofollow = 1;		/* Files to follow in the archive */
-    int  n;
-
-    while (tofollow && ((n = read(fd, buf, BUFSIZE)) != -1)) {
-						/* If there is a header block */
-	if (n != BUFSIZE) {
-	    fprintf(stderr, "%s: %s file size is broken\n", progname, blufile);
-	    exit(1);
-	}
-        if ((buf[0] != 10) || (buf[1] != 71) ||
-            (buf[2] != 76) || (buf[18] != 2)) { 
-            fprintf(stderr, "%s: %s not a binary II file\n", progname, blufile);
-            exit(1);
-        }
-	tofollow = buf[127];		/* How many files to follow */
-        if (firstblock && verbose) {
-            print_global_info(buf);
-            firstblock = 0;
-        }
-        process_file(fd, buf, wanted);          /* process the file for it    */
-    }
-    return;
-
-} /* unblu */
-
-
-/*
- * process_file -- retrieve or print file information of file given
- *                 in buf
- */
-void process_file(fd, buf, wanted)
-int     fd;
-unsigned char *  buf;
-char ** wanted;
-{
-    int tf;
-    int ftype;
-    int dflags;
-    int fnamelen;
-    int filelen;
-    char fname[64];
-    int nblocks;
-    int modyear, modmonth, modday;
-    int creyear, cremonth, creday;
-    int modhour, modsec;
-    int crehour, cresec;
-
-    /*
-     * Get fileinfo
-     */
-    ftype =  buf[4];				/* File type */
-    fnamelen =  buf[23];			/* filename */
-    strncpy(fname, &buf[24], fnamelen);
-    fname[fnamelen] = '\0';
-    dflags =  buf[125];				/* Data flags */
-    tf =  buf[127];				/* Number of files to follow */
-    filelen = buf[20] + (buf[21]<<8) + (buf[22]<<16);/* Calculate file length */
-    nblocks = (filelen + BUFSIZE-1) / BUFSIZE;
-    modyear = buf[11] >>1;
-    modday  = buf[10] & 0x1f;
-    modmonth= ((buf[11] & 0x01) << 3) + (buf[10] >> 5);
-    modhour = buf[13] & 0x1f;
-    modsec  = buf[12] & 0x3f;
-    creyear = buf[15] >>1;
-    creday  = buf[14] & 0x1f;
-    cremonth= ((buf[15] & 0x01) << 3) + (buf[14] >> 5);
-    crehour = buf[17] & 0x1f;
-    cresec  = buf[16] & 0x3f;
-
-
-    if (*wanted == NULL || want(fname, wanted)) {
-        if (verbose) {			        /* print file information */
-	    printf("%-15s  %3s", fname, filetypes[ftype]);
-	    printf(" %02d/%02d/%02d(%02d:%02d)", modyear, modmonth, modday,
-						 modhour, modsec);
-	    printf(" - %02d/%02d/%02d(%02d:%02d)", creyear, cremonth, creday,
-						   crehour, cresec);
-	    printf(" %5d bytes ", filelen);
-	    if (dflags == 0)
-		printf("stored");
-	    else {
-		if (dflags & 128) {
-	            printf("squeezed");
-	        }
-	        if (dflags & 64) {
-	            printf("encrypted");
-	        }
-	        if (dflags & 1) 
-	            printf("packed");
-	    }
-	    putchar('\n'); 
-
-	    if (ftype != 15)  			/* If not a directory */
-                lseek(fd, BUFSIZE*nblocks, 1);  /* Seek to next file */
-        }
-	else if (ftype != 15) 
-            extract_file(fd, fname, filelen);
-    }
-    else if (ftype != 15)  			/* If not a directory */
-        lseek(fd, BUFSIZE*nblocks, 1);          /* Seek to next file */
-
-    return;
-
-} /* process_file */
-
-
-/*
- * extract_file -- extract file fname from the archive fd. Fname
- *                 comtains filelen bytes.
- */
-void extract_file(fd, fname, filelen)
-int    fd;
-char * fname;
-int    filelen;
-{
-    int ofd;
-    int n;
-    unsigned char buf[BUFSIZE];
-
-    printf("x - %s\n", fname);
-    if ((ofd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
-						/* Open (PRODOS) file */
-        perror(fname);
-        exit(1);
-    }
-
-    while (filelen > 0) {
-        if ((n = read(fd, buf, BUFSIZE)) != BUFSIZE) { /* Read 128 bytes */
-	    fprintf(stderr, "%s: %s file size is broken\n", progname, blufile);
-	    exit(1);
-	}
-        write(ofd, buf, (filelen >= BUFSIZE ? BUFSIZE : filelen));
-        filelen -= BUFSIZE;
-    }
-
-    close(ofd); 				/* Close (PRODOS) file */
-    return;
-
-} /* extract_file */
-
-
-
-/*
- * print_global_info -- print global information of the binary II file
- */
-void print_global_info(buf)
-unsigned char * buf;
-{
-    int disk_blocks;
-
-    disk_blocks = buf[117] + (buf[118]<<8) + (buf[119]<<16) + (buf[120]<<24);
-    printf("%s, by Blu %d, ", blufile, buf[126]);
-    printf("%d files, using %d blocks\n", buf[127]+1, disk_blocks);
-    return;
-
-} /* print_global_info */
-
-
-
-/*
- * want -- return 1 if name exists in array wantlist,
- *         else return 0
- */
-want(name, wantlist)
-char *  name;
-char ** wantlist;
-{
-    while (*wantlist != NULL) {
-        if (strcmp(name, *wantlist++) == NULL)
-            return(1);
-    }
-    return(0);
-
-} /* want */
-
-
-
-void usage()
-{
-    fprintf(stderr, "usage: %s [-hv] <blufile> [<filetoextract> ...]\n",
-                        progname);
-    return;
-
-} /* usage */
-
-
-
-void printhelp()
-{
-    fprintf(stderr, "\t-h show this help.\n");
-    fprintf(stderr, "\t-v show contents of archive.\n");
-}
+ END OF ARCHIVE