home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / xbntbnry.shr < prev    next >
Text File  |  1991-05-20  |  24KB  |  1,073 lines

  1.  
  2. : This is a shar archive.  Extract with sh, not csh.
  3. echo x - Makefile
  4. sed -e 's/^X//' > Makefile << '!Funky!Stuff!'
  5. XFILES = xbin.c xbin.1 xbinary Makefile readme
  6. XCFLAGS=-O
  7. X
  8. Xxbin:    xbin.o
  9. X    cc -o xbin xbin.o
  10. X
  11. Xclean:
  12. X    rm -f *.o xbin xbin.sh
  13. X
  14. Xshar:
  15. X    shar $(FILES) > xbin.sh
  16. !Funky!Stuff!
  17. echo x - readme
  18. sed -e 's/^X//' > readme << '!Funky!Stuff!'
  19. X
  20. XThis is a small rewrite of xbin to create either macget/macput format
  21. Xfiles or MacBinary files from BinHex files.
  22. X
  23. Xxbin [other options] files:
  24. X
  25. X    .hqx    ->    .rsrc .info .data
  26. X
  27. XFiles are suitable for downloading with MacTerminal 1.1 protocol.
  28. X
  29. Xxbin -b [other options] files
  30. X
  31. X    .hqx    ->    .bin 
  32. X
  33. XFiles are suitable for downloading with MacBinary protocol, and there
  34. Xare one-third as many output files!
  35. X
  36. XThere is a Makefile, and a new man page.  Enjoy!
  37. X
  38. XEarle Horton
  39. !Funky!Stuff!
  40. echo x - xbin.1
  41. sed -e 's/^X//' > xbin.1 << '!Funky!Stuff!'
  42. X.TH XBIN 1L "16 Jul 1988"
  43. X.UC 4
  44. X.SH NAME
  45. Xxbin \- convert BinHex file to binary before downloading
  46. Xto MacTerminal
  47. X.SH SYNOPSIS
  48. X.B xbin
  49. X[
  50. X.B \-o
  51. X]
  52. X[
  53. X.B \-b
  54. X]
  55. X[
  56. X.B \-v
  57. X]
  58. X[
  59. X.B \-l
  60. X]
  61. X[[
  62. X.B \-n
  63. Xname
  64. X] file] ...
  65. X.SH DESCRIPTION
  66. X.I Xbin
  67. Xconverts a file created by BinHex (usually
  68. Xnamed with one of the extensions ".hex", ".hcx", or ".hqx")
  69. Xinto either three host-system files suitable for downloading to a
  70. XMacintosh via macput, or a MacBinary format file.
  71. XThis program is designed for use with the 1.1 Release
  72. Xversion of MacTerminal, but includes a compatibility option for the
  73. Xold -0.15X Almost-Alpha version.  MacBinary files are compatible
  74. Xwith many Macintosh communication programs.
  75. X.PP
  76. XThe 
  77. X.B -l 
  78. X(list) option reads the header information and
  79. Xprints out all the useful information there,
  80. Xwithout creating any converted output files.
  81. X.PP
  82. XThe 
  83. X.B -v 
  84. X(verbose) option prints a line for each file to be converted, indicating
  85. Xthe input and output file names.
  86. X.PP
  87. XThe 
  88. X.B -n
  89. Xname
  90. Xoption allows the user to specify the name to use when creating
  91. Xthe host files and the eventual name to use on the mac.
  92. XThis option must precede the input file name it is to affect.
  93. X.PP
  94. XIf this option is not used, the names will be derived from
  95. Xeither the input file name (.hex or .hcx files),
  96. Xor the name encoded in the header information (.hqx files).
  97. XSpaces and slashes will be converted to underscores, and
  98. Xthe .h?x extension will be deleted, if one is included in the
  99. Xinput file name.
  100. X.PP
  101. XA file name of "-" indicates that the input should be taken from stdin.
  102. XIf no mac file name is specified, the default name (for .hex or .hcx files)
  103. Xis "stdin".
  104. X.PP
  105. XMail or news headers and signatures need not be manually
  106. Xstripped -- xbin will ignore pretty much anything
  107. Xit doesn't need. 
  108. X.PP
  109. X.I xbin 
  110. Xcreates three host-system files from each input file:
  111. X.IB name .info ,
  112. X.IB name .data ,
  113. Xand
  114. X.IB name .rsrc .
  115. X.PP
  116. XThe 
  117. X.B \-o
  118. Xflag specifies "old" (version -0.15X) MacTerminal compatibility mode.
  119. X.PP
  120. XThe
  121. X.B \-b
  122. Xflag specifies create a single MacBinary file:
  123. X.IB name .bin ,
  124. Xinstead of the three MacTerminal format files.
  125. X.SH BUGS
  126. XThe "LOCKED" bit in the flags cannot be set by xbin.
  127. XThis is due to a bug in MacTerminal, which sets the flags
  128. Xwhen the file is created, rather than after it has been
  129. Xtransfered, resulting in it not being able to write the
  130. Xfile.
  131. X.PP
  132. XInput files must contain a line starting with "(This file"
  133. Xto detect the beginning of the BinHex information.
  134. X.SH SEE ALSO
  135. Xmacput(1), macget(1)
  136. X.SH AUTHOR
  137. XDave Johnson, Brown 12/16/84;
  138. XCRC handling code by Darin Adler, TMQ Software 3/16/85
  139. !Funky!Stuff!
  140. echo x - xbin.c
  141. sed -e 's/^X//' > xbin.c << '!Funky!Stuff!'
  142. X
  143. X
  144. X#ifndef lint
  145. Xstatic char     version[] = "xbin.c Version 2.2.2 07/16/88";
  146. X#endif lint
  147. Xstatic char     fname_trans_table[] =
  148. X"@ABCDEFGHIJKLMNOPQRSTUVWXYZexxxxxxx#xxxxxxxxxxxx0123456789xxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZxxxx_xabcdefghijklmnopqrstuvwxyzxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZexxxxxxxxxxxxxxxxxxxx0123456789xxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZxxxx_xabcdefghijklmnopqrstuvwxyzxxxxxx";
  149. X
  150. X#include <stdio.h>
  151. X#include <sys/types.h>
  152. X#include <sys/stat.h>
  153. X#include <sys/dir.h>
  154. X
  155. X#ifdef MAXNAMLEN        /* 4.2 BSD */
  156. X#define FNAMELEN MAXNAMLEN
  157. X#else
  158. X#define FNAMELEN DIRSIZ
  159. X#endif
  160. X
  161. X#ifdef BSD
  162. X#include <sys/time.h>
  163. X#include <sys/timeb.h>
  164. X#define search_last rindex
  165. Xextern char    *rindex();
  166. X#else
  167. X#include <time.h>
  168. Xextern long     timezone;
  169. X#define search_last strrchr
  170. Xextern char    *strrchr();
  171. X#endif
  172. X
  173. X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  174. X#define TIMEDIFF 0x7c25b080
  175. X
  176. X#define DATABYTES 128
  177. X
  178. X#define BYTEMASK 0xff
  179. X#define BYTEBIT 0x100
  180. X#define WORDMASK 0xffff
  181. X#define WORDBIT 0x10000
  182. X
  183. X#define NAMEBYTES 63
  184. X#define H_NLENOFF 1
  185. X#define H_NAMEOFF 2
  186. X
  187. X/* 65 <-> 80 is the FInfo structure */
  188. X#define H_TYPEOFF 65
  189. X#define H_AUTHOFF 69
  190. X#define H_FLAGOFF 73
  191. X
  192. X#define H_LOCKOFF 81
  193. X#define H_DLENOFF 83
  194. X#define H_RLENOFF 87
  195. X#define H_CTIMOFF 91
  196. X#define H_MTIMOFF 95
  197. X
  198. X#define H_OLD_DLENOFF 81
  199. X#define H_OLD_RLENOFF 85
  200. X
  201. X#define F_BUNDLE 0x2000
  202. X#define F_LOCKED 0x8000
  203. X
  204. Xstruct macheader {
  205. X    char            m_name[NAMEBYTES + 1];
  206. X    char            m_type[4];
  207. X    char            m_author[4];
  208. X    short           m_flags;
  209. X    long            m_datalen;
  210. X    long            m_rsrclen;
  211. X    long            m_createtime;
  212. X    long            m_modifytime;
  213. X}               mh;
  214. X
  215. Xstruct filenames {
  216. X    char            f_info[256];
  217. X    char            f_data[256];
  218. X    char            f_rsrc[256];
  219. X}               files;
  220. X
  221. Xint             pre_beta;    /* options */
  222. Xint             listmode;
  223. Xint             verbose;
  224. Xint             macbinary = 0;
  225. X
  226. Xint             compressed;    /* state variables */
  227. Xint             qformat;
  228. XFILE           *ifp;
  229. XFILE           *fp = NULL;
  230. X
  231. X
  232. X/*
  233. X * xbin -- unpack BinHex format file into suitable
  234. X * format for downloading with macput
  235. X * Dave Johnson, Brown University Computer Science
  236. X *
  237. X * checksum code by Darin Adler, TMQ Software
  238. X *
  239. X * modification to support MacBinary output file by Earle Horton
  240. X *  uses code from Jim Budler's "macbin.c"
  241. X *
  242. X * (c) 1984 Brown University 
  243. X * may be used but not sold without permission
  244. X *
  245. X * created ddj 12/16/84 
  246. X * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
  247. X * revised ddj 03/11/85 -- strip LOCKED bit from m_flags
  248. X * revised ahm 03/12/85 -- System V compatibility
  249. X * revised dba 03/16/85 -- 4.0 EOF fixed, 4.0 checksum added
  250. X * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
  251. X * revised ddj 03/24/85 -- check for filename truncation, allow multiple files
  252. X * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
  253. X * revised jcb 03/30/85 -- revised for compatibility with 16-bit int
  254. X * revised erh 07/16/88 -- revised to support MacBinary output with "-b"
  255. X */
  256. Xchar usage[] = "usage: \"xbin [-v] [-l] [-o] [-b] [-n name] [-] filename\"\n";
  257. X
  258. Xmain(ac, av)
  259. X    char          **av;
  260. X{
  261. X    char           *filename, *macname;
  262. X    int            i;
  263. X
  264. X    filename = "";
  265. X    macname = "";
  266. X    ac--;
  267. X    av++;
  268. X    while (ac) {
  269. X        if (av[0][0] == '-') {
  270. X            switch (av[0][1]) {
  271. X            case '\0':
  272. X                filename = "-";
  273. X                break;
  274. X            case 'v':
  275. X                verbose++;
  276. X                break;
  277. X            case 'l':
  278. X                listmode++;
  279. X                break;
  280. X            case 'o':
  281. X                pre_beta++;
  282. X                break;
  283. X            case 'b':
  284. X                macbinary = 1;
  285. X                break;
  286. X            case 'n':
  287. X                if (ac > 1) {
  288. X                    ac--;
  289. X                    av++;
  290. X                    macname = av[0];
  291. X                    filename = "";
  292. X                    break;
  293. X                } else
  294. X                    goto bad_usage;
  295. X            default:
  296. X                goto bad_usage;
  297. X            }
  298. X        } else
  299. X            filename = av[0];
  300. X        if (filename[0] != '\0') {
  301. X            setup_files(filename, macname);
  302. X            if (listmode) {
  303. X                print_header();
  304. X            } else 
  305. X{
  306. X if (macbinary == 1) {
  307. X    fp = fopen(files.f_info, "w");
  308. X    if (fp == NULL) {
  309. X           perror("output file");
  310. X           exit(-1);
  311. X    }
  312. X    for(i = 128 ; i-- > 0;) {
  313. X           putc(0,fp);/* Make space for info. */
  314. X    }
  315. X }
  316. X process_forks();
  317. X /* now that we know the size of the forks */
  318. X if (macbinary == 1)
  319. X rewind(fp);
  320. X forge_info();
  321. X}
  322. X            if (ifp != stdin)
  323. X                fclose(ifp);
  324. X            macname = "";
  325. X            ifp = NULL;    /* reset state */
  326. X            qformat = 0;
  327. X            compressed = 0;
  328. X        }
  329. X        ac--;
  330. X        av++;
  331. X    }
  332. X    if (*filename == '\0') {
  333. Xbad_usage:
  334. X        fprintf(stderr, usage);
  335. X        exit(1);
  336. X    }
  337. X}
  338. X
  339. Xstatic char    *extensions[] = {
  340. X                ".hqx",
  341. X                ".hcx",
  342. X                ".hex",
  343. X                "",
  344. X                NULL
  345. X};
  346. X
  347. Xsetup_files(filename, macname)
  348. X    char           *filename;    /* input file name -- extension
  349. X                     * optional */
  350. X    char           *macname;/* name to use on the mac side of things */
  351. X{
  352. X    char            namebuf[256], *np;
  353. X    char          **ep;
  354. X    int             n;
  355. X    struct stat     stbuf;
  356. X    long            curtime;
  357. X
  358. X    if (filename[0] == '-') {
  359. X        ifp = stdin;
  360. X        filename = "stdin";
  361. X    } else {
  362. X        /* find input file and open it */
  363. X        for (ep = extensions; *ep != NULL; ep++) {
  364. X            sprintf(namebuf, "%s%s", filename, *ep);
  365. X            if (stat(namebuf, &stbuf) == 0)
  366. X                break;
  367. X        }
  368. X        if (*ep == NULL) {
  369. X            perror(namebuf);
  370. X            exit(-1);
  371. X        }
  372. X        ifp = fopen(namebuf, "r");
  373. X        if (ifp == NULL) {
  374. X            perror(namebuf);
  375. X            exit(-1);
  376. X        }
  377. X    }
  378. X    if (ifp == stdin) {
  379. X        curtime = time(0);
  380. X        mh.m_createtime = curtime;
  381. X        mh.m_modifytime = curtime;
  382. X    } else {
  383. X        mh.m_createtime = stbuf.st_mtime;
  384. X        mh.m_modifytime = stbuf.st_mtime;
  385. X    }
  386. X    if (listmode || verbose) {
  387. X        fprintf(stderr, "%s %s%s",
  388. X            listmode ? "\nListing" : "Converting",
  389. X            namebuf, listmode ? ":\n" : " ");
  390. X    }
  391. X    qformat = find_header();/* eat mailer header &cetera, intuit format */
  392. X
  393. X    if (qformat)
  394. X        do_q_header(macname);
  395. X    else
  396. X        do_o_header(macname, filename);
  397. X
  398. X    /* make sure host file name doesn't get truncated beyond recognition */
  399. X    n = strlen(mh.m_name);
  400. X    if (n > FNAMELEN - 2)
  401. X        n = FNAMELEN - 2;
  402. X    strncpy(namebuf, mh.m_name, n);
  403. X    namebuf[n] = '\0';
  404. X
  405. X    /* get rid of troublesome characters */
  406. X    for (np = namebuf; *np; np++)
  407. X        /* Negative chars on some systems make lousy subscripts. */
  408. X        *np = fname_trans_table[(unsigned) *np];
  409. X
  410. X    if ((macbinary == 1)) {
  411. X        sprintf(files.f_info, "%s.bin", namebuf);
  412. X    } else {
  413. X        sprintf(files.f_data, "%s.data", namebuf);
  414. X        sprintf(files.f_rsrc, "%s.rsrc", namebuf);
  415. X        sprintf(files.f_info, "%s.info", namebuf);
  416. X    }
  417. X    if (verbose) {
  418. X        if ((macbinary == 1))
  419. X            fprintf(stderr, "==> %s.bin\n", namebuf);
  420. X        else
  421. X            fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf);
  422. X    }
  423. X}
  424. X
  425. X/* print out header information in human-readable format */
  426. Xprint_header()
  427. X{
  428. X    char           *ctime();
  429. X
  430. X    printf("macname: %s\n", mh.m_name);
  431. X    printf("filetype: %.4s, ", mh.m_type);
  432. X    printf("author: %.4s, ", mh.m_author);
  433. X    printf("flags: 0x%x\n", mh.m_flags);
  434. X    if (qformat) {
  435. X        printf("data length: %ld, ", mh.m_datalen);
  436. X        printf("rsrc length: %ld\n", mh.m_rsrclen);
  437. X    }
  438. X    if (!pre_beta) {
  439. X        printf("create time: %s", ctime(&mh.m_createtime));
  440. X    }
  441. X}
  442. X
  443. Xprocess_forks()
  444. X{
  445. X    if (qformat) {
  446. X        /* read data and resource forks of .hqx file */
  447. X        do_q_fork(files.f_data, mh.m_datalen);
  448. X        do_q_fork(files.f_rsrc, mh.m_rsrclen);
  449. X    } else
  450. X        do_o_forks();
  451. X}
  452. X
  453. X/* write out .info file from information in the mh structure */
  454. Xforge_info()
  455. X{
  456. X    static char     buf[DATABYTES];
  457. X    char           *np;
  458. X    int             n;
  459. X    long            tdiff;
  460. X    struct tm      *tp;
  461. X#ifdef BSD
  462. X    struct timeb    tbuf;
  463. X#else
  464. X    long            bs;
  465. X#endif
  466. X
  467. X    for (np = mh.m_name; *np; np++)
  468. X        if (*np == '_')
  469. X            *np = ' ';
  470. X
  471. X    buf[H_NLENOFF] = n = np - mh.m_name;
  472. X    strncpy(buf + H_NAMEOFF, mh.m_name, n);
  473. X    strncpy(buf + H_TYPEOFF, mh.m_type, 4);
  474. X    strncpy(buf + H_AUTHOFF, mh.m_author, 4);
  475. X    put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED);
  476. X    if (pre_beta) {
  477. X        put4(buf + H_OLD_DLENOFF, mh.m_datalen);
  478. X        put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
  479. X    } else {
  480. X        put4(buf + H_DLENOFF, mh.m_datalen);
  481. X        put4(buf + H_RLENOFF, mh.m_rsrclen);
  482. X
  483. X        /* convert unix file time to mac time format */
  484. X#ifdef BSD
  485. X        ftime(&tbuf);
  486. X        tp = localtime(&tbuf.time);
  487. X        tdiff = TIMEDIFF - tbuf.timezone * 60;
  488. X        if (tp->tm_isdst)
  489. X            tdiff += 60 * 60;
  490. X#else
  491. X        /* I hope this is right! -andy */
  492. X        time(&bs);
  493. X        tp = localtime(&bs);
  494. X        tdiff = TIMEDIFF - timezone;
  495. X        if (tp->tm_isdst)
  496. X            tdiff += 60 * 60;
  497. X#endif
  498. X        put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
  499. X        put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
  500. X    }
  501. X    if (fp == NULL) {
  502. X        fp = fopen(files.f_info, "w");
  503. X        if (fp == NULL) {
  504. X                perror("info file");
  505. X                    exit(-1);
  506. X        }
  507. X    }
  508. X    if (macbinary == 1) {
  509. X        if (buf[74] & 0x40)
  510. X            buf[81] = '\1';    /* protected */
  511. X        buf[74] = '\0';         /* MacBinary identifiers */
  512. X        buf[82] = '\0';
  513. X    }
  514. X    fwrite(buf, 1, DATABYTES, fp);
  515. X    fclose(fp);
  516. X    fp = NULL;
  517. X}
  518. X
  519. X/* eat characters until header detected, return which format */
  520. Xfind_header()
  521. X{
  522. X    int             c, at_bol;
  523. X    char            ibuf[BUFSIZ];
  524. X
  525. X    /* look for "(This file ...)" line */
  526. X    while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
  527. X        if (strncmp(ibuf, "(This file", 10) == 0)
  528. X            break;
  529. X    }
  530. X    at_bol = 1;
  531. X    while ((c = getc(ifp)) != EOF) {
  532. X        switch (c) {
  533. X        case '\n':
  534. X        case '\r':
  535. X            at_bol = 1;
  536. X            break;
  537. X        case ':':
  538. X            if (at_bol)    /* q format */
  539. X                return 1;
  540. X            break;
  541. X        case '#':
  542. X            if (at_bol) {    /* old format */
  543. X                ungetc(c, ifp);
  544. X                return 0;
  545. X            }
  546. X            break;
  547. X        default:
  548. X            at_bol = 0;
  549. X            break;
  550. X        }
  551. X    }
  552. X
  553. X    fprintf(stderr, "unexpected EOF\n");
  554. X    exit(2);
  555. X    /* NOTREACHED */
  556. X}
  557. X
  558. Xstatic unsigned int crc;
  559. X
  560. Xshort           get2q();
  561. Xlong            get4q();
  562. X
  563. X/* read header of .hqx file */
  564. Xdo_q_header(macname)
  565. X    char           *macname;
  566. X{
  567. X    char            namebuf[256];    /* big enough for both att & bsd */
  568. X    int             n;
  569. X    int             calc_crc, file_crc;
  570. X
  571. X    crc = 0;        /* compute a crc for the header */
  572. X    q_init();        /* reset static variables */
  573. X
  574. X    n = getq();        /* namelength */
  575. X    n++;            /* must read trailing null also */
  576. X    getqbuf(namebuf, n);    /* read name */
  577. X    if (macname[0] == '\0')
  578. X        macname = namebuf;
  579. X
  580. X    n = strlen(macname);
  581. X    if (n > NAMEBYTES)
  582. X        n = NAMEBYTES;
  583. X    strncpy(mh.m_name, macname, n);
  584. X    mh.m_name[n] = '\0';
  585. X
  586. X    getqbuf(mh.m_type, 4);
  587. X    getqbuf(mh.m_author, 4);
  588. X    mh.m_flags = get2q();
  589. X    mh.m_datalen = get4q();
  590. X    mh.m_rsrclen = get4q();
  591. X
  592. X    comp_q_crc(0);
  593. X    comp_q_crc(0);
  594. X    calc_crc = crc;
  595. X    file_crc = get2q();
  596. X    verify_crc(calc_crc, file_crc);
  597. X}
  598. X
  599. Xdo_q_fork(fname, len)
  600. X    char           *fname;
  601. X    register long   len;
  602. X{
  603. X    register int    c, i;
  604. X    int             calc_crc, file_crc;
  605. X
  606. X    if (macbinary != 1) {
  607. X        if (fp != NULL) {
  608. X            fclose(fp);
  609. X        }
  610. X        fp = fopen(fname, "w");
  611. X        if (fp == NULL) {
  612. X            perror(fname);
  613. X            exit(-1);
  614. X        }
  615. X    }
  616. X    crc = 0;        /* compute a crc for a fork */
  617. X
  618. X    if (len)
  619. X        for (i = 0; i < len; i++) {
  620. X            if ((c = getq()) == EOF) {
  621. X                fprintf(stderr, "unexpected EOF\n");
  622. X                exit(2);
  623. X            }
  624. X            putc(c, fp);
  625. X        }
  626. X
  627. X    comp_q_crc(0);
  628. X    comp_q_crc(0);
  629. X    calc_crc = crc;
  630. X    file_crc = get2q();
  631. X    verify_crc(calc_crc, file_crc);
  632. X    if (macbinary != 1) {
  633. X        fclose(fp);
  634. X        fp = NULL;
  635. X    }
  636. X}
  637. X
  638. X/* verify_crc(); -- check if crc's check out */
  639. Xverify_crc(calc_crc, file_crc)
  640. X    unsigned int    calc_crc, file_crc;
  641. X{
  642. X    calc_crc &= WORDMASK;
  643. X    file_crc &= WORDMASK;
  644. X
  645. X    if (calc_crc != file_crc) {
  646. X        fprintf(stderr, "CRC error\n---------\n");
  647. X        fprintf(stderr, "CRC in file:\t0x%x\n", file_crc);
  648. X        fprintf(stderr, "calculated CRC:\t0x%x\n", calc_crc);
  649. X        exit(3);
  650. X    }
  651. X}
  652. X
  653. Xstatic int      eof;
  654. Xstatic char     obuf[3];
  655. Xstatic char    *op, *oend;
  656. X
  657. X/* initialize static variables for q format input */
  658. Xq_init()
  659. X{
  660. X    eof = 0;
  661. X    op = obuf;
  662. X    oend = obuf + sizeof obuf;
  663. X}
  664. X
  665. X/* get2q(); q format -- read 2 bytes from input, return short */
  666. Xshort
  667. Xget2q()
  668. X{
  669. X    register int    c;
  670. X    short           value = 0;
  671. X
  672. X    c = getq();
  673. X    value = (c & BYTEMASK) << 8;
  674. X    c = getq();
  675. X    value |= (c & BYTEMASK);
  676. X
  677. X    return value;
  678. X}
  679. X
  680. X/* get4q(); q format -- read 4 bytes from input, return long */
  681. Xlong
  682. Xget4q()
  683. X{
  684. X    register int    c, i;
  685. X    long            value = 0L;
  686. X
  687. X    for (i = 0; i < 4; i++) {
  688. X        c = getq();
  689. X        value <<= 8;
  690. X        value |= (c & BYTEMASK);
  691. X    }
  692. X    return value;
  693. X}
  694. X
  695. X/* getqbuf(); q format -- read n characters from input into buf */
  696. X/*        All or nothing -- no partial buffer allowed */
  697. Xgetqbuf(buf, n)
  698. X    register char  *buf;
  699. X    register int    n;
  700. X{
  701. X    register int    c, i;
  702. X
  703. X    for (i = 0; i < n; i++) {
  704. X        if ((c = getq()) == EOF)
  705. X            return EOF;
  706. X        *buf++ = c;
  707. X    }
  708. X    return 0;
  709. X}
  710. X
  711. X#define RUNCHAR 0x90
  712. X
  713. X/* q format -- return one byte per call, keeping track of run codes */
  714. Xgetq()
  715. X{
  716. X    register int    c;
  717. X
  718. X    if ((c = getq_nocrc()) == EOF)
  719. X        return EOF;
  720. X    comp_q_crc(c);
  721. X    return c;
  722. X}
  723. X
  724. Xgetq_nocrc()
  725. X{
  726. X    static int      rep, lastc;
  727. X    int             c;
  728. X
  729. X    if (rep) {
  730. X        rep--;
  731. X        return lastc;
  732. X    }
  733. X    if ((c = getq_raw()) == EOF) {
  734. X        return EOF;
  735. X    }
  736. X    if (c == RUNCHAR) {
  737. X        if ((rep = getq_raw()) == EOF)
  738. X            return EOF;
  739. X        if (rep == 0) {
  740. X            return RUNCHAR;
  741. X        } else {
  742. X            /* already returned one, about to return another */
  743. X            rep -= 2;
  744. X            return lastc;
  745. X        }
  746. X    } else {
  747. X        lastc = c;
  748. X        return c;
  749. X    }
  750. X}
  751. X
  752. X/* q format -- return next 8 bits from file without interpreting run codes */
  753. Xgetq_raw()
  754. X{
  755. X    char            ibuf[4];
  756. X    register char  *ip = ibuf, *iend = ibuf + sizeof ibuf;
  757. X    int             c;
  758. X
  759. X    if (op == obuf) {
  760. X        for (ip = ibuf; ip < iend; ip++) {
  761. X            if ((c = get6bits()) == EOF)
  762. X                if (ip <= &ibuf[1])
  763. X                    return EOF;
  764. X                else if (ip == &ibuf[2])
  765. X                    eof = 1;
  766. X                else
  767. X                    eof = 2;
  768. X            *ip = c;
  769. X        }
  770. X        obuf[0] = (ibuf[0] << 2 | ibuf[1] >> 4);
  771. X        obuf[1] = (ibuf[1] << 4 | ibuf[2] >> 2);
  772. X        obuf[2] = (ibuf[2] << 6 | ibuf[3]);
  773. X    }
  774. X    if ((eof) & (op >= &obuf[eof]))
  775. X        return EOF;
  776. X    c = *op++;
  777. X    if (op >= oend)
  778. X        op = obuf;
  779. X    return (c & BYTEMASK);
  780. X}
  781. X
  782. Xchar            tr[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
  783. X
  784. X/* q format -- decode one byte into 6 bit binary */
  785. Xget6bits()
  786. X{
  787. X    register int    c;
  788. X    register char  *where;
  789. X
  790. X    while (1) {
  791. X        c = getc(ifp);
  792. X        switch (c) {
  793. X        case '\n':
  794. X        case '\r':
  795. X            continue;
  796. X        case ':':
  797. X        case EOF:
  798. X            return EOF;
  799. X        default:
  800. X            where = tr;
  801. X            while (*where != '\0' && *where != c)
  802. X                where++;
  803. X            if (*where == c)
  804. X                return (where - tr);
  805. X            else {
  806. X                fprintf(stderr, "bad char\n");
  807. X                return EOF;
  808. X            }
  809. X        }
  810. X    }
  811. X}
  812. X
  813. X#define CRCCONSTANT 0x1021
  814. X
  815. Xcomp_q_crc(c)
  816. X    register unsigned int c;
  817. X{
  818. X    register int    i;
  819. X    register unsigned long temp = crc;
  820. X
  821. X    for (i = 0; i < 8; i++) {
  822. X        c <<= 1;
  823. X        if ((temp <<= 1) & WORDBIT)
  824. X            temp = (temp & WORDMASK) ^ CRCCONSTANT;
  825. X        temp ^= (c >> 8);
  826. X        c &= BYTEMASK;
  827. X    }
  828. X    crc = temp;
  829. X}
  830. X
  831. X/* old format -- process .hex and .hcx files */
  832. Xdo_o_header(macname, filename)
  833. X    char           *macname, *filename;
  834. X{
  835. X    char            namebuf[256];    /* big enough for both att & bsd */
  836. X    char            ibuf[BUFSIZ];
  837. X    int             n;
  838. X
  839. X    /* set up name for output files */
  840. X    if (macname[0] == '\0') {
  841. X        strcpy(namebuf, filename);
  842. X
  843. X        /* strip directories */
  844. X        macname = search_last(namebuf, '/');
  845. X        if (macname == NULL)
  846. X            macname = namebuf;
  847. X        else
  848. X            macname++;
  849. X
  850. X        /* strip extension */
  851. X        n = strlen(macname);
  852. X        if (n > 4) {
  853. X            n -= 4;
  854. X            if (macname[n] == '.' && macname[n + 1] == 'h'
  855. X                && macname[n + 3] == 'x')
  856. X                macname[n] = '\0';
  857. X        }
  858. X    }
  859. X    n = strlen(macname);
  860. X    if (n > NAMEBYTES)
  861. X        n = NAMEBYTES;
  862. X    strncpy(mh.m_name, macname, n);
  863. X    mh.m_name[n] = '\0';
  864. X
  865. X    /* read "#TYPEAUTH$flag"  line */
  866. X    if (fgets(ibuf, BUFSIZ, ifp) == NULL) {
  867. X        fprintf(stderr, "unexpected EOF\n");
  868. X        exit(2);
  869. X    }
  870. X    n = strlen(ibuf);
  871. X    if (n >= 7 && ibuf[0] == '#' && ibuf[n - 6] == '$') {
  872. X        if (n >= 11)
  873. X            strncpy(mh.m_type, &ibuf[1], 4);
  874. X        if (n >= 15)
  875. X            strncpy(mh.m_author, &ibuf[5], 4);
  876. X        sscanf(&ibuf[n - 5], "%4hx", &mh.m_flags);
  877. X    }
  878. X}
  879. X
  880. Xdo_o_forks()
  881. X{
  882. X    char            ibuf[BUFSIZ];
  883. X    int             forks = 0, found_crc = 0;
  884. X    int             calc_crc, file_crc;
  885. X    extern long     make_file();
  886. X
  887. X    crc = 0;        /* calculate a crc for both forks */
  888. X
  889. X    /* create empty files ahead of time */
  890. X    if (macbinary != 1) {
  891. X        close(creat(files.f_data, 0666));
  892. X        close(creat(files.f_rsrc, 0666));
  893. X    }
  894. X    while (!found_crc && fgets(ibuf, BUFSIZ, ifp) != NULL) {
  895. X        if (forks == 0 && strncmp(ibuf, "***COMPRESSED", 13) == 0) {
  896. X            compressed++;
  897. X            continue;
  898. X        }
  899. X        if (strncmp(ibuf, "***DATA", 7) == 0) {
  900. X            mh.m_datalen = make_file(files.f_data, compressed);
  901. X            forks++;
  902. X            continue;
  903. X        }
  904. X        if (strncmp(ibuf, "***RESOURCE", 11) == 0) {
  905. X            mh.m_rsrclen = make_file(files.f_rsrc, compressed);
  906. X            forks++;
  907. X            continue;
  908. X        }
  909. X        if (compressed && strncmp(ibuf, "***CRC:", 7) == 0) {
  910. X            found_crc++;
  911. X            calc_crc = crc;
  912. X            sscanf(&ibuf[7], "%x", &file_crc);
  913. X            break;
  914. X        }
  915. X        if (!compressed && strncmp(ibuf, "***CHECKSUM:", 12) == 0) {
  916. X            found_crc++;
  917. X            calc_crc = crc & BYTEMASK;
  918. X            sscanf(&ibuf[12], "%x", &file_crc);
  919. X            file_crc &= BYTEMASK;
  920. X            break;
  921. X        }
  922. X    }
  923. X
  924. X    if (found_crc)
  925. X        verify_crc(calc_crc, file_crc);
  926. X    else {
  927. X        fprintf(stderr, "missing CRC\n");
  928. X        exit(3);
  929. X    }
  930. X}
  931. X
  932. Xlong
  933. Xmake_file(fname, compressed)
  934. X    char           *fname;
  935. X    int             compressed;
  936. X{
  937. X    char            ibuf[BUFSIZ];
  938. X    register long   nbytes = 0;
  939. X
  940. X    if (macbinary != 1) {
  941. X        if (fp != NULL)
  942. X            fclose(fp);
  943. X        fp = fopen(fname, "w");
  944. X        if (fp == NULL) {
  945. X            perror(fname);
  946. X            exit(-1);
  947. X        }
  948. X    }
  949. X    while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
  950. X        if (strncmp(ibuf, "***END", 6) == 0)
  951. X            break;
  952. X        if (compressed)
  953. X            nbytes += comp_to_bin(ibuf, fp);
  954. X        else
  955. X            nbytes += hex_to_bin(ibuf, fp);
  956. X    }
  957. X    if (macbinary != 1) {
  958. X        fclose(fp);
  959. X        fp = NULL;
  960. X    }
  961. X    return nbytes;
  962. X}
  963. X
  964. Xcomp_c_crc(c)
  965. X    unsigned char   c;
  966. X{
  967. X    crc = (crc + c) & WORDMASK;
  968. X    crc = ((crc << 3) & WORDMASK) | (crc >> 13);
  969. X}
  970. X
  971. Xcomp_e_crc(c)
  972. X    unsigned char   c;
  973. X{
  974. X    crc += c;
  975. X}
  976. X
  977. X#define SIXB(c) (((c)-0x20) & 0x3f)
  978. X
  979. Xcomp_to_bin(ibuf, outf)
  980. X    char            ibuf[];
  981. XFILE           *outf;
  982. X{
  983. X    char            obuf[BUFSIZ];
  984. X    register char  *ip = ibuf;
  985. X    register char  *op = obuf;
  986. X    register int    n, outcount;
  987. X    int             numread, incount;
  988. X
  989. X    numread = strlen(ibuf);
  990. X    ip[numread - 1] = ' ';    /* zap out the newline */
  991. X    outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4);
  992. X    incount = ((outcount / 3) + 1) * 4;
  993. X    for (n = numread; n < incount; n++)    /* restore lost spaces */
  994. X        ibuf[n] = ' ';
  995. X
  996. X    n = 0;
  997. X    while (n <= outcount) {
  998. X        *op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4;
  999. X        *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2;
  1000. X        *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]);
  1001. X        ip += 4;
  1002. X        n += 3;
  1003. X    }
  1004. X
  1005. X    for (n = 1; n <= outcount; n++)
  1006. X        comp_c_crc(obuf[n]);
  1007. X
  1008. X    fwrite(obuf + 1, 1, outcount, outf);
  1009. X    return outcount;
  1010. X}
  1011. X
  1012. Xhex_to_bin(ibuf, outf)
  1013. X    char            ibuf[];
  1014. XFILE           *outf;
  1015. X{
  1016. X    register char  *ip = ibuf;
  1017. X    register int    n, outcount;
  1018. X    int             c;
  1019. X
  1020. X    n = strlen(ibuf) - 1;
  1021. X    outcount = n / 2;
  1022. X    for (n = 0; n < outcount; n++) {
  1023. X        c = hexit(*ip++);
  1024. X        comp_e_crc(c = (c << 4) | hexit(*ip++));
  1025. X        fputc(c, outf);
  1026. X    }
  1027. X    return outcount;
  1028. X}
  1029. X
  1030. Xhexit(c)
  1031. X    int             c;
  1032. X{
  1033. X    if ('0' <= c && c <= '9')
  1034. X        return c - '0';
  1035. X    if ('A' <= c && c <= 'F')
  1036. X        return c - 'A' + 10;
  1037. X
  1038. X    fprintf(stderr, "illegal hex digit: %c", c);
  1039. X    exit(4);
  1040. X    /* NOTREACHED */
  1041. X}
  1042. X
  1043. Xput2(bp, value)
  1044. X    char           *bp;
  1045. X    short           value;
  1046. X{
  1047. X    *bp++ = (value >> 8) & BYTEMASK;
  1048. X    *bp++ = value & BYTEMASK;
  1049. X}
  1050. X
  1051. Xput4(bp, value)
  1052. X    char           *bp;
  1053. X    long            value;
  1054. X{
  1055. X    register int    i, c;
  1056. X
  1057. X    for (i = 0; i < 4; i++) {
  1058. X        c = (value >> 24) & BYTEMASK;
  1059. X        value <<= 8;
  1060. X        *bp++ = c;
  1061. X    }
  1062. X}
  1063. !Funky!Stuff!
  1064. echo x - xbinary
  1065. sed -e 's/^X//' > xbinary << '!Funky!Stuff!'
  1066. X#!/bin/csh
  1067. X# Shell script for always running xbin in MacBinary mode.  Make this
  1068. X# executable and put it in your search path.
  1069. Xxbin -b $*
  1070. !Funky!Stuff!
  1071. exit
  1072.  
  1073.