From:	SMTP%"VMSSERV@kcl.ac.uk" 19-AUG-1996 18:16:56.25
To:	everhart@star.zko.dec.com
CC:	
Subj:	XBIN.30-OF-31

-+-+-+-+-+-+-+-+ START OF PART 30 -+-+-+-+-+-+-+-+
X`09static char buf`5BDATABYTES`5D;
X`09char *np;
X`09FILE *fp;
X`09int n;
X`09long tdiff;
X`09struct tm *tp;
X#if defined(BSD) `7C`7C\1009__VMS)
X`09struct timeb tbuf;
X#else
X`09long bs;
X#endif
X
X`09for (np = mh.m_name; *np; np++)
X`09`09if (*np == '_') *np = ' ';
X
X`09buf`5BH_NLENOFF`5D = n = np - mh.m_name;
X`09strncpy(buf + H_NAMEOFF, mh.m_name, n);
X`09strncpy(buf + H_TYPEOFF, mh.m_type, 4);
X`09strncpy(buf + H_AUTHOFF, mh.m_author, 4);
X`09put2(buf + H_FLAGOFF, mh.m_flags `26 `7EF_LOCKED);
X`09if (pre_beta) `7B
X`09`09put4(buf + H_OLD_DLENOFF, mh.m_datalen);
X`09`09put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
X`09`7D
X`09else `7B
X`09`09put4(buf + H_DLENOFF, mh.m_datalen);
X`09`09put4(buf + H_RLENOFF, mh.m_rsrclen);
X
X`09`09/* convert unix file time to mac\0C06format */
X#if defined(BSD) `7C`7C\1009__VMS)
X`09`09ftime(`26tbuf);
X`09`09tp = localtime(`26tbuf.time);
X`09`09tdiff = TIMEDIFF - tbuf.timezone * 60;
X`09`09if (tp->tm_isdst)
X`09`09`09tdiff += 60 * 60;
X#else
X`09`09/* I hope this is right! -andy */
X`09`09time(`26bs);
X`09`09tp = localtime(`26bs);
X`09`09tdiff = TIMEDIFF - timezone;
X`09`09if (tp->tm_isdst)
X`09`09`09tdiff += 60 * 60;
X#endif
X`09`09put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
X`09`09put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
X`09`7D
X`09fp = fopen(files.f_info, "w");
X`09if (fp == NULL) `7B
X`09`09perror("info file");
X`09`09exit(-1);
X`09`7D
X`09fwrite(buf, 1, DATABYTES, fp);
X`09fclose(fp);
X`7D
X
X/* eat characters until header detected, return which format */
Xfind_header()
X`7B
X`09int c, at_bol;
X`09char ibuf`5BBUFSIZ`5D;
X
X`09/* look for "(This file ...)" line */
X`09while (fgets(ibuf, BUFSIZ, ifp) != NULL) `7B
X`09`09if (strncmp(ibuf, "(This file", 10) == 0)
X`09`09`09break;
X`09`7D
X`09at_bol = 1;
X`09while ((c = getc(ifp)) != EOF) `7B
X`09`09switch (c) `7B
X`09`09case '`5Cn':
X`09`09case '`5Cr':
X`09`09`09at_bol = 1;
X`09`09`09break;
X`09`09case ':':
X`09`09`09if (at_bol)`09/* q format */
X`09`09&0209return 1;
X`09`09`09break;
X`09`09case '#':
X`09`09`09if (at_bol) `7B`09/* old format */
X`09`09&0209ungetc(c, ifp);
X`09`09&0209return 0;
X`09`09`09`7D
X`09`09`09break;
X`09`09default:
X`09`09`09at_bol = 0;
X`09`09`09break;
X`09`09`7D
X`09`7D
X
X`09fprintf(stderr, "unexpected EOF`5Cn");
X`09exit(2);
X`09/* NOTREACHED */
X`7D
X
Xstatic unsigned int crc;
X
Xshort get2q();
Xlong get4q();
X
X/* read header of .hqx file */
Xdo_q_header(macname)
Xchar *macname;
X`7B
X`09char namebuf`5B256`5D;`09`09/* big enough for both att `26 bsd */
X`09int n;
X`09unsigned int calc_crc, file_crc;
X
X`09crc = 0;`09`09`09/* compute a crc for the header */
X`09q_init();`09`09`09/* reset static variables */
X
X`09n = getq();`09`09`09/* namelength */
X`09n++;`09`09&0209/* must read trailing null also */
X`09getqbuf(namebuf, n);`09`09/* read name */
X`09if (macname`5B0`5D == '`5C0')
X`09`09macname = namebuf;
X
X`09n = strlen(macname);
X`09if (n > NAMEBYTES)
X`09`09n = NAMEBYTES;
X`09strncpy(mh.m_name, mac\0906n);
X`09mh.m_name`5Bn`5D = '`5C0';
X
X`09getqbuf(mh.m_type, 4);
X`09getqbuf(mh.m_author, 4);
X`09mh.m_flags = get2q();
X`09mh.m_datalen = get4q();
X`09mh.m_rsrclen = get4q();
X
X`09comp_q_crc(0);
X`09comp_q_crc(0);
X`09calc_crc = crc;
X`09file_crc = get2q();
X`09verify_crc(calc_crc, file_crc);
X`7D
X
Xdo_q_fork(fname, len)
Xchar *fname;
Xregister long len;
X`7B
X`09FILE *outf;
X`09register int c, i;
X`09unsigned int calc_crc, file_crc;
X
X`09outf = fopen(fname, "w");
X`09if (outf == NULL) `7B
X`09`09perror(fname);
X`09`09exit(-1);
X`09`7D
X
X`09crc = 0;`09/* compute a crc for a fork */
X
X`09if (len)
X`09`09for (i = 0; i < len; i++) `7B
X`09`09`09if ((c = getq()) == EOF) `7B
X`09`09&0209fprintf(stderr, "unexpected EOF`5Cn");
X`09`09&0209exit(2);
X`09`09`09`7D
X`09`09`09putc(c, outf);
X`09`09`7D
X
X`09comp_q_crc(0);
X`09comp_q_crc(0);
X`09calc_crc = crc;
X`09file_crc = get2q();
X`09verify_crc(calc_crc, file_crc);
X`09fclose(outf);
X`7D
X
X/* verify_crc(); -- check if crc's\0F07out */
Xverify_crc(calc_crc, file_crc)
Xunsigned int calc_crc, file_crc;
X`7B
X`09calc_crc `26= WORDMASK;
X`09file_crc `26= WORDMASK;
X
X`09if (calc_crc != file_crc) `7B
X`09`09fprintf(stderr, "CRC error`5Cn---------`5Cn");
X`09`09fprintf(stderr, "CRC in file:`5Ct0x%x`5Cn", file_crc);
X`09`09fprintf(stderr, "calculated CRC:`5Ct0x%x`5Cn", calc_crc);
X`09`09exit(3);
X`09`7D
X`7D
X
Xstatic int eof;
Xstatic char obuf`5B3`5D;
Xstatic char *op, *oend;
X
X/* initialize static variables for q format input */
Xq_init()
X`7B
X`09eof = 0;
X`09op = obuf;
X`09oend = obuf + sizeof obuf;
X`7D
X
X/* get2q(); q format -- read 2 bytes from input, return short */
Xshort
Xget2q()
X`7B
X`09register int c;
X`09short value = 0;
X
X`09c = getq();
X`09value = (c `26 BYTEMASK) << 8;
X`09c = getq();
X`09value `7C= (c `26 BYTEMASK);
X
X`09return value;
X`7D
X
X/* get4q(); q format -- read 4 bytes from input, return long */
Xlong
Xget4q()
X`7B
X`09register int c, i;
X`09long value = 0L;
X
X`09for (i = 0; i < 4; i++) `7B
X`09`09c = getq();
X`09`09value <<= 8;
X`09`09value `7C= (c `26 BYTEMASK);
X`09`7D
X`09return value;
X`7D
X
X/* getqbuf(); q format -- read n characters from input into buf */
X/*`09`09All or nothing -- no partial buffer allowed */
Xgetqbuf(buf, n)
Xregister char *buf;
Xregister int n;
X`7B
X`09register int c, i;
X
X`09for (i = 0; i < n; i++) `7B
X`09`09if ((c = getq()) == EOF)
X`09`09`09return EOF;
X`09`09*buf++ = c;
X`09`7D
X`09return 0;
X`7D
X
X#define RUNCHAR 0x90
X
X/* q format -- return one byte per call, keeping track of run codes */
Xgetq()
X`7B
X`09register int c;
X
X`09if ((c = getq_nocrc()) == EOF)
X`09`09return EOF;
X`09comp_q_crc((unsigned)c);
X`09return c;
X`7D
X
Xgetq_nocrc()
X`7B
X`09static int rep, lastc;
X`09int c;
X
X`09if (rep) `7B
X`09`09rep--;
X`09`09return lastc;
X`09`7D
X`09if ((c = getq_raw()) == EOF) `7B
X`09`09return EOF;
X`09`7D
X`09if (c == RUNCHAR) `7B
X`09`09if ((rep = getq_raw()) == EOF)
X`09`09`09return EOF;
X`09`09if (rep != 0) `7B
X`09`09`09/* already returned one, about to\1707 another */
X`09`09`09rep -= 2;
X`09`09`09return lastc;
X`09`09`7D
X`09`09else `7B
X`09`09`09lastc = RUNCHAR;
X`09`09`09return RUNCHAR;
X`09`09`7D
X`09`7D
X`09else `7B
X`09`09lastc = c;
X`09`09return c;
X`09`7D
X`7D
X
X/* q format -- return next 8 bits from file without interpreting run codes */
V
Xgetq_raw()
X`7B
X`09char ibuf`5B4`5D;
X`09register char *ip = ibuf, *iend\0E07 + sizeof ibuf;
X`09int c;
X
X`09if (op == obuf) `7B
X`09`09for (ip = ibuf; ip < iend; ip++) `7B
X`09`09`09if ((c = get6bits()) == EOF)
X`09`09&0209if (ip <= `26ibuf`5B1`5D)
X`09`09&0209`09return EOF;
X`09`09&0209else if (ip == `26ibuf`5B2`5D)
X`09`09&0209`09eof = 1;
X`09`09&0209else
X`09`09&0209`09eof = 2;
X`09`09`09*ip = c;
X`09`09`7D
X`09`09obuf`5B0`5D = (i\0B07<< 2 `7C ibuf`5B1`5D >> 4);
X`09`09obuf`5B1`5D = (i\0B07<< 4 `7C ibuf`5B2`5D >> 2);
X`09`09obuf`5B2`5D = (i\0B07<< 6 `7C ibuf`5B3`5D);
X`09`7D
X`09if ((eof) `26 (op >= `26obuf`5Beof`5D))
X`09`09return EOF;
X`09c = *op++;
X`09if (op >= oend)
X`09`09op = obuf;
X`09return (c `26 BYTEMASK);
X`7D
X
X/*
Xchar tr`5B`5D = "!`5C"#$%`26'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ`5B`60abc
Vdefhijklmpqr";
X`09     0 123456789abcdef0\1010\201F
X`09     0          \0A061\110F2\210F3`20
Xtrlookup is used to translate by direct \2606.  The input character
Xis an index into trlookup.  If the result is 0xFF, a bad char has been read.
XAdded by:  Dan LaLiberte, l\0906@uiucdcs.Uiuc.ARPA, ihnp4!\1907!\2907
X*/
Xchar trlookup`5B83`5D = `7B `090xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
V
X`09`09`090x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0xFF\0606,
X`09`09`090x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xFF,
X`09`09`090x14, 0x15, 0xFF\0606\0C0C\180D
X`09`09`090x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
X`09`09`090x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0xFF,
X`09`09`090x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0xFF,
X`09`09`090x2C, 0x2D, 0x2E, 0x2F, 0xF\0606\0C0CF,
X`09`09`090x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0xFF,
X`09`09`090x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0xFF\0606,
X`09`09`090x3D, 0x3E, 0x3F `7D;
X
X/* q format -- decode one byte into 6 bit binary */
Xget6bits()
X`7B
X`09register int c;
X`09register int tc;
X
X`09while (1) `7B
X`09`09c = getc(ifp);
X`09`09switch (c) `7B
X`09`09case '`5Cn':
X`09`09case '`5Cr':
X`09`09`09continue;
X`09`09case ':':
X`09`09case EOF:
X`09`09`09return EOF;
X`09`09default:
X`09`09 `09tc = ((c-' ') < 83) ? trlookup`5Bc-' '`5D : 0xff;
X/*`09`09`09fprintf(stderr, "c = '%c'  tc = %4x`5Cn", c, tc); */
X`09`09`09if (tc != 0xff)
X`09`09&0209return (tc);
X`09`09`09fprintf(stderr, "bad char: '%c'`5Cn", c);
X`09`09`09return EOF;
X`09`09`7D
X`09`7D
X`7D
X
X
X#define CRCCONSTANT 0x1021
X
Xcomp_q_crc(c)
Xregister unsigned int c;
X`7B
X`09register int i;
X`09register unsigned long temp = crc;
X
X`09for (i=0; i<8; i++) `7B
X`09`09c <<= 1;
X`09`09if ((temp <<= 1) `26 WORDBIT)
X`09`09`09temp = (temp `26 WORDMASK) `5E CRCCONSTANT;
X`09`09temp `5E= (c >> 8);
X`09`09c `26= BYTEMASK;
X`09`7D
X`09crc = temp;
X`7D
X
X/* old format -- process .hex and .hcx files */
Xdo_o_header(macname, filename)
Xchar *macname, *filename;
X`7B
X`09char namebuf`5B256`5D;`09`09/* big enough for both att `26 bsd */
X`09char ibuf`5BBUFSIZ`5D;
X`09int n;
X
X`09/* set up name for output files */
X`09if (macname`5B0`5D == '`5C0') `7B
X`09`09strcpy(namebuf, filename);
X
X`09`09/* strip directories */
X`09`09macname = search_last(namebuf, '/');
X`09`09if (macname == NULL)
X`09`09`09macname = namebuf;
X`09`09else
X`09`09`09macname++;
X
X`09`09/* strip extension */
X`09`09n = strlen(macname);
X`09`09if (n > 4) `7B
X`09`09    n -= 4;
X`09`09    if (macname`5Bn`5D == '.' `26`26 \1509+1\1706h'
X`09`09&0209`09    `26`26 macname`5Bn+3`5D == 'x')
X`09`09`09    macname`5Bn`5D = '`5C0';
X`09`09`7D
X`09`7D
X`09n = strlen(macname);
X`09if (n > NAMEBYTES)
X`09`09n = NAMEBYTES;
X`09strncpy(mh.m_name, mac\0906n);
X`09mh.m_name`5Bn`5D = '`5C0';
X
X`09/* read "#TYPEAUTH$flag"  line */
X`09if (fgets(ibuf, BUFSIZ, ifp) == NULL) `7B
X`09`09fprintf(stderr, "unexpected EOF`5Cn");
X`09`09exit(2);
X`09`7D
X`09n = strlen(ibuf);
X`09if (n >= 7 `26`26 ibuf`5B0`5D == '#'\1209n-6\1406$') `7B
X`09`09if (n >= 11)
X`09`09`09strncpy(mh.m_type, `26ibuf`5B1`5D, 4);
X`09`09if (n >= 15)
X`09`09`09strncpy(mh.m_author, `26ibuf`5B5`5D, 4);
X`09`09sscanf(`26ibuf`5Bn-5`5D, "%4hx", `26mh.m_flags);
X`09`7D
X`7D
X
Xdo_o_forks()
X`7B
X`09char ibuf`5BBUFSIZ`5D;
X`09int forks = 0, found_crc = 0;
X`09unsigned int calc_crc, file_crc;
X`09extern long make_file();
X
X
X`09crc = 0;`09/* calculate a crc for both forks */
X
X`09/* create empty files ahead of time */
X`09close(creat(files.f_data, 0666));
X`09close(creat(files.f_rsrc, 0666));
X
X`09while (!found_crc `26`26 fgets(ibuf, BUFSIZ, ifp) != NULL) `7B
X`09`09if (forks == 0 `26`26 strncmp(ibuf, "***COMPRESSED", 13) == 0) `7B
X`09`09`09compressed++;
X`09`09`09continue;
X`09`09`7D
X`09`09if (strncmp(ibuf, "***DATA", 7) == 0) `7B
X`09`09`09mh.m_datalen = make_file(files.f_data, compressed);
X`09`09`09forks++;
X`09`09`09continue;
X`09`09`7D
X`09`09if (strncmp(ibuf, "***RESOURCE", 11) == 0) `7B
X`09`09`09mh.m_rsrclen = make_file(files.f_rsrc, compressed);
X`09`09`09forks++;
X`09`09`09continue;
X`09`09`7D
X`09`09if (compressed `26`26 strncmp(ibuf, "***CRC:", 7) == 0) `7B
X`09`09`09found_crc++;
X`09`09`09calc_crc = crc;
X`09`09`09sscanf(`26ibuf`5B7`5D, "%x", `26file_crc);
X`09`09`09break;
X`09`09`7D
X`09`09if (!compressed `26`26 strncmp(ibuf, "***CHECKSUM:", 12) == 0) `7B
X`09`09`09found_crc++;
X`09`09`09calc_crc = crc `26 BYTEMASK;
X`09`09`09sscanf(`26ibuf`5B12`5D, "%x", `26file_crc);
X`09`09`09file_crc `26= BYTEMASK;
X`09`09`09break;
X`09`09`7D
X`09`7D
X
X`09if (found_crc)
X`09`09verify_crc(calc_crc, file_crc);
X`09else `7B
X`09`09fprintf(stderr, "missing CRC`5Cn");
X`09`09exit(3);
X`09`7D
X`7D
X
Xlong
Xmake_file(fname, compressed)
Xchar *fname;
Xint compressed;
X`7B
X`09char ibuf`5BBUFSIZ`5D;
X`09FILE *outf;
X`09register long nbytes = 0L;
X
X`09outf = fopen(fname, "w");
X`09if (outf == NULL) `7B
X`09`09perror(fname);
X`09`09exit(-1);
X`09`7D
X
X`09while (fgets(ibuf, BUFSIZ, ifp) != NULL) `7B
X`09`09if (strncmp(ibuf, "***END", 6) == 0)
X`09`09`09break;
X`09`09if (compressed)
X`09`09`09nbytes += comp_to_bin(ibuf, outf);
X`09`09else
X`09`09`09nbytes += hex_to_bin(ibuf, outf);
X`09`7D
X
X`09fclose(outf);
X`09return nbytes;
X`7D
X
Xcomp_c_crc(c)
Xunsigned char c;
X`7B
X`09crc = (crc + c) `26 WORDMASK;
X`09crc = ((crc << 3) `26 WORDMASK) `7C (crc >> 13);
X`7D
X
Xcomp_e_crc(c)
Xunsigned char c;
X`7B
X`09crc += c;
X`7D
X
X#define SIXB(c) (((c)-0x20) `26 0x3f)
X
Xcomp_to_bin(ibuf, outf)
Xchar ibuf`5B`5D;
XFILE *outf;
X`7B
X`09char obuf`5BBUFSIZ`5D;
X`09register char *ip = ibuf;
X`09register char *op = obuf;
X`09register int n, outcount;
X`09int numread, incount;
X
X`09numread = strlen(ibuf);
X`09ip`5Bnumread-1`5D = ' ';`09`09/* zap out the newline */
X`09outcount = (SIXB(ip`5B0`5D) << 2) `7C\150A1`5D) >> 4);
X`09incount = ((out\0D06/ 3) + 1) * 4;
X`09for (n = numread; n < incount; n++)`09/* restore lost spaces */
X`09`09ibuf`5Bn`5D = ' ';
X
X`09n = 0;
X`09while (n <= outcount) `7B
X`09`09*op++ = SIXB(ip`5B0`5D) << 2 `7C\13091`5D) >> 4;
X`09`09*op++ = SIXB(ip`5B1`5D) << 4 `7C\13092`5D) >> 2;
X`09`09*op++ = SIXB(ip`5B2`5D) << 6 `7C\13093`5D);
X`09`09ip += 4;
X`09`09n += 3;
X`09`7D
X
X`09for (n=1; n <= outcount; n++)
X`09`09comp_c_crc((unsigned)obuf`5Bn`5D);
X
X`09fwrite(obuf+1, 1, outcount, outf);
X`09return outcount;
X`7D
X
Xhex_to_bin(ibuf, outf)
Xchar ibuf`5B`5D;
XFILE *outf;
X`7B
X`09register char *ip = ibuf;
X`09register int n, outcount;
X`09int c;
X
X`09n = strlen(ibuf) - 1;
X`09outcount = n / 2;
X`09for (n = 0; n < outcount; n++) `7B
X`09`09c = hexit(*ip++);
X`09`09comp_e_crc((unsigned)(c = (c << 4) `7C hexit(*ip++)));
X`09`09fputc(c, outf);
X`09`7D
X`09return outcount;
X`7D
X
Xhexit(c)
Xint c;
X`7B
X`09if ('0' <= c `26`26 c <= '9')
X`09`09return c - '0';
X`09if ('A' <= c `26`26 c <= 'F')
X`09`09return c - 'A' + 10;
X
X`09fprintf(stderr, "illegal hex digit: %c", c);
X`09exit(4);
X`09/* NOTREACHED */
X`7D
X
Xput2(bp, value)
Xchar *bp;
Xshort value;
X`7B
X`09*bp++ = (value >> 8) `26 BYTEMASK;
X`09*bp++ = value `26 BYTEMASK;
X`7D
X
Xput4(bp, value)
Xchar *bp;
Xlong value;
X`7B
X`09register int i, c;
X
X`09for (i = 0; i < 4; i++) `7B
X`09`09c = (value >> 24) `26 BYTEMASK;
X`09`09value <<= 8;
X`09`09*bp++ = c;
X`09`7D
X`7D
$ call unpack [.XBIN.SRC]XBIN.C;3 -
 1610971042 "FORMAT STREAM_LF;CARRIAGE_CONTROL CARRIAGE_RETURN" 39 12 16
$!
$ create 'f'
X#ifndef lint
Xstatic char version`5B`5D = "xbin.c V\1406 2.3 09/30/85";
X#endif lint
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X
X#ifdef MAXNAMLEN`09/* 4.2 BSD */
X#define FNAMELEN MAXNAMLEN
X#else
X#define FNAMELEN DIRSIZ
X#endif
X
X#ifdef BSD
X#include <sys/time.h>
X#include <sys/timeb.h>
X#define search_last rindex
Xextern char *rindex();
X#else
X#include <time.h>
Xextern long timezone;
X#define search_last strrchr
Xextern char *strrchr();
X#endif
X
X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
X#define TIMEDIFF 0x7c25b080
X
X#define DATABYTES 128
X
X#define BYTEMASK 0xff
X#define BYTEBIT 0x100
X#define WORDMASK 0xffff
X#define WORDBIT 0x10000
X
X#define NAMEBYTES 63
X#define H_NLENOFF 1
X#define H_NAMEOFF 2
X
X/* 65 <-> 80 is the FInfo structure */
X#define H_TYPEOFF 65
X#define H_AUTHOFF 69
X#define H_FLAGOFF 73
X
X#define H_LOCKOFF 81
X#define H_DLENOFF 83
X#define H_RLENOFF 87
X#define H_CTIMOFF 91
X#define H_MTIMOFF 95
X
X#define H_OLD_DLENOFF 81
X#define H_OLD_RLENOFF 85
X
X#define F_BUNDLE 0x2000
X#define F_LOCKED 0x8000
X
Xstruct macheader `7B
X`09char m_name`5BNAMEBYTES+1`5D;
X`09char m_type`5B4`5D;
X`09char m_author`5B4`5D;
X`09short m_flags;
X`09long m_datalen;
X`09long m_rsrclen;
X`09long m_createtime;
X`09long m_modifytime;
X`7D mh;
X
Xstruct filenames `7B
X`09char f_info`5B256`5D;
X`09char f_data`5B256`5D;
X`09char f_rsrc`5B256`5D;
X`7D files;
X
Xint pre_beta;`09/* options */
Xint listmode;
Xint verbose;
X
Xint compressed;`09/* state variables */
Xint qformat;
XFILE *ifp;
X
X/*
X * xbin -- unpack BinHex format file into suitable
X * format for downloading with macput
X * Dave Johnson, Brown University Computer Science
X *
X * (c) 1984 Brown University
X * may be used but not sold without permission
X *
X * created ddj 12/16/84
X * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
X * revised ddj 03/11/85 -- strip LOCKED bit from m_flags
X * revised ahm 03/12/85 -- System V compatibility
X * revised dba 03/16/85 -- (Darin Adler, TMQ Software)  4.0 EOF fixed,
X *`09`09`09   4.0 checksum added
X * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
X * revised ddj 03/24/85 -- check for filename truncation, allow multiple files
V
X * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
X * revised jcb 03/30/85 -- (Jim Budler, amdcad!jimb), \3308for compatibility
X *`09`09`09   with 16-bit int machines
X * revised dl  06/16/85 -- (Dan LaLiberte, l\0906@uiucdcs) character
X *`09`09`09   translation speedup
X * revised ddj 09/30/85 -- fixed problem with run of RUNCHAR
X */
Xchar usage`5B`5D = "usage: `5C"xbin `5B-v`5D `5B-l`5D `5B-o`5D `5B-n name`5D`20
V`5B-`5D filename`5C"`5Cn";
X
Xmain(ac, av)
Xchar **av;
X`7B
X`09char *filename, *macname;
X
X`09filename = ""; mac\0E0A
X`09ac--; av++;
X`09while (ac) `7B
X`09`09if (av`5B0`5D`5B0`5D == '-') `7B
X`09`09`09switch (av`5B0`5D`5B1`5D) `7B
X`09`09`09case '`5C0':
X`09`09&0209filename = "-";
X`09`09&0209break;
X`09`09`09case 'v':
X`09`09&0209verbose++;
X`09`09&0209break;
X`09`09`09case 'l':
X`09`09&0209listmode++;
X`09`09&0209break;
X`09`09`09case 'o':
X`09`09&0209pre_beta++;
X`09`09&0209break;
X`09`09`09case 'n':
X`09`09&0209if (ac > 1) `7B
X`09`09&0209`09ac--; av++;
X`09`09&0209`09macname = av`5B0`5D;
X`09`09&0209`09filename = "";
X`09`09&0209`09break;
X`09`09&0209`7D
X`09`09&0209else
X`09`09&0209`09goto bad_usage;
X`09`09`09default:
X`09`09&0209goto bad_usage;
X`09`09`09`7D
X`09`09`7D
X`09`09else
X`09`09`09filename = av`5B0`5D;
X`09`09if (filename`5B0`5D != '`5C0') `7B
X`09`09`09setup_files(filename, macname);
X`09`09`09if (listmode) `7B
X`09`09&0209print_header();
X`09`09`09`7D
X`09`09`09else `7B
X`09`09&0209process_forks();
X`09`09&0209/* now that we k\0D06e size of the forks */
X`09`09&0209forge_info();
X`09`09`09`7D
X`09`09`09if (ifp != stdin)
X`09`09&0209fclose(ifp);
X`09`09`09macname = "";
X`09`09`09ifp = NULL;&0209/* reset state */
X`09`09`09qformat = 0;
X`09`09`09compressed = 0;
X`09`09`7D
X`09`09ac--; av++;
X`09`7D
X`09if (*filename == '`5C0') `7B
Xbad_usage:
X`09`09fprintf(stderr, usage);
X`09`09exit(1);
X`09`7D
X`7D
X
Xstatic char *extensions`5B`5D = `7B
X`09".hqx",
X`09".hcx",
X`09".hex",
X`09"",
X`09NULL
X`7D;
X
Xsetup_files(filename, macname)
Xchar *filename;`09`09/* input file name -- extension optional */
Xchar *macname;`09`09/* name to use on the mac side of things */
X`7B
X`09char namebuf`5B256`5D, *np;
X`09char **ep;
X`09int n;
X`09struct stat stbuf;
X`09long curtime;
X
X`09if (filename`5B0`5D == '-') `7B
X`09`09ifp = stdin;
X`09`09filename = "stdin";
X`09`7D
X`09else `7B
X`09`09/* find input file and open it */
X`09`09for (ep = extensions; *ep != NULL; ep++) `7B
X`09`09`09sprintf(namebuf, "%s%s", filename, *ep);
X`09`09`09if (stat(namebuf, `26stbuf) == 0)
X`09`09&0209break;
X`09`09`7D
X`09`09if (*ep == NULL) `7B
X`09`09`09perror(namebuf);
X`09`09`09exit(-1);
X`09`09`7D
X`09`09ifp = fopen(namebuf, "r");
X`09`09if (ifp == NULL) `7B
X`09`09`09perror(namebuf);
X`09`09`09exit(-1);
X`09`09`7D
X`09`7D
X`09if (ifp == stdin) `7B
X`09`09curtime = time(0);
X`09`09mh.m_createtime = curtime;
X`09`09mh.m_modifytime = curtime;
X`09`7D
X`09else `7B
X`09`09mh.m_createtime = stbuf.st_mtime;
X`09`09mh.m_modifytime = stbuf.st_mtime;
X`09`7D
X`09if (listmode `7C`7C verbose) `7B
X`09`09fprintf(stderr, "%s %s%s",
X`09`09`09listmode ? "`5CnListing" : "Converting",
X`09`09`09namebuf, listmode ? ":`5Cn" : " ");
X`09`7D
X
X`09qformat = find_header(); /* eat mailer \1806 `26cetera, intuit \3D07*/
X
X`09if (qformat)
X`09`09do_q_header(macname);
X`09else
X`09`09do_o_header(macname, filename);
X
X`09/* make sure host file name doesn't get truncated beyond recognition */
X`09n = strlen(mh.m_name);
X`09if (n > FNAMELEN - 2)
X`09`09n = FNAMELEN - 2;
X`09strncpy(namebuf, mh.m_name, n);
X`09namebuf`5Bn`5D = '`5C0';
X
X`09/* get rid of troublesome characters */
X`09for (np = namebuf; *np; np++)
X`09`09if (*np == ' ' `7C`7C \0E08/')
X`09`09`09*np = '_';
X
X`09sprintf(files.f_data, "%s.data", namebuf);
X`09sprintf(files.f_rsrc, "%s.rsrc", namebuf);
X`09sprintf(files.f_info, "%s.info", namebuf);
X`09if (verbose)
X`09`09fprintf(stderr, "==> %s.`7Binfo,data,rsrc`7D`5Cn", namebuf);
X`7D
X
X/* print out header information in human-readable \1C06 */
Xprint_header()
X`7B
X`09char *ctime();
X
X`09printf("macname: %s`5Cn", mh.m_name);
X`09printf("filetype: %.4s, ", mh.m_type);
X`09printf("author: %.4s, ", mh.m_\1606);
X`09printf("flags: 0x%x`5Cn", mh.m_flags);
X`09if (qformat) `7B
X`09`09printf("data length: %ld, ", mh.m_datalen);
X`09`09printf("rsrc length: %ld`5Cn", mh.m_rsrclen);
X`09`7D
X`09if (!pre_beta) `7B
X`09`09printf("create time: %s", ctime(`26mh.m_\1E06time));
X`09`7D
X`7D
X
Xprocess_forks()
X`7B
X`09if (qformat) `7B
X`09`09/* read data and resource forks of .hqx file */
X`09`09do_q_fork(files.f_data, mh.m_datalen);
X`09`09do_q_fork(files.f_rsrc, mh.m_rsrclen);
X`09`7D
X`09else
X`09`09do_o_forks();
X`7D
X
X/* write out .info file from information in the mh structure */
Xforge_info()
X`7B
X`09static char buf`5BDATABYTES`5D;
X`09char *np;
X`09FILE *fp;
X`09int n;
X`09long tdiff;
X`09struct tm *tp;
X#ifdef BSD
X`09struct timeb tbuf;
X#else
X`09long bs;
X#endif
X
X`09for (np = mh.m_name; *np; np++)
X`09`09if (*np == '_') *np = ' ';
X
X`09buf`5BH_NLENOFF`5D = n = np - mh.m_name;
X`09strncpy(buf + H_NAMEOFF, mh.m_name, n);
X`09strncpy(buf + H_TYPEOFF, mh.m_type, 4);
X`09strncpy(buf + H_AUTHOFF, mh.m_author, 4);
X`09put2(buf + H_FLAGOFF, mh.m_flags `26 `7EF_LOCKED);
X`09if (pre_beta) `7B
X`09`09put4(buf + H_OLD_DLENOFF, mh.m_datalen);
X`09`09put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
X`09`7D
X`09else `7B
X`09`09put4(buf + H_DLENOFF, mh.m_datalen);
X`09`09put4(buf + H_RLENOFF, mh.m_rsrclen);
X
X`09`09/* convert unix file time to mac\0C06format */
X#ifdef BSD
X`09`09ftime(`26tbuf);
X`09`09tp = localtime(`26tbuf.time);
X`09`09tdiff = TIMEDIFF - tbuf.timezone * 60;
X`09`09if (tp->tm_isdst)
X`09`09`09tdiff += 60 * 60;
X#else
X`09`09/* I hope this is right! -andy */
X`09`09time(`26bs);
X`09`09tp = localtime(`26bs);
X`09`09tdiff = TIMEDIFF - timezone;
X`09`09if (tp->tm_isdst)
X`09`09`09tdiff += 60 * 60;
X#endif
X`09`09put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
X`09`09put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
X`09`7D
X`09fp = fopen(files.f_info, "w");
X`09if (fp == NULL) `7B
X`09`09perror("info file");
X`09`09exit(-1);
X`09`7D
X`09fwrite(buf, 1, DATABYTES, fp);
X`09fclose(fp);
X`7D
X
X/* eat characters until header detected, return which format */
Xfind_header()
X`7B
X`09int c, at_bol;
X`09char ibuf`5BBUFSIZ`5D;
X
X`09/* look for "(This file ...)" line */
X`09while (fgets(ibuf, BUFSIZ, ifp) != NULL) `7B
X`09`09if (strncmp(ibuf, "(This file", 10) == 0)
X`09`09`09break;
X`09`7D
X`09at_bol = 1;
X`09while ((c = getc(ifp)) != EOF) `7B
X`09`09switch (c) `7B
X`09`09case '`5Cn':
X`09`09case '`5Cr':
X`09`09`09at_bol = 1;
X`09`09`09break;
X`09`09case ':':
X`09`09`09if (at_bol)`09/* q format */
X`09`09&0209return 1;
X`09`09`09break;
X`09`09case '#':
X`09`09`09if (at_bol) `7B`09/* old format */
X`09`09&0209ungetc(c, ifp);
X`09`09&0209return 0;
X`09`09`09`7D
X`09`09`09break;
X`09`09default:
X`09`09`09at_bol = 0;
X`09`09`09break;
X`09`09`7D
X`09`7D
X
X`09fprintf(stderr, "unexpected EOF`5Cn");
X`09exit(2);
X`09/* NOTREACHED */
X`7D
X
Xstatic unsigned int crc;
X
Xshort get2q();
Xlong get4q();
X
X/* read header of .hqx file */
Xdo_q_header(macname)
Xchar *macname;
X`7B
X`09char namebuf`5B256`5D;`09`09/* big enough for both att `26 bsd */
X`09int n;
X`09unsigned int calc_crc, file_crc;
X
X`09crc = 0;`09`09`09/* compute a crc for the header */
X`09q_init();`09`09`09/* reset static variables */
X
X`09n = getq();`09`09`09/* namelength */
X`09n++;`09`09&0209/* must read trailing null also */
X`09getqbuf(namebuf, n);`09`09/* read name */
X`09if (macname`5B0`5D == '`5C0')
X`09`09macname = namebuf;
X
X`09n = strlen(macname);
X`09if (n > NAMEBYTES)
X`09`09n = NAMEBYTES;
X`09strncpy(mh.m_name, mac\0906n);
X`09mh.m_name`5Bn`5D = '`5C0';
X
X`09getqbuf(mh.m_type, 4);
X`09getqbuf(mh.m_author, 4);
X`09mh.m_flags = get2q();
X`09mh.m_datalen = get4q();
X`09mh.m_rsrclen = get4q();
X
X`09comp_q_crc(0);
X`09comp_q_crc(0);
X`09calc_crc = crc;
X`09file_crc = get2q();
X`09verify_crc(calc_crc, file_crc);
X`7D
X
Xdo_q_fork(fname, len)
Xchar *fname;
Xregister long len;
X`7B
X`09FILE *outf;
X`09register int c, i;
X`09unsigned int calc_crc, file_crc;
X
X`09outf = fopen(fname, "w");
X`09if (outf == NULL) `7B
X`09`09perror(fname);
X`09`09exit(-1);
X`09`7D
X
X`09crc = 0;`09/* compute a crc for a fork */
X
X`09if (len)
X`09`09for (i = 0; i < len; i++) `7B
X`09`09`09if ((c = getq()) == EOF) `7B
X`09`09&0209fprintf(stderr, "unexpected EOF`5Cn");
X`09`09&0209exit(2);
X`09`09`09`7D
X`09`09`09putc(c, outf);
X`09`09`7D
X
X`09comp_q_crc(0);
X`09comp_q_crc(0);
X`09calc_crc = crc;
X`09file_crc = get2q();
X`09verify_crc(calc_crc, file_crc);
X`09fclose(outf);
X`7D
X
X/* verify_crc(); -- check if crc's\0F07out */
Xverify_crc(calc_crc, file_crc)
Xunsigned int calc_crc, file_crc;
X`7B
X`09calc_crc `26= WORDMASK;
X`09file_crc `26= WORDMASK;
X
X`09if (calc_crc != file_crc) `7B
X`09`09fprintf(stderr, "CRC error`5Cn---------`5Cn");
X`09`09fprintf(stderr, "CRC in file:`5Ct0x%x`5Cn", file_crc);
X`09`09fprintf(stderr, "calculated CRC:`5Ct0x%x`5Cn", calc_crc);
X`09`09exit(3);
X`09`7D
X`7D
X
Xstatic int eof;
Xstatic char obuf`5B3`5D;
Xstatic char *op, *oend;
X
X/* initialize static variables for q format input */
Xq_init()
X`7B
X`09eof = 0;
X`09op = obuf;
X`09oend = obuf + sizeof obuf;
X`7D
X
X/* get2q(); q format -- read 2 bytes from input, return short */
Xshort
Xget2q()
X`7B
X`09register int c;
X`09short value = 0;
X
X`09c = getq();
X`09value = (c `26 BYTEMASK) << 8;
X`09c = getq();
X`09value `7C= (c `26 BYTEMASK);
X
X`09return value;
X`7D
X
X/* get4q(); q format -- read 4 bytes from input, return long */
Xlong
Xget4q()
X`7B
X`09register int c, i;
X`09long value = 0L;
X
X`09for (i = 0; i < 4; i++) `7B
X`09`09c = getq();
X`09`09value <<= 8;
X`09`09value `7C= (c `26 BYTEMASK);
X`09`7D
X`09return value;
X`7D
X
X/* getqbuf(); q format -- read n characters from input into buf */
X/*`09`09All or nothing -- no partial buffer allowed */
Xgetqbuf(buf, n)
Xregister char *buf;
Xregister int n;
X`7B
X`09register int c, i;
X
X`09for (i = 0; i < n; i++) `7B
X`09`09if ((c = getq()) == EOF)
X`09`09`09return EOF;
X`09`09*buf++ = c;
X`09`7D
X`09return 0;
X`7D
X
X#define RUNCHAR 0x90
X
X/* q format -- return one byte per call, keeping track of run codes */
Xgetq()
X`7B
X`09register int c;
X
X`09if ((c = getq_nocrc()) == EOF)
X`09`09return EOF;
X`09comp_q_crc((unsigned)c);
X`09return c;
X`7D
X
Xgetq_nocrc()
X`7B
X`09static int rep, lastc;
X`09int c;
X
X`09if (rep) `7B
X`09`09rep--;
X`09`09return lastc;
X`09`7D
X`09if ((c = getq_raw()) == EOF) `7B
X`09`09return EOF;
X`09`7D
X`09if (c == RUNCHAR) `7B
X`09`09if ((rep = getq_raw()) == EOF)
X`09`09`09return EOF;
X`09`09if (rep != 0) `7B
X`09`09`09/* already returned one, about to\1707 another */
X`09`09`09rep -= 2;
X`09`09`09return lastc;
X`09`09`7D
X`09`09else `7B
X`09`09`09lastc = RUNCHAR;
X`09`09`09return RUNCHAR;
X`09`09`7D
X`09`7D
X`09else `7B
X`09`09lastc = c;
X`09`09return c;
X`09`7D
X`7D
X
X/* q format -- return next 8 bits from file without interpreting run codes */
V
Xgetq_raw()
X`7B
X`09char ibuf`5B4`5D;
X`09register char *ip = ibuf, *iend\0E07 + sizeof ibuf;
X`09int c;
X
X`09if (op == obuf) `7B
X`09`09for (ip = ibuf; ip < iend; ip++) `7B
X`09`09`09if ((c = get6bits()) == EOF)
X`09`09&0209if (ip <= `26ibuf`5B1`5D)
X`09`09&0209`09return EOF;
X`09`09&0209else if (ip == `26ibuf`5B2`5D)
X`09`09&0209`09eof = 1;
X`09`09&0209else
+-+-+-+-+-+-+-+-  END  OF PART 30 +-+-+-+-+-+-+-+-
================== RFC 822 Headers ==================
Return-Path: VMSSERV@kcl.ac.uk
Received: by galaxy.zko.dec.com (UCX V4.0-10B, OpenVMS V6.2 VAX);
	Mon, 19 Aug 1996 18:16:46 -0400
Received: from newt.kcl.ac.uk by mail11.digital.com (8.7.5/UNX 1.2/1.0/WV)
	id SAA17179; Mon, 19 Aug 1996 18:04:51 -0400 (EDT)
Received: from alder.cc.kcl.ac.uk by newt.kcl.ac.uk with SMTP (PP) 
          id <23400-0@newt.kcl.ac.uk>; Mon, 19 Aug 1996 23:04:26 +0100
Received: by alder.cc.kcl.ac.uk (MX V4.2 AXP) id 737;
          Mon, 19 Aug 1996 23:04:46 EDT
Date: Mon, 19 Aug 1996 23:04:32 BST
From: Kings College London File Server <VMSSERV@kcl.ac.uk>
To: everhart@star.zko.dec.com
Message-ID: <009A71AB.3EF86920.737@alder.cc.kcl.ac.uk>
Subject: XBIN.30-OF-31
