From: endres@uni-muenster.de Subject: Unix hqx->bin tool This is xbin.shar, an unix shell archive containing sources of a program to convert binhex'ed files to macbinary format. It has been on the net as xbin-to-binary for a long time but contained a bug. I fixed it and now it produces correct macbinary files (AFAIK). #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 1995-09-21 11:19 MET DST by . # Source directory was `/home/endres/xbin'. # # Existing files will *not* be overwritten unless `-c' is specified. # This format requires very little intelligence at unshar time. # "if test", "echo", and "sed" may be needed. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 19160 -rw-r--r-- xbin.c # 2572 -rw-r--r-- xbin.1 # 136 -rw-r--r-- xbinary # 153 -rw-r--r-- Makefile # 457 -rw-r--r-- readme # # ============= xbin.c ============== if test -f 'xbin.c' && test X"$1" != X"-c"; then echo 'x - skipping xbin.c (file already exists)' else echo 'x - extracting xbin.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'xbin.c' && X X#ifndef lint Xstatic char version[] = "xbin.c Version 2.2.2 07/16/88"; X#endif lint Xstatic char fname_trans_table[] = X"@ABCDEFGHIJKLMNOPQRSTUVWXYZexxxx_xx#xxxxxxxxxx.x0123456789xxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZxxxx_xabcdefghijklmnopqrstuvwxyzxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZexxxxxxxxxxxxxxxxxxxx0123456789xxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZxxxx_xabcdefghijklmnopqrstuvwxyzxxxxxx"; X X#include X#include X#include X X#ifdef MAXNAMLEN /* 4.2 BSD */ X#define FNAMELEN MAXNAMLEN X#else X#define FNAMELEN DIRSIZ X#endif X X#ifdef BSD X#include X#include X#define search_last rindex Xextern char *rindex(); X#else X#include 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 { X char m_name[NAMEBYTES + 1]; X char m_type[4]; X char m_author[4]; X short m_flags; X long m_datalen; X long m_rsrclen; X long m_createtime; X long m_modifytime; X} mh; X Xstruct filenames { X char f_info[256]; X char f_data[256]; X char f_rsrc[256]; X} files; X Xint pre_beta; /* options */ Xint listmode; Xint verbose; Xint macbinary = 0; X Xint compressed; /* state variables */ Xint qformat; XFILE *ifp; XFILE *fp = NULL; X 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 * checksum code by Darin Adler, TMQ Software X * X * modification to support MacBinary output file by Earle Horton X * uses code from Jim Budler's "macbin.c" X * X * modification to this modification to create correct MacBinary files X * by Johannes Endres (endres@uni-muenster.de) 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 -- 4.0 EOF fixed, 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 X * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files X * revised jcb 03/30/85 -- revised for compatibility with 16-bit int X * revised erh 07/16/88 -- revised to support MacBinary output with "-b" X * revised jne 09/20/95 -- fixed MacBinary output X */ Xchar usage[] = "usage: \"xbin [-v] [-l] [-o] [-b] [-n name] [-] filename\"\n"; X Xmain(ac, av) X char **av; X{ X char *filename, *macname; X int i; X X filename = ""; X macname = ""; X ac--; X av++; X while (ac) { X if (av[0][0] == '-') { X switch (av[0][1]) { X case '\0': X filename = "-"; X break; X case 'v': X verbose++; X break; X case 'l': X listmode++; X break; X case 'o': X pre_beta++; X break; X case 'b': X macbinary = 1; X break; X case 'n': X if (ac > 1) { X ac--; X av++; X macname = av[0]; X filename = ""; X break; X } else X goto bad_usage; X default: X goto bad_usage; X } X } else X filename = av[0]; X if (filename[0] != '\0') { X setup_files(filename, macname); X if (listmode) { X print_header(); X } else X{ X if (macbinary == 1) { X fp = fopen(files.f_info, "w"); X if (fp == NULL) { X perror("output file"); X exit(-1); X } X for(i = 128 ; i-- > 0;) { X putc(0,fp);/* Make space for info. */ X } X } X process_forks(); X /* now that we know the size of the forks */ X if (macbinary == 1) X rewind(fp); X forge_info(); X} X if (ifp != stdin) X fclose(ifp); X macname = ""; X ifp = NULL; /* reset state */ X qformat = 0; X compressed = 0; X } X ac--; X av++; X } X if (*filename == '\0') { Xbad_usage: X fprintf(stderr, usage); X exit(1); X } X} X Xstatic char *extensions[] = { X ".hqx", X ".hcx", X ".hex", X "", X NULL X}; X Xsetup_files(filename, macname) X char *filename; /* input file name -- extension X * optional */ X char *macname;/* name to use on the mac side of things */ X{ X char namebuf[256], *np; X char **ep; X int n; X struct stat stbuf; X long curtime; X X if (filename[0] == '-') { X ifp = stdin; X filename = "stdin"; X } else { X /* find input file and open it */ X for (ep = extensions; *ep != NULL; ep++) { X sprintf(namebuf, "%s%s", filename, *ep); X if (stat(namebuf, &stbuf) == 0) X break; X } X if (*ep == NULL) { X perror(namebuf); X exit(-1); X } X ifp = fopen(namebuf, "r"); X if (ifp == NULL) { X perror(namebuf); X exit(-1); X } X } X if (ifp == stdin) { X curtime = time(0); X mh.m_createtime = curtime; X mh.m_modifytime = curtime; X } else { X mh.m_createtime = stbuf.st_mtime; X mh.m_modifytime = stbuf.st_mtime; X } X if (listmode || verbose) { X fprintf(stderr, "%s %s%s", X listmode ? "\nListing" : "Converting", X namebuf, listmode ? ":\n" : " "); X } X qformat = find_header();/* eat mailer header &cetera, intuit format */ X X if (qformat) X do_q_header(macname); X else X do_o_header(macname, filename); X X /* make sure host file name doesn't get truncated beyond recognition */ X n = strlen(mh.m_name); X if (n > FNAMELEN - 2) X n = FNAMELEN - 2; X strncpy(namebuf, mh.m_name, n); X namebuf[n] = '\0'; X X /* get rid of troublesome characters */ X for (np = namebuf; *np; np++) X /* Negative chars on some systems make lousy subscripts. */ X *np = fname_trans_table[(unsigned) *np]; X X if ((macbinary == 1)) { X sprintf(files.f_info, "%s.bin", namebuf); X } else { X sprintf(files.f_data, "%s.data", namebuf); X sprintf(files.f_rsrc, "%s.rsrc", namebuf); X sprintf(files.f_info, "%s.info", namebuf); X } X if (verbose) { X if ((macbinary == 1)) X fprintf(stderr, "==> %s.bin\n", namebuf); X else X fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf); X } X} X X/* print out header information in human-readable format */ Xprint_header() X{ X char *ctime(); X X printf("macname: %s\n", mh.m_name); X printf("filetype: %.4s, ", mh.m_type); X printf("author: %.4s, ", mh.m_author); X printf("flags: 0x%x\n", mh.m_flags); X if (qformat) { X printf("data length: %ld, ", mh.m_datalen); X printf("rsrc length: %ld\n", mh.m_rsrclen); X } X if (!pre_beta) { X printf("create time: %s", ctime(&mh.m_createtime)); X } X} X Xprocess_forks() X{ X if (qformat) { X /* read data and resource forks of .hqx file */ X do_q_fork(files.f_data, mh.m_datalen); X do_q_fork(files.f_rsrc, mh.m_rsrclen); X } else X do_o_forks(); X} X X/* write out .info file from information in the mh structure */ Xforge_info() X{ X static char buf[DATABYTES]; X char *np; X int n; X long tdiff; X struct tm *tp; X#ifdef BSD X struct timeb tbuf; X#else X long bs; X#endif X X for (np = mh.m_name; *np; np++) X if (*np == '_') X *np = ' '; X X buf[H_NLENOFF] = n = np - mh.m_name; X strncpy(buf + H_NAMEOFF, mh.m_name, n); X strncpy(buf + H_TYPEOFF, mh.m_type, 4); X strncpy(buf + H_AUTHOFF, mh.m_author, 4); X put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED); X if (pre_beta) { X put4(buf + H_OLD_DLENOFF, mh.m_datalen); X put4(buf + H_OLD_RLENOFF, mh.m_rsrclen); X } else { X put4(buf + H_DLENOFF, mh.m_datalen); X put4(buf + H_RLENOFF, mh.m_rsrclen); X X /* convert unix file time to mac time format */ X#ifdef BSD X ftime(&tbuf); X tp = localtime(&tbuf.time); X tdiff = TIMEDIFF - tbuf.timezone * 60; X if (tp->tm_isdst) X tdiff += 60 * 60; X#else X /* I hope this is right! -andy */ X time(&bs); X tp = localtime(&bs); X tdiff = TIMEDIFF - timezone; X if (tp->tm_isdst) X tdiff += 60 * 60; X#endif X put4(buf + H_CTIMOFF, mh.m_createtime + tdiff); X put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff); X } X if (fp == NULL) { X fp = fopen(files.f_info, "w"); X if (fp == NULL) { X perror("info file"); X exit(-1); X } X } X if (macbinary == 1) { X if (buf[74] & 0x40) X buf[81] = '\1'; /* protected */ X buf[74] = '\0'; /* MacBinary identifiers */ X buf[82] = '\0'; X } X fwrite(buf, 1, DATABYTES, fp); X fclose(fp); X fp = NULL; X} X X/* eat characters until header detected, return which format */ Xfind_header() X{ X int c, at_bol; X char ibuf[BUFSIZ]; X X /* look for "(This file ...)" line */ X while (fgets(ibuf, BUFSIZ, ifp) != NULL) { X if (strncmp(ibuf, "(This file", 10) == 0) X break; X } X at_bol = 1; X while ((c = getc(ifp)) != EOF) { X switch (c) { X case '\n': X case '\r': X at_bol = 1; X break; X case ':': X if (at_bol) /* q format */ X return 1; X break; X case '#': X if (at_bol) { /* old format */ X ungetc(c, ifp); X return 0; X } X break; X default: X at_bol = 0; X break; X } X } X X fprintf(stderr, "unexpected EOF\n"); X exit(2); X /* NOTREACHED */ X} X Xstatic unsigned int crc; X Xshort get2q(); Xlong get4q(); X X/* read header of .hqx file */ Xdo_q_header(macname) X char *macname; X{ X char namebuf[256]; /* big enough for both att & bsd */ X int n; X int calc_crc, file_crc; X X crc = 0; /* compute a crc for the header */ X q_init(); /* reset static variables */ X X n = getq(); /* namelength */ X n++; /* must read trailing null also */ X getqbuf(namebuf, n); /* read name */ X if (macname[0] == '\0') X macname = namebuf; X X n = strlen(macname); X if (n > NAMEBYTES) X n = NAMEBYTES; X strncpy(mh.m_name, macname, n); X mh.m_name[n] = '\0'; X X getqbuf(mh.m_type, 4); X getqbuf(mh.m_author, 4); X mh.m_flags = get2q(); X mh.m_datalen = get4q(); X mh.m_rsrclen = get4q(); X X comp_q_crc(0); X comp_q_crc(0); X calc_crc = crc; X file_crc = get2q(); X verify_crc(calc_crc, file_crc); X} X Xdo_q_fork(fname, len) X char *fname; X register long len; X{ X register int c, i; X int calc_crc, file_crc; X X if (macbinary != 1) { X if (fp != NULL) { X fclose(fp); X } X fp = fopen(fname, "w"); X if (fp == NULL) { X perror(fname); X exit(-1); X } X } X crc = 0; /* compute a crc for a fork */ X X if (len) X for (i = 0; i < len; i++) { X if ((c = getq()) == EOF) { X fprintf(stderr, "unexpected EOF\n"); X exit(2); X } X putc(c, fp); X } X X comp_q_crc(0); X comp_q_crc(0); X calc_crc = crc; X file_crc = get2q(); X verify_crc(calc_crc, file_crc); X if (macbinary != 1) { X fclose(fp); X fp = NULL; X }else{ X/* Q&D hack: both forks have to be padded to next multiple of 128 */ X if(calc_crc=len%128) X for(;calc_crc<128;calc_crc++) X putc(0,fp); X } X} X X/* verify_crc(); -- check if crc's check out */ Xverify_crc(calc_crc, file_crc) X unsigned int calc_crc, file_crc; X{ X calc_crc &= WORDMASK; X file_crc &= WORDMASK; X X if (calc_crc != file_crc) { X fprintf(stderr, "CRC error\n---------\n"); X fprintf(stderr, "CRC in file:\t0x%x\n", file_crc); X fprintf(stderr, "calculated CRC:\t0x%x\n", calc_crc); X exit(3); X } X} X Xstatic int eof; Xstatic char obuf[3]; Xstatic char *op, *oend; X X/* initialize static variables for q format input */ Xq_init() X{ X eof = 0; X op = obuf; X oend = obuf + sizeof obuf; X} X X/* get2q(); q format -- read 2 bytes from input, return short */ Xshort Xget2q() X{ X register int c; X short value = 0; X X c = getq(); X value = (c & BYTEMASK) << 8; X c = getq(); X value |= (c & BYTEMASK); X X return value; X} X X/* get4q(); q format -- read 4 bytes from input, return long */ Xlong Xget4q() X{ X register int c, i; X long value = 0L; X X for (i = 0; i < 4; i++) { X c = getq(); X value <<= 8; X value |= (c & BYTEMASK); X } X return value; X} X X/* getqbuf(); q format -- read n characters from input into buf */ X/* All or nothing -- no partial buffer allowed */ Xgetqbuf(buf, n) X register char *buf; X register int n; X{ X register int c, i; X X for (i = 0; i < n; i++) { X if ((c = getq()) == EOF) X return EOF; X *buf++ = c; X } X return 0; X} X X#define RUNCHAR 0x90 X X/* q format -- return one byte per call, keeping track of run codes */ Xgetq() X{ X register int c; X X if ((c = getq_nocrc()) == EOF) X return EOF; X comp_q_crc(c); X return c; X} X Xgetq_nocrc() X{ X static int rep, lastc; X int c; X X if (rep) { X rep--; X return lastc; X } X if ((c = getq_raw()) == EOF) { X return EOF; X } X if (c == RUNCHAR) { X if ((rep = getq_raw()) == EOF) X return EOF; X if (rep == 0) { X return RUNCHAR; X } else { X /* already returned one, about to return another */ X rep -= 2; X return lastc; X } X } else { X lastc = c; X return c; X } X} X X/* q format -- return next 8 bits from file without interpreting run codes */ Xgetq_raw() X{ X char ibuf[4]; X register char *ip = ibuf, *iend = ibuf + sizeof ibuf; X int c; X X if (op == obuf) { X for (ip = ibuf; ip < iend; ip++) { X if ((c = get6bits()) == EOF) X if (ip <= &ibuf[1]) X return EOF; X else if (ip == &ibuf[2]) X eof = 1; X else X eof = 2; X *ip = c; X } X obuf[0] = (ibuf[0] << 2 | ibuf[1] >> 4); X obuf[1] = (ibuf[1] << 4 | ibuf[2] >> 2); X obuf[2] = (ibuf[2] << 6 | ibuf[3]); X } X if ((eof) & (op >= &obuf[eof])) X return EOF; X c = *op++; X if (op >= oend) X op = obuf; X return (c & BYTEMASK); X} X Xchar tr[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; X X/* q format -- decode one byte into 6 bit binary */ Xget6bits() X{ X register int c; X register char *where; X X while (1) { X c = getc(ifp); X switch (c) { X case '\n': X case '\r': X continue; X case ':': X case EOF: X return EOF; X default: X where = tr; X while (*where != '\0' && *where != c) X where++; X if (*where == c) X return (where - tr); X else { X fprintf(stderr, "bad char\n"); X return EOF; X } X } X } X} X X#define CRCCONSTANT 0x1021 X Xcomp_q_crc(c) X register unsigned int c; X{ X register int i; X register unsigned long temp = crc; X X for (i = 0; i < 8; i++) { X c <<= 1; X if ((temp <<= 1) & WORDBIT) X temp = (temp & WORDMASK) ^ CRCCONSTANT; X temp ^= (c >> 8); X c &= BYTEMASK; X } X crc = temp; X} X X/* old format -- process .hex and .hcx files */ Xdo_o_header(macname, filename) X char *macname, *filename; X{ X char namebuf[256]; /* big enough for both att & bsd */ X char ibuf[BUFSIZ]; X int n; X X /* set up name for output files */ X if (macname[0] == '\0') { X strcpy(namebuf, filename); X X /* strip directories */ X macname = search_last(namebuf, '/'); X if (macname == NULL) X macname = namebuf; X else X macname++; X X /* strip extension */ X n = strlen(macname); X if (n > 4) { X n -= 4; X if (macname[n] == '.' && macname[n + 1] == 'h' X && macname[n + 3] == 'x') X macname[n] = '\0'; X } X } X n = strlen(macname); X if (n > NAMEBYTES) X n = NAMEBYTES; X strncpy(mh.m_name, macname, n); X mh.m_name[n] = '\0'; X X /* read "#TYPEAUTH$flag" line */ X if (fgets(ibuf, BUFSIZ, ifp) == NULL) { X fprintf(stderr, "unexpected EOF\n"); X exit(2); X } X n = strlen(ibuf); X if (n >= 7 && ibuf[0] == '#' && ibuf[n - 6] == '$') { X if (n >= 11) X strncpy(mh.m_type, &ibuf[1], 4); X if (n >= 15) X strncpy(mh.m_author, &ibuf[5], 4); X sscanf(&ibuf[n - 5], "%4hx", &mh.m_flags); X } X} X Xdo_o_forks() X{ X char ibuf[BUFSIZ]; X int forks = 0, found_crc = 0; X int calc_crc, file_crc; X extern long make_file(); X X crc = 0; /* calculate a crc for both forks */ X X /* create empty files ahead of time */ X if (macbinary != 1) { X close(creat(files.f_data, 0666)); X close(creat(files.f_rsrc, 0666)); X } X while (!found_crc && fgets(ibuf, BUFSIZ, ifp) != NULL) { X if (forks == 0 && strncmp(ibuf, "***COMPRESSED", 13) == 0) { X compressed++; X continue; X } X if (strncmp(ibuf, "***DATA", 7) == 0) { X mh.m_datalen = make_file(files.f_data, compressed); X forks++; X continue; X } X if (strncmp(ibuf, "***RESOURCE", 11) == 0) { X mh.m_rsrclen = make_file(files.f_rsrc, compressed); X forks++; X continue; X } X if (compressed && strncmp(ibuf, "***CRC:", 7) == 0) { X found_crc++; X calc_crc = crc; X sscanf(&ibuf[7], "%x", &file_crc); X break; X } X if (!compressed && strncmp(ibuf, "***CHECKSUM:", 12) == 0) { X found_crc++; X calc_crc = crc & BYTEMASK; X sscanf(&ibuf[12], "%x", &file_crc); X file_crc &= BYTEMASK; X break; X } X } X X if (found_crc) X verify_crc(calc_crc, file_crc); X else { X fprintf(stderr, "missing CRC\n"); X exit(3); X } X} X Xlong Xmake_file(fname, compressed) X char *fname; X int compressed; X{ X char ibuf[BUFSIZ]; X register long nbytes = 0; X X if (macbinary != 1) { X if (fp != NULL) X fclose(fp); X fp = fopen(fname, "w"); X if (fp == NULL) { X perror(fname); X exit(-1); X } X } X while (fgets(ibuf, BUFSIZ, ifp) != NULL) { X if (strncmp(ibuf, "***END", 6) == 0) X break; X if (compressed) X nbytes += comp_to_bin(ibuf, fp); X else X nbytes += hex_to_bin(ibuf, fp); X } X if (macbinary != 1) { X fclose(fp); X fp = NULL; X } X return nbytes; X} X Xcomp_c_crc(c) X unsigned char c; X{ X crc = (crc + c) & WORDMASK; X crc = ((crc << 3) & WORDMASK) | (crc >> 13); X} X Xcomp_e_crc(c) X unsigned char c; X{ X crc += c; X} X X#define SIXB(c) (((c)-0x20) & 0x3f) X Xcomp_to_bin(ibuf, outf) X char ibuf[]; XFILE *outf; X{ X char obuf[BUFSIZ]; X register char *ip = ibuf; X register char *op = obuf; X register int n, outcount; X int numread, incount; X X numread = strlen(ibuf); X ip[numread - 1] = ' '; /* zap out the newline */ X outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4); X incount = ((outcount / 3) + 1) * 4; X for (n = numread; n < incount; n++) /* restore lost spaces */ X ibuf[n] = ' '; X X n = 0; X while (n <= outcount) { X *op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4; X *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2; X *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]); X ip += 4; X n += 3; X } X X for (n = 1; n <= outcount; n++) X comp_c_crc(obuf[n]); X X fwrite(obuf + 1, 1, outcount, outf); X return outcount; X} X Xhex_to_bin(ibuf, outf) X char ibuf[]; XFILE *outf; X{ X register char *ip = ibuf; X register int n, outcount; X int c; X X n = strlen(ibuf) - 1; X outcount = n / 2; X for (n = 0; n < outcount; n++) { X c = hexit(*ip++); X comp_e_crc(c = (c << 4) | hexit(*ip++)); X fputc(c, outf); X } X return outcount; X} X Xhexit(c) X int c; X{ X if ('0' <= c && c <= '9') X return c - '0'; X if ('A' <= c && c <= 'F') X return c - 'A' + 10; X X fprintf(stderr, "illegal hex digit: %c", c); X exit(4); X /* NOTREACHED */ X} X Xput2(bp, value) X char *bp; X short value; X{ X *bp++ = (value >> 8) & BYTEMASK; X *bp++ = value & BYTEMASK; X} X Xput4(bp, value) X char *bp; X long value; X{ X register int i, c; X X for (i = 0; i < 4; i++) { X c = (value >> 24) & BYTEMASK; X value <<= 8; X *bp++ = c; X } X} SHAR_EOF : || echo 'restore of xbin.c failed' fi # ============= xbin.1 ============== if test -f 'xbin.1' && test X"$1" != X"-c"; then echo 'x - skipping xbin.1 (file already exists)' else echo 'x - extracting xbin.1 (text)' sed 's/^X//' << 'SHAR_EOF' > 'xbin.1' && X.TH XBIN 1L "16 Jul 1988" X.UC 4 X.SH NAME Xxbin \- convert BinHex file to binary before downloading Xto MacTerminal X.SH SYNOPSIS X.B xbin X[ X.B \-o X] X[ X.B \-b X] X[ X.B \-v X] X[ X.B \-l X] X[[ X.B \-n Xname X] file] ... X.SH DESCRIPTION X.I Xbin Xconverts a file created by BinHex (usually Xnamed with one of the extensions ".hex", ".hcx", or ".hqx") Xinto either three host-system files suitable for downloading to a XMacintosh via macput, or a MacBinary format file. XThis program is designed for use with the 1.1 Release Xversion of MacTerminal, but includes a compatibility option for the Xold -0.15X Almost-Alpha version. MacBinary files are compatible Xwith many Macintosh communication programs. X.PP XThe X.B -l X(list) option reads the header information and Xprints out all the useful information there, Xwithout creating any converted output files. X.PP XThe X.B -v X(verbose) option prints a line for each file to be converted, indicating Xthe input and output file names. X.PP XThe X.B -n Xname Xoption allows the user to specify the name to use when creating Xthe host files and the eventual name to use on the mac. XThis option must precede the input file name it is to affect. X.PP XIf this option is not used, the names will be derived from Xeither the input file name (.hex or .hcx files), Xor the name encoded in the header information (.hqx files). XSpaces and slashes will be converted to underscores, and Xthe .h?x extension will be deleted, if one is included in the Xinput file name. X.PP XA file name of "-" indicates that the input should be taken from stdin. XIf no mac file name is specified, the default name (for .hex or .hcx files) Xis "stdin". X.PP XMail or news headers and signatures need not be manually Xstripped -- xbin will ignore pretty much anything Xit doesn't need. X.PP X.I xbin Xcreates three host-system files from each input file: X.IB name .info , X.IB name .data , Xand X.IB name .rsrc . X.PP XThe X.B \-o Xflag specifies "old" (version -0.15X) MacTerminal compatibility mode. X.PP XThe X.B \-b Xflag specifies create a single MacBinary file: X.IB name .bin , Xinstead of the three MacTerminal format files. X.SH BUGS XThe "LOCKED" bit in the flags cannot be set by xbin. XThis is due to a bug in MacTerminal, which sets the flags Xwhen the file is created, rather than after it has been Xtransfered, resulting in it not being able to write the Xfile. X.PP XInput files must contain a line starting with "(This file" Xto detect the beginning of the BinHex information. X.SH SEE ALSO Xmacput(1), macget(1) X.SH AUTHOR XDave Johnson, Brown 12/16/84; XCRC handling code by Darin Adler, TMQ Software 3/16/85 SHAR_EOF : || echo 'restore of xbin.1 failed' fi # ============= xbinary ============== if test -f 'xbinary' && test X"$1" != X"-c"; then echo 'x - skipping xbinary (file already exists)' else echo 'x - extracting xbinary (text)' sed 's/^X//' << 'SHAR_EOF' > 'xbinary' && X#!/bin/csh X# Shell script for always running xbin in MacBinary mode. Make this X# executable and put it in your search path. Xxbin -b $* SHAR_EOF : || echo 'restore of xbinary failed' fi # ============= Makefile ============== if test -f 'Makefile' && test X"$1" != X"-c"; then echo 'x - skipping Makefile (file already exists)' else echo 'x - extracting Makefile (text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && XFILES = xbin.c xbin.1 xbinary Makefile readme XCFLAGS=-O X Xxbin: xbin.o X cc -o xbin xbin.o X Xclean: X rm -f *.o xbin xbin.sh X Xshar: X shar $(FILES) > xbin.sh SHAR_EOF : || echo 'restore of Makefile failed' fi # ============= readme ============== if test -f 'readme' && test X"$1" != X"-c"; then echo 'x - skipping readme (file already exists)' else echo 'x - extracting readme (text)' sed 's/^X//' << 'SHAR_EOF' > 'readme' && X XThis is a small rewrite of xbin to create either macget/macput format Xfiles or MacBinary files from BinHex files. X Xxbin [other options] files: X X .hqx -> .rsrc .info .data X XFiles are suitable for downloading with MacTerminal 1.1 protocol. X Xxbin -b [other options] files X X .hqx -> .bin X XFiles are suitable for downloading with MacBinary protocol, and there Xare one-third as many output files! X XThere is a Makefile, and a new man page. Enjoy! X XEarle Horton SHAR_EOF : || echo 'restore of readme failed' fi exit 0 .