home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-10 | 23.3 KB | 1,082 lines |
- #!/bin/sh-----cut here-----cut here-----cut here-----cut here-----
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README # xbin.c # xbin.l
- echo shar: extracting README
- cat - << \SHAR_EOF > README
- This is version 2.3 of xbin. The major changes include
- perfomance improvements from Dan LaLiberte of UIUC, fixes
- for 16-bit machines from Jim Budler of AMD, and a fix for
- a bug in the run-length encoding code.
-
- This version of "xbin" can handle all three BinHex formats
- (so far). Thanks to Darin Adler at TMQ Software for providing
- the code to compute and check the CRC values for all three formats.
- (There are no plans to support binhex5.0, as its use of binary
- encoding makes it useless for sending programs through e-mail).
-
- Other new features include "list" and "verbose" modes, the
- ability to convert several binhex files at one time, the ability
- to read standard input, somewhat better error handling, and a
- manual page.
-
- Any extraneous mail or news headers are ignored, but xbin relies
- on finding a line which starts with "(This file" to know when
- the header ends and the good stuff begins. You can add one
- of these by hand if it's been lost.
-
- To compile it on USG systems, type:
- cc -o xbin xbin.c
-
- or on Berkeley systems:
- cc -o xbin xbin.c -DBSD
-
- As usual, please report any problems, suggestions, or
- improvements to me.
-
- Dave Johnson
- Brown University Computer Science
- ddj%brown@csnet-relay.ARPA
- {ihnp4,decvax,allegra,ulysses,linus}!brunix!ddj
-
- ===================
- Here's an informal description of the HQX format as I understand it:
- -----
- The first and last characters are each a ':'. After the first ':',
- the rest of the file is just string of 6 bit encoded characters.
- All newlines and carriage returns are to be ignored.
-
- The tricky part is that there are holes in the translation string
- so you have to look up each file character to get its binary 6 bit
- value. I found the string by looking at a hex dump of BinHex:
-
- !"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr
-
- I can't see how this aids or abets any kind of error recovery, but
- if you ran into a char not in the list, you would know something's
- wrong and give up.
-
- There is some run length encoding, where the character to be repeated
- is followed by a 0x90 byte then the repeat count. For example, ff9004
- means repeat 0xff 4 times. The special case of a repeat count of zero
- means it's not a run, but a literal 0x90. 2b9000 => 2b90.
-
- *** Note: the 9000 can be followed by a run, which means to repeat the
- 0x90 (not the character previous to that). That is, 2090009003 means
- a 0x20 followed by 3 0x90's.
-
- Once you've turned the 6 bit chars into 8, you can parse the header.
- The header format consists of a one byte name length, then the mac
- file name, then a null. The rest of the header is 20 bytes long,
- and contains the usual file type, creator/author, file flags, data
- and resource lengths, and the two byte crc value for the header.
-
- The data fork and resource fork contents follow in that order.
- There is a two byte file crc at the end of each fork. If a fork
- is empty, there will be no bytes of contents and the checksum
- will be two bytes of zero.
-
- So the decoded data between the first and last ':' looks like:
-
- 1 n 4 4 2 4 4 2 (length)
- +-+---------+-+----+----+----+----+----+--+
- |n| name... |0|TYPE|AUTH|FLAG|DLEN|RLEN|HC| (contents)
- +-+---------+-+----+----+----+----+----+--+
-
- DLEN 2 (length)
- +--------------------------------------+--+
- | DATA FORK |DC| (contents)
- +--------------------------------------+--+
-
- RLEN 2 (length)
- +--------------------------------------+--+
- | RESOURCE FORK |RC| (contents)
- +--------------------------------------+--+
-
- ------
- SHAR_EOF
- echo shar: extracting xbin.c
- cat - << \SHAR_EOF > xbin.c
- #ifndef lint
- static char version[] = "xbin.c Version 2.3 09/30/85";
- #endif lint
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
-
- #ifdef MAXNAMLEN /* 4.2 BSD */
- #define FNAMELEN MAXNAMLEN
- #else
- #define FNAMELEN DIRSIZ
- #endif
-
- #ifdef BSD
- #include <sys/time.h>
- #include <sys/timeb.h>
- #define search_last rindex
- extern char *rindex();
- #else
- #include <time.h>
- extern long timezone;
- #define search_last strrchr
- extern char *strrchr();
- #endif
-
- /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
- #define TIMEDIFF 0x7c25b080
-
- #define DATABYTES 128
-
- #define BYTEMASK 0xff
- #define BYTEBIT 0x100
- #define WORDMASK 0xffff
- #define WORDBIT 0x10000
-
- #define NAMEBYTES 63
- #define H_NLENOFF 1
- #define H_NAMEOFF 2
-
- /* 65 <-> 80 is the FInfo structure */
- #define H_TYPEOFF 65
- #define H_AUTHOFF 69
- #define H_FLAGOFF 73
-
- #define H_LOCKOFF 81
- #define H_DLENOFF 83
- #define H_RLENOFF 87
- #define H_CTIMOFF 91
- #define H_MTIMOFF 95
-
- #define H_OLD_DLENOFF 81
- #define H_OLD_RLENOFF 85
-
- #define F_BUNDLE 0x2000
- #define F_LOCKED 0x8000
-
- struct macheader {
- char m_name[NAMEBYTES+1];
- char m_type[4];
- char m_author[4];
- short m_flags;
- long m_datalen;
- long m_rsrclen;
- long m_createtime;
- long m_modifytime;
- } mh;
-
- struct filenames {
- char f_info[256];
- char f_data[256];
- char f_rsrc[256];
- } files;
-
- int pre_beta; /* options */
- int listmode;
- int verbose;
-
- int compressed; /* state variables */
- int qformat;
- FILE *ifp;
-
- /*
- * xbin -- unpack BinHex format file into suitable
- * format for downloading with macput
- * Dave Johnson, Brown University Computer Science
- *
- * (c) 1984 Brown University
- * may be used but not sold without permission
- *
- * created ddj 12/16/84
- * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
- * revised ddj 03/11/85 -- strip LOCKED bit from m_flags
- * revised ahm 03/12/85 -- System V compatibility
- * revised dba 03/16/85 -- (Darin Adler, TMQ Software) 4.0 EOF fixed,
- * 4.0 checksum added
- * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
- * revised ddj 03/24/85 -- check for filename truncation, allow multiple files
- * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
- * revised jcb 03/30/85 -- (Jim Budler, amdcad!jimb), revised for compatibility
- * with 16-bit int machines
- * revised dl 06/16/85 -- (Dan LaLiberte, liberte@uiucdcs) character
- * translation speedup
- * revised ddj 09/30/85 -- fixed problem with run of RUNCHAR
- */
- char usage[] = "usage: \"xbin [-v] [-l] [-o] [-n name] [-] filename\"\n";
-
- main(ac, av)
- char **av;
- {
- char *filename, *macname;
-
- filename = ""; macname = "";
- ac--; av++;
- while (ac) {
- if (av[0][0] == '-') {
- switch (av[0][1]) {
- case '\0':
- filename = "-";
- break;
- case 'v':
- verbose++;
- break;
- case 'l':
- listmode++;
- break;
- case 'o':
- pre_beta++;
- break;
- case 'n':
- if (ac > 1) {
- ac--; av++;
- macname = av[0];
- filename = "";
- break;
- }
- else
- goto bad_usage;
- default:
- goto bad_usage;
- }
- }
- else
- filename = av[0];
- if (filename[0] != '\0') {
- setup_files(filename, macname);
- if (listmode) {
- print_header();
- }
- else {
- process_forks();
- /* now that we know the size of the forks */
- forge_info();
- }
- if (ifp != stdin)
- fclose(ifp);
- macname = "";
- ifp = NULL; /* reset state */
- qformat = 0;
- compressed = 0;
- }
- ac--; av++;
- }
- if (*filename == '\0') {
- bad_usage:
- fprintf(stderr, usage);
- exit(1);
- }
- }
-
- static char *extensions[] = {
- ".hqx",
- ".hcx",
- ".hex",
- "",
- NULL
- };
-
- setup_files(filename, macname)
- char *filename; /* input file name -- extension optional */
- char *macname; /* name to use on the mac side of things */
- {
- char namebuf[256], *np;
- char **ep;
- int n;
- struct stat stbuf;
- long curtime;
-
- if (filename[0] == '-') {
- ifp = stdin;
- filename = "stdin";
- }
- else {
- /* find input file and open it */
- for (ep = extensions; *ep != NULL; ep++) {
- sprintf(namebuf, "%s%s", filename, *ep);
- if (stat(namebuf, &stbuf) == 0)
- break;
- }
- if (*ep == NULL) {
- perror(namebuf);
- exit(-1);
- }
- ifp = fopen(namebuf, "r");
- if (ifp == NULL) {
- perror(namebuf);
- exit(-1);
- }
- }
- if (ifp == stdin) {
- curtime = time(0);
- mh.m_createtime = curtime;
- mh.m_modifytime = curtime;
- }
- else {
- mh.m_createtime = stbuf.st_mtime;
- mh.m_modifytime = stbuf.st_mtime;
- }
- if (listmode || verbose) {
- fprintf(stderr, "%s %s%s",
- listmode ? "\nListing" : "Converting",
- namebuf, listmode ? ":\n" : " ");
- }
-
- qformat = find_header(); /* eat mailer header &cetera, intuit format */
-
- if (qformat)
- do_q_header(macname);
- else
- do_o_header(macname, filename);
-
- /* make sure host file name doesn't get truncated beyond recognition */
- n = strlen(mh.m_name);
- if (n > FNAMELEN - 2)
- n = FNAMELEN - 2;
- strncpy(namebuf, mh.m_name, n);
- namebuf[n] = '\0';
-
- /* get rid of troublesome characters */
- for (np = namebuf; *np; np++)
- if (*np == ' ' || *np == '/')
- *np = '_';
-
- sprintf(files.f_data, "%s.data", namebuf);
- sprintf(files.f_rsrc, "%s.rsrc", namebuf);
- sprintf(files.f_info, "%s.info", namebuf);
- if (verbose)
- fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf);
- }
-
- /* print out header information in human-readable format */
- print_header()
- {
- char *ctime();
-
- printf("macname: %s\n", mh.m_name);
- printf("filetype: %.4s, ", mh.m_type);
- printf("author: %.4s, ", mh.m_author);
- printf("flags: 0x%x\n", mh.m_flags);
- if (qformat) {
- printf("data length: %ld, ", mh.m_datalen);
- printf("rsrc length: %ld\n", mh.m_rsrclen);
- }
- if (!pre_beta) {
- printf("create time: %s", ctime(&mh.m_createtime));
- }
- }
-
- process_forks()
- {
- if (qformat) {
- /* read data and resource forks of .hqx file */
- do_q_fork(files.f_data, mh.m_datalen);
- do_q_fork(files.f_rsrc, mh.m_rsrclen);
- }
- else
- do_o_forks();
- }
-
- /* write out .info file from information in the mh structure */
- forge_info()
- {
- static char buf[DATABYTES];
- char *np;
- FILE *fp;
- int n;
- long tdiff;
- struct tm *tp;
- #ifdef BSD
- struct timeb tbuf;
- #else
- long bs;
- #endif
-
- for (np = mh.m_name; *np; np++)
- if (*np == '_') *np = ' ';
-
- buf[H_NLENOFF] = n = np - mh.m_name;
- strncpy(buf + H_NAMEOFF, mh.m_name, n);
- strncpy(buf + H_TYPEOFF, mh.m_type, 4);
- strncpy(buf + H_AUTHOFF, mh.m_author, 4);
- put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED);
- if (pre_beta) {
- put4(buf + H_OLD_DLENOFF, mh.m_datalen);
- put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
- }
- else {
- put4(buf + H_DLENOFF, mh.m_datalen);
- put4(buf + H_RLENOFF, mh.m_rsrclen);
-
- /* convert unix file time to mac time format */
- #ifdef BSD
- ftime(&tbuf);
- tp = localtime(&tbuf.time);
- tdiff = TIMEDIFF - tbuf.timezone * 60;
- if (tp->tm_isdst)
- tdiff += 60 * 60;
- #else
- /* I hope this is right! -andy */
- time(&bs);
- tp = localtime(&bs);
- tdiff = TIMEDIFF - timezone;
- if (tp->tm_isdst)
- tdiff += 60 * 60;
- #endif
- put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
- put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
- }
- fp = fopen(files.f_info, "w");
- if (fp == NULL) {
- perror("info file");
- exit(-1);
- }
- fwrite(buf, 1, DATABYTES, fp);
- fclose(fp);
- }
-
- /* eat characters until header detected, return which format */
- find_header()
- {
- int c, at_bol;
- char ibuf[BUFSIZ];
-
- /* look for "(This file ...)" line */
- while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
- if (strncmp(ibuf, "(This file", 10) == 0)
- break;
- }
- at_bol = 1;
- while ((c = getc(ifp)) != EOF) {
- switch (c) {
- case '\n':
- case '\r':
- at_bol = 1;
- break;
- case ':':
- if (at_bol) /* q format */
- return 1;
- break;
- case '#':
- if (at_bol) { /* old format */
- ungetc(c, ifp);
- return 0;
- }
- break;
- default:
- at_bol = 0;
- break;
- }
- }
-
- fprintf(stderr, "unexpected EOF\n");
- exit(2);
- /* NOTREACHED */
- }
-
- static unsigned int crc;
-
- short get2q();
- long get4q();
-
- /* read header of .hqx file */
- do_q_header(macname)
- char *macname;
- {
- char namebuf[256]; /* big enough for both att & bsd */
- int n;
- unsigned int calc_crc, file_crc;
-
- crc = 0; /* compute a crc for the header */
- q_init(); /* reset static variables */
-
- n = getq(); /* namelength */
- n++; /* must read trailing null also */
- getqbuf(namebuf, n); /* read name */
- if (macname[0] == '\0')
- macname = namebuf;
-
- n = strlen(macname);
- if (n > NAMEBYTES)
- n = NAMEBYTES;
- strncpy(mh.m_name, macname, n);
- mh.m_name[n] = '\0';
-
- getqbuf(mh.m_type, 4);
- getqbuf(mh.m_author, 4);
- mh.m_flags = get2q();
- mh.m_datalen = get4q();
- mh.m_rsrclen = get4q();
-
- comp_q_crc(0);
- comp_q_crc(0);
- calc_crc = crc;
- file_crc = get2q();
- verify_crc(calc_crc, file_crc);
- }
-
- do_q_fork(fname, len)
- char *fname;
- register long len;
- {
- FILE *outf;
- register int c, i;
- unsigned int calc_crc, file_crc;
-
- outf = fopen(fname, "w");
- if (outf == NULL) {
- perror(fname);
- exit(-1);
- }
-
- crc = 0; /* compute a crc for a fork */
-
- if (len)
- for (i = 0; i < len; i++) {
- if ((c = getq()) == EOF) {
- fprintf(stderr, "unexpected EOF\n");
- exit(2);
- }
- putc(c, outf);
- }
-
- comp_q_crc(0);
- comp_q_crc(0);
- calc_crc = crc;
- file_crc = get2q();
- verify_crc(calc_crc, file_crc);
- fclose(outf);
- }
-
- /* verify_crc(); -- check if crc's check out */
- verify_crc(calc_crc, file_crc)
- unsigned int calc_crc, file_crc;
- {
- calc_crc &= WORDMASK;
- file_crc &= WORDMASK;
-
- if (calc_crc != file_crc) {
- fprintf(stderr, "CRC error\n---------\n");
- fprintf(stderr, "CRC in file:\t0x%x\n", file_crc);
- fprintf(stderr, "calculated CRC:\t0x%x\n", calc_crc);
- exit(3);
- }
- }
-
- static int eof;
- static char obuf[3];
- static char *op, *oend;
-
- /* initialize static variables for q format input */
- q_init()
- {
- eof = 0;
- op = obuf;
- oend = obuf + sizeof obuf;
- }
-
- /* get2q(); q format -- read 2 bytes from input, return short */
- short
- get2q()
- {
- register int c;
- short value = 0;
-
- c = getq();
- value = (c & BYTEMASK) << 8;
- c = getq();
- value |= (c & BYTEMASK);
-
- return value;
- }
-
- /* get4q(); q format -- read 4 bytes from input, return long */
- long
- get4q()
- {
- register int c, i;
- long value = 0L;
-
- for (i = 0; i < 4; i++) {
- c = getq();
- value <<= 8;
- value |= (c & BYTEMASK);
- }
- return value;
- }
-
- /* getqbuf(); q format -- read n characters from input into buf */
- /* All or nothing -- no partial buffer allowed */
- getqbuf(buf, n)
- register char *buf;
- register int n;
- {
- register int c, i;
-
- for (i = 0; i < n; i++) {
- if ((c = getq()) == EOF)
- return EOF;
- *buf++ = c;
- }
- return 0;
- }
-
- #define RUNCHAR 0x90
-
- /* q format -- return one byte per call, keeping track of run codes */
- getq()
- {
- register int c;
-
- if ((c = getq_nocrc()) == EOF)
- return EOF;
- comp_q_crc((unsigned)c);
- return c;
- }
-
- getq_nocrc()
- {
- static int rep, lastc;
- int c;
-
- if (rep) {
- rep--;
- return lastc;
- }
- if ((c = getq_raw()) == EOF) {
- return EOF;
- }
- if (c == RUNCHAR) {
- if ((rep = getq_raw()) == EOF)
- return EOF;
- if (rep != 0) {
- /* already returned one, about to return another */
- rep -= 2;
- return lastc;
- }
- else {
- lastc = RUNCHAR;
- return RUNCHAR;
- }
- }
- else {
- lastc = c;
- return c;
- }
- }
-
- /* q format -- return next 8 bits from file without interpreting run codes */
- getq_raw()
- {
- char ibuf[4];
- register char *ip = ibuf, *iend = ibuf + sizeof ibuf;
- int c;
-
- if (op == obuf) {
- for (ip = ibuf; ip < iend; ip++) {
- if ((c = get6bits()) == EOF)
- if (ip <= &ibuf[1])
- return EOF;
- else if (ip == &ibuf[2])
- eof = 1;
- else
- eof = 2;
- *ip = c;
- }
- obuf[0] = (ibuf[0] << 2 | ibuf[1] >> 4);
- obuf[1] = (ibuf[1] << 4 | ibuf[2] >> 2);
- obuf[2] = (ibuf[2] << 6 | ibuf[3]);
- }
- if ((eof) & (op >= &obuf[eof]))
- return EOF;
- c = *op++;
- if (op >= oend)
- op = obuf;
- return (c & BYTEMASK);
- }
-
- /*
- char tr[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
- 0 123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
- 0 1 2 3
- trlookup is used to translate by direct lookup. The input character
- is an index into trlookup. If the result is 0xFF, a bad char has been read.
- Added by: Dan LaLiberte, liberte@uiucdcs.Uiuc.ARPA, ihnp4!uiucdcs!liberte
- */
- char trlookup[83] = { 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0xFF, 0xFF,
- 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xFF,
- 0x14, 0x15, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
- 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0xFF,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0xFF,
- 0x2C, 0x2D, 0x2E, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0xFF,
- 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0xFF, 0xFF,
- 0x3D, 0x3E, 0x3F };
-
- /* q format -- decode one byte into 6 bit binary */
- get6bits()
- {
- register int c;
- register int tc;
-
- while (1) {
- c = getc(ifp);
- switch (c) {
- case '\n':
- case '\r':
- continue;
- case ':':
- case EOF:
- return EOF;
- default:
- tc = ((c-' ') < 83) ? trlookup[c-' '] : 0xff;
- /* fprintf(stderr, "c = '%c' tc = %4x\n", c, tc); */
- if (tc != 0xff)
- return (tc);
- fprintf(stderr, "bad char: '%c'\n", c);
- return EOF;
- }
- }
- }
-
-
- #define CRCCONSTANT 0x1021
-
- comp_q_crc(c)
- register unsigned int c;
- {
- register int i;
- register unsigned long temp = crc;
-
- for (i=0; i<8; i++) {
- c <<= 1;
- if ((temp <<= 1) & WORDBIT)
- temp = (temp & WORDMASK) ^ CRCCONSTANT;
- temp ^= (c >> 8);
- c &= BYTEMASK;
- }
- crc = temp;
- }
-
- /* old format -- process .hex and .hcx files */
- do_o_header(macname, filename)
- char *macname, *filename;
- {
- char namebuf[256]; /* big enough for both att & bsd */
- char ibuf[BUFSIZ];
- int n;
-
- /* set up name for output files */
- if (macname[0] == '\0') {
- strcpy(namebuf, filename);
-
- /* strip directories */
- macname = search_last(namebuf, '/');
- if (macname == NULL)
- macname = namebuf;
- else
- macname++;
-
- /* strip extension */
- n = strlen(macname);
- if (n > 4) {
- n -= 4;
- if (macname[n] == '.' && macname[n+1] == 'h'
- && macname[n+3] == 'x')
- macname[n] = '\0';
- }
- }
- n = strlen(macname);
- if (n > NAMEBYTES)
- n = NAMEBYTES;
- strncpy(mh.m_name, macname, n);
- mh.m_name[n] = '\0';
-
- /* read "#TYPEAUTH$flag" line */
- if (fgets(ibuf, BUFSIZ, ifp) == NULL) {
- fprintf(stderr, "unexpected EOF\n");
- exit(2);
- }
- n = strlen(ibuf);
- if (n >= 7 && ibuf[0] == '#' && ibuf[n-6] == '$') {
- if (n >= 11)
- strncpy(mh.m_type, &ibuf[1], 4);
- if (n >= 15)
- strncpy(mh.m_author, &ibuf[5], 4);
- sscanf(&ibuf[n-5], "%4hx", &mh.m_flags);
- }
- }
-
- do_o_forks()
- {
- char ibuf[BUFSIZ];
- int forks = 0, found_crc = 0;
- unsigned int calc_crc, file_crc;
- extern long make_file();
-
-
- crc = 0; /* calculate a crc for both forks */
-
- /* create empty files ahead of time */
- close(creat(files.f_data, 0666));
- close(creat(files.f_rsrc, 0666));
-
- while (!found_crc && fgets(ibuf, BUFSIZ, ifp) != NULL) {
- if (forks == 0 && strncmp(ibuf, "***COMPRESSED", 13) == 0) {
- compressed++;
- continue;
- }
- if (strncmp(ibuf, "***DATA", 7) == 0) {
- mh.m_datalen = make_file(files.f_data, compressed);
- forks++;
- continue;
- }
- if (strncmp(ibuf, "***RESOURCE", 11) == 0) {
- mh.m_rsrclen = make_file(files.f_rsrc, compressed);
- forks++;
- continue;
- }
- if (compressed && strncmp(ibuf, "***CRC:", 7) == 0) {
- found_crc++;
- calc_crc = crc;
- sscanf(&ibuf[7], "%x", &file_crc);
- break;
- }
- if (!compressed && strncmp(ibuf, "***CHECKSUM:", 12) == 0) {
- found_crc++;
- calc_crc = crc & BYTEMASK;
- sscanf(&ibuf[12], "%x", &file_crc);
- file_crc &= BYTEMASK;
- break;
- }
- }
-
- if (found_crc)
- verify_crc(calc_crc, file_crc);
- else {
- fprintf(stderr, "missing CRC\n");
- exit(3);
- }
- }
-
- long
- make_file(fname, compressed)
- char *fname;
- int compressed;
- {
- char ibuf[BUFSIZ];
- FILE *outf;
- register long nbytes = 0L;
-
- outf = fopen(fname, "w");
- if (outf == NULL) {
- perror(fname);
- exit(-1);
- }
-
- while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
- if (strncmp(ibuf, "***END", 6) == 0)
- break;
- if (compressed)
- nbytes += comp_to_bin(ibuf, outf);
- else
- nbytes += hex_to_bin(ibuf, outf);
- }
-
- fclose(outf);
- return nbytes;
- }
-
- comp_c_crc(c)
- unsigned char c;
- {
- crc = (crc + c) & WORDMASK;
- crc = ((crc << 3) & WORDMASK) | (crc >> 13);
- }
-
- comp_e_crc(c)
- unsigned char c;
- {
- crc += c;
- }
-
- #define SIXB(c) (((c)-0x20) & 0x3f)
-
- comp_to_bin(ibuf, outf)
- char ibuf[];
- FILE *outf;
- {
- char obuf[BUFSIZ];
- register char *ip = ibuf;
- register char *op = obuf;
- register int n, outcount;
- int numread, incount;
-
- numread = strlen(ibuf);
- ip[numread-1] = ' '; /* zap out the newline */
- outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4);
- incount = ((outcount / 3) + 1) * 4;
- for (n = numread; n < incount; n++) /* restore lost spaces */
- ibuf[n] = ' ';
-
- n = 0;
- while (n <= outcount) {
- *op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4;
- *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2;
- *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]);
- ip += 4;
- n += 3;
- }
-
- for (n=1; n <= outcount; n++)
- comp_c_crc((unsigned)obuf[n]);
-
- fwrite(obuf+1, 1, outcount, outf);
- return outcount;
- }
-
- hex_to_bin(ibuf, outf)
- char ibuf[];
- FILE *outf;
- {
- register char *ip = ibuf;
- register int n, outcount;
- int c;
-
- n = strlen(ibuf) - 1;
- outcount = n / 2;
- for (n = 0; n < outcount; n++) {
- c = hexit(*ip++);
- comp_e_crc((unsigned)(c = (c << 4) | hexit(*ip++)));
- fputc(c, outf);
- }
- return outcount;
- }
-
- hexit(c)
- int c;
- {
- if ('0' <= c && c <= '9')
- return c - '0';
- if ('A' <= c && c <= 'F')
- return c - 'A' + 10;
-
- fprintf(stderr, "illegal hex digit: %c", c);
- exit(4);
- /* NOTREACHED */
- }
-
- put2(bp, value)
- char *bp;
- short value;
- {
- *bp++ = (value >> 8) & BYTEMASK;
- *bp++ = value & BYTEMASK;
- }
-
- put4(bp, value)
- char *bp;
- long value;
- {
- register int i, c;
-
- for (i = 0; i < 4; i++) {
- c = (value >> 24) & BYTEMASK;
- value <<= 8;
- *bp++ = c;
- }
- }
- SHAR_EOF
- echo shar: extracting xbin.l
- cat - << \SHAR_EOF > xbin.l
- .TH XBIN local "24 Mar 1985"
- .UC 4
- .SH NAME
- xbin \- convert mailable format BinHex file into binary before downloading
- to MacTerminal
- .SH SYNOPSIS
- .B xbin
- [
- .B \-o
- ]
- [
- .B \-v
- ]
- [
- .B \-l
- ]
- [[
- .B \-n
- name
- ] file] ...
- .SH DESCRIPTION
- .I Xbin
- converts a file created by BinHex (usually
- named with one of the extensions ".hex", ".hcx", or ".hqx")
- into three host-system files suitable for downloading to a
- Macintosh via macput.
- This program is designed for use with the 1.1 Release
- version of MacTerminal, but includes a compatibility option for the
- old -0.15X Almost-Alpha version.
- .PP
- The
- .B -l
- (list) option reads the header information and
- prints out all the useful information there,
- without creating any converted output files.
- .PP
- The
- .B -v
- (verbose) option prints a line for each file to be converted, indicating
- the input and output file names.
- .PP
- The
- .B -n
- name
- option allows the user to specify the name to use when creating
- the host files and the eventual name to use on the mac.
- This option must precede the input file name it is to affect.
- .PP
- If this option is not used, the names will be derived from
- either the input file name (.hex or .hcx files),
- or the name encoded in the header information (.hqx files).
- Spaces and slashes will be converted to underscores, and
- the .h?x extension will be deleted, if one is included in the
- input file name.
- .PP
- A file name of "-" indicates that the input should be taken from stdin.
- If no mac file name is specified, the default name (for .hex or .hcx files)
- is "stdin".
- .PP
- Mail or news headers and signatures need not be manually
- stripped -- xbin will ignore pretty much anything
- it doesn't need.
- .PP
- .I xbin
- creates three host-system files from each input file:
- .IB name .info ,
- .IB name .data ,
- and
- .IB name .rsrc .
- .PP
- The
- .B \-o
- flag specifies "old" (version -0.15X) MacTerminal compatibility mode.
- .SH BUGS
- The "LOCKED" bit in the flags cannot be set by xbin.
- This is due to a bug in MacTerminal, which sets the flags
- when the file is created, rather than after it has been
- transfered, resulting in it not being able to write the
- file.
- .PP
- Input files must contain a line starting with "(This file"
- to detect the beginning of the BinHex information.
- .SH SEE ALSO
- macput(1), macget(1)
- .SH AUTHOR
- Dave Johnson, Brown 12/16/84;
- CRC handling code by Darin Adler, TMQ Software 3/16/85
- SHAR_EOF
-