home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / aufstols.zoo / aufstools.3 < prev    next >
Text File  |  1991-02-26  |  50KB  |  1,490 lines

  1. #! /bin/sh
  2. # This is a shell archive.  Remove anything before this line, then unpack
  3. # it by saving it into a file and typing "sh file".  To overwrite existing
  4. # files, type "sh file -c".  You can also feed this as standard input via
  5. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  6. # will see the following message at the end:
  7. #        "End of archive 3 (of 4)."
  8. # Contents:  mcvert/hqxify.c mcvert/mcvert.c stuffit/sit.c
  9. # Wrapped by np@asun5 on Mon Dec  3 13:15:58 1990
  10. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  11. if test -f 'mcvert/hqxify.c' -a "${1}" != "-c" ; then 
  12.   echo shar: Will not clobber existing file \"'mcvert/hqxify.c'\"
  13. else
  14. echo shar: Extracting \"'mcvert/hqxify.c'\" \(19992 characters\)
  15. sed "s/^X//" >'mcvert/hqxify.c' <<'END_OF_FILE'
  16. X#include "mactypes.h"
  17. X
  18. X#define HQXBUFLEN 512
  19. Xbyte hqxbuf[HQXBUFLEN+1], *buf_ptr, *buf_end, *buf_start=hqxbuf+1;
  20. X
  21. X#define MAXLINE 255
  22. Xbyte line[MAXLINE+1], *line_ptr, *line_end, *line_start=line+1;
  23. X
  24. Xint line_count, file_count;
  25. Xint save_state, total_bytes, save_run_length;
  26. Xword save_nibble;
  27. Xchar binfname[BINNAMELEN], hqxfname[BINNAMELEN];
  28. XFILE *hqxfile, *binfile;
  29. X
  30. X/* This routine reads the header of a hqxed file and appropriately twiddles it,
  31. X    determines if it has CRC problems, creates the .bin file, and puts the info
  32. X    into the .bin file.
  33. X    Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile */
  34. X
  35. Xhqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen)
  36. Xchar *type;
  37. Xulong *hqx_datalen, *hqx_rsrclen;
  38. X{   register byte *hqx_ptr, *hqx_end;
  39. X    register ulong calc_crc;
  40. X    hqx_buf *hqx_block;
  41. X    hqx_header *hqx;
  42. X    info_header info;
  43. X    ulong mtim;
  44. X    short crc;
  45. X
  46. X    extern word magic[];
  47. X    extern FILE *verbose;
  48. X    extern char *dir, *ext;
  49. X    extern short calc_mb_crc();
  50. X
  51. X    /* read the hqx header, assuming that I won't exhaust hqxbuf in so doing */
  52. X    fill_hqxbuf();
  53. X    hqx_block = (hqx_buf *) buf_ptr;
  54. X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  55. X    hqx_ptr = buf_ptr;
  56. X    hqx_end = (byte *) hqx + sizeof(hqx_header) - 1;
  57. X    calc_crc = 0;
  58. X    while (hqx_ptr < hqx_end)
  59. X        calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  60. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  61. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  62. X    buf_ptr = hqx_ptr;
  63. X
  64. X    /* stuff the hqx header data into the info header */
  65. X    bzero(&info, sizeof(info_header));
  66. X    info.nlen = hqx_block->nlen;
  67. X    strncpy(info.name, hqx_block->name, info.nlen);     /* name */
  68. X    bcopy(hqx->type, info.type, 9);             /* type, author, flag */
  69. X    info.flags  &= 0x7e;                        /* reset lock bit, init bit */
  70. X    if (hqx->protect & 0x40) info.protect = 1;  /* copy protect bit */
  71. X    bcopy(hqx->dlen, info.dlen, 8);             /* dlen, rlen */
  72. X    mtim = time2mac(time(0));
  73. X    bcopy(&mtim, info.mtim, 4);
  74. X    bcopy(&mtim, info.ctim, 4);
  75. X    info.uploadvers = '\201';
  76. X    info.readvers = '\201';
  77. X
  78. X    /* calculate MacBinary CRC */
  79. X    crc = calc_mb_crc(&info, 124, 0);
  80. X    info.crc[0] = (char) (crc >> 8);
  81. X    info.crc[1] = (char) crc;
  82. X
  83. X    /* Create the .bin file and write the info to it */
  84. X    unixify(hqx_block->name);
  85. X    sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
  86. X    fprintf(verbose,
  87. X        "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  88. X        hqx_block->name, info.type, info.auth);
  89. X    if ((binfile = fopen(binfname, "w")) == NULL)
  90. X        error("Cannot open %s", binfname);
  91. X    check_hqx_crc(calc_crc, "File header CRC mismatch in %s", binfname);
  92. X    fwrite(&info, sizeof(info), 1, binfile);
  93. X
  94. X    /* Get a couple of items we'll need later */
  95. X    bcopy(info.dlen, hqx_datalen, 4);
  96. X    *hqx_datalen = mac2long(*hqx_datalen);
  97. X    bcopy(info.rlen, hqx_rsrclen, 4);
  98. X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
  99. X    bcopy(info.type, type, 4);
  100. X    }
  101. X
  102. X/* This routine reads the header of a bin file and appropriately twiddles it,
  103. X    creates the .hqx file, and puts the info into the .hqx file.
  104. X    Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
  105. X
  106. Xbin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
  107. Xulong *hqx_datalen, *hqx_rsrclen;
  108. X{   register byte *hqx_ptr, *hqx_end;
  109. X    register ulong calc_crc;
  110. X    hqx_buf *hqx_block;
  111. X    hqx_header *hqx;
  112. X    info_header info;
  113. X    extern word magic[];
  114. X    extern FILE *verbose;
  115. X    extern char **hqxnames_left;
  116. X    extern char *ext;
  117. X
  118. X    strcpy(binfname, *hqxnames_left++);
  119. X    if (!(binfile = fopen(binfname, "r"))) {
  120. X        /* Maybe we are supposed to figure out the suffix ourselves? */
  121. X        strcat(binfname, ext);
  122. X        if (!(binfile = fopen(binfname, "r")))
  123. X            error("Cannot open %s", binfname);
  124. X        }
  125. X    if (!fread(&info, sizeof(info), 1, binfile))
  126. X        error("Unexpected EOF in header of %s", binfname);
  127. X
  128. X    /* stuff the info header into the hqx header */
  129. X    hqx_block = (hqx_buf *) buf_ptr;
  130. X    hqx_block->nlen = info.nlen;
  131. X    strncpy(hqx_block->name, info.name, info.nlen);
  132. X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  133. X    hqx->version  = 0;
  134. X    bcopy(info.type, hqx->type, 9);             /* type, author, flags */
  135. X    if (info.protect = 1) hqx->protect = 0;     /* protect bit: 0x40 */
  136. X    else hqx->protect = 0;
  137. X    bcopy(info.dlen, hqx->dlen, 8);             /* dlen, rlen */
  138. X
  139. X    /* Create the .hqx file and write the info to it */
  140. X    strncpy(hqxfname, info.name, info.nlen);
  141. X    hqxfname[info.nlen] = '\0';
  142. X    unixify(hqxfname);
  143. X    fprintf(verbose,
  144. X        "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  145. X        hqxfname, info.type, info.auth);
  146. X
  147. X    calc_crc = 0;
  148. X    hqx_ptr = (byte *) hqx_block;
  149. X    hqx_end = hqx_ptr + hqx_block->nlen + sizeof(hqx_header);
  150. X    while (hqx_ptr < hqx_end)
  151. X        calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  152. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  153. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  154. X    buf_ptr = hqx_end;
  155. X    write_hqx_crc(calc_crc);
  156. X
  157. X    /* Get a couple of items we'll need later */
  158. X    bcopy(info.dlen, hqx_datalen, 4);
  159. X    *hqx_datalen = mac2long(*hqx_datalen);
  160. X    bcopy(info.rlen, hqx_rsrclen, 4);
  161. X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
  162. X    }
  163. X
  164. X
  165. X/* This routine copies bytes from the decoded input stream to the output.  
  166. X    It also pads to a multiple of 128 bytes on the output, which is part
  167. X    of the .bin format */
  168. Xword hqx_to_bin_fork(nbytes)
  169. Xregister ulong nbytes;
  170. X{   register byte *c;
  171. X    register ulong calc_crc;
  172. X    register int c_length;
  173. X    ulong extra_bytes;
  174. X    extern word magic[];
  175. X
  176. X    extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  177. X    calc_crc = 0;
  178. X    for (;;) {
  179. X        c = buf_ptr;
  180. X        c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  181. X        nbytes -= c_length;
  182. X        fwrite(c, sizeof(byte), c_length, binfile);
  183. X        while (c_length--)
  184. X            calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  185. X        if (!nbytes) break;
  186. X        fill_hqxbuf();
  187. X        }
  188. X    buf_ptr = c;
  189. X    while (extra_bytes--) putc(0, binfile);
  190. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  191. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  192. X    return (word) calc_crc;
  193. X    }
  194. X
  195. X/* This routine copies bytes from the input stream to the encoded output.  
  196. X    It also pads to a multiple of 128 bytes on the input, which is part
  197. X    of the .bin format */
  198. Xword bin_to_hqx_fork(nbytes)
  199. Xregister ulong nbytes;
  200. X{   register byte *c;
  201. X    register ulong calc_crc;
  202. X    register int c_length;
  203. X    ulong extra_bytes;
  204. X    extern word magic[];
  205. X
  206. X    extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  207. X    calc_crc = 0;
  208. X    for (;;) {
  209. X        c = buf_ptr;
  210. X        c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  211. X        nbytes -= c_length;
  212. X        fread(c, sizeof(byte), c_length, binfile);
  213. X        buf_ptr += c_length;
  214. X        while (c_length--)
  215. X            calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  216. X        if (!nbytes) break;
  217. X        empty_hqxbuf();
  218. X        }
  219. X    buf_ptr = c;
  220. X
  221. X    fseek(binfile, extra_bytes, 1);
  222. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  223. X    calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  224. X    return (word) calc_crc;
  225. X    }
  226. X
  227. X/* Essentials for Binhex 8to6 run length encoding */
  228. X#define RUNCHAR 0x90
  229. X#define MAXRUN 255
  230. X#define IS_LEGAL <0x40
  231. X#define ISNT_LEGAL >0x3f
  232. X#define DONE 0x7F /* tr68[':'] = DONE, since Binhex terminator is ':' */
  233. X#define SKIP 0x7E /* tr68['\n'|'\r'] = SKIP, i. e. end of line char.  */
  234. X#define FAIL 0x7D /* character illegal in binhex file */
  235. X
  236. Xbyte tr86[] =
  237. X        "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; 
  238. Xbyte tr68[] = {
  239. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  240. X    FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
  241. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  242. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  243. X    FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  244. X    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
  245. X    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
  246. X    0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
  247. X    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
  248. X    0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
  249. X    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
  250. X    0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
  251. X    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
  252. X    0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
  253. X    0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
  254. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  255. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  256. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  257. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  258. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  259. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  260. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  261. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  262. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  263. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  264. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  265. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  266. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  267. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  268. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  269. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  270. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  271. X    };
  272. X
  273. X/*
  274. X *  This procedure transparently reads and decodes the hqx input.  It does run 
  275. X *  length and 6 to 8 decoding.
  276. X */
  277. X#define READING 0
  278. X#define SKIPPING 1
  279. X#define FIND_START_COLON 2
  280. X
  281. X/* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
  282. X#define X_MAIL_STR "\054\014\043\061\070\073\065\077\177"
  283. X#define X_MAIL_LEN strlen(X_MAIL_STR)
  284. X
  285. Xfill_hqxbuf()
  286. X{   register ulong c, nibble;
  287. X    register int not_in_a_run = TRUE, state68;
  288. X    register byte *fast_buf, *fast_line;
  289. X    static int status = FIND_START_COLON;
  290. X
  291. X    buf_ptr = fast_buf = buf_start;
  292. X    fast_line = line_ptr;
  293. X    state68 = save_state;
  294. X    nibble = save_nibble;
  295. X    if (save_run_length > 0) {
  296. X        c = save_run_length;
  297. X        save_run_length = 0;
  298. X        goto continue_run;
  299. X        }
  300. X    while (fast_buf < buf_end) {
  301. X        next_char:
  302. X        if ((c = *fast_line++) ISNT_LEGAL) {
  303. X            if (c == DONE) break;
  304. X            next_line:
  305. X            if (!fgets(line_start, MAXLINE, hqxfile) && !new_in_hqx_file())
  306. X                if (status == FIND_START_COLON) exit(0);
  307. X        else error("Premature EOF in %s\n", hqxfname);
  308. X            line_ptr = line_start;
  309. X            scan_line:
  310. X            fast_line = line_ptr;
  311. X        while ((*fast_line = tr68[*fast_line]) IS_LEGAL) fast_line++;
  312. X        c = *fast_line;
  313. X            switch (status) {
  314. X            case READING:
  315. X                if (c == SKIP && fast_line == line_end) break;
  316. X                if (c == DONE) {
  317. X                    status = FIND_START_COLON;
  318. X                    break;
  319. X                    }
  320. X                status = SKIPPING;
  321. X                goto next_line;
  322. X            case SKIPPING:
  323. X                if (c == SKIP && fast_line == line_end) {
  324. X                    status = READING;
  325. X                    break;
  326. X                    }
  327. X        /*  GMT, 1/9/90: Added this clause to avoid losing the last
  328. X         *  line if it was preceeded by a skipped line.  */
  329. X                if (c == DONE) { 
  330. X          /* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
  331. X          if( (fast_line - line_ptr == X_MAIL_LEN - 1)
  332. X             && (strncmp(line_ptr, X_MAIL_STR, X_MAIL_LEN) == 0)) goto next_line;
  333. X                    status = FIND_START_COLON;
  334. X                    break;
  335. X                    }
  336. X                goto next_line;
  337. X            case FIND_START_COLON:
  338. X                if (*line_start == DONE) {
  339. X                    status = READING;
  340. X                    line_ptr++;
  341. X                    goto scan_line;
  342. X                    }
  343. X                goto next_line;
  344. X                }
  345. X            fast_line = line_ptr;
  346. X            c = *fast_line++;
  347. X      }
  348. X
  349. X        /* Finally, we have the next 6 bits worth of data */
  350. X        switch (state68++) {
  351. X        case 0:
  352. X            nibble = c;
  353. X            goto next_char;
  354. X        case 1:
  355. X            nibble = (nibble << 6) | c;
  356. X            c = nibble >> 4;
  357. X            break;
  358. X        case 2:
  359. X            nibble = (nibble << 6) | c;
  360. X            c = (nibble >> 2) & 0xff;
  361. X            break;
  362. X        case 3:
  363. X            c = (nibble << 6) & 0xff | c;
  364. X            state68 = 0;
  365. X            break;
  366. X            }
  367. X        if (not_in_a_run)
  368. X            if (c != RUNCHAR) *fast_buf++ = c;
  369. X            else {not_in_a_run = FALSE; goto next_char;}
  370. X        else {
  371. X            if (c--) {
  372. X                not_in_a_run = buf_end - fast_buf;
  373. X                if (c > not_in_a_run) {
  374. X                    save_run_length = c - not_in_a_run;
  375. X                    c = not_in_a_run;
  376. X                    }
  377. X                continue_run:
  378. X                not_in_a_run = fast_buf[-1];
  379. X                while (c--) *fast_buf++ = not_in_a_run;
  380. X                }
  381. X            else *fast_buf++ = RUNCHAR;
  382. X            not_in_a_run = TRUE;
  383. X            }
  384. X        }
  385. X    total_bytes += fast_buf - buf_ptr;
  386. X    buf_start[-1] = fast_buf[-1];
  387. X    line_ptr = fast_line;
  388. X    save_state = state68;
  389. X    save_nibble = nibble;
  390. X    }
  391. X
  392. X
  393. Xnew_in_hqx_file()
  394. X{   char *hqx_ext;
  395. X    extern char **hqxnames_left;
  396. X    if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') return FALSE;
  397. X    strcpy(hqxfname, *hqxnames_left++);
  398. X    hqx_ext = hqxfname + strlen(hqxfname) - 4;
  399. X    if (!strcmp(hqx_ext, ".hqx"))
  400. X        if (!freopen(hqxfname, "r", hqxfile))
  401. X            error("Cannot open %s\n", hqxfname);
  402. X            else;
  403. X    else {
  404. X        if (!freopen(hqxfname, "r", hqxfile)) {
  405. X            hqx_ext += 4;
  406. X            strcpy(hqx_ext, ".hqx");
  407. X            if (!freopen(hqxfname, "r", hqxfile)) {
  408. X                error("Cannot find %s\n", hqxfname);
  409. X            }
  410. X        }
  411. X      }
  412. X    fgets(line_start, MAXLINE, hqxfile);
  413. X    return TRUE;
  414. X    }
  415. X
  416. X/*
  417. X *  This procedure transparently encodes and writes the hqx output.  
  418. X *  It does run length and 8 to 6 encoding.
  419. X */
  420. Xempty_hqxbuf()
  421. X{   register ulong c, nibble, last_c;
  422. X    register byte *fast_buf, *fast_line;
  423. X    register int state86, dont_look_for_runs = FALSE, run_length;
  424. X    extern int maxlines;
  425. X
  426. X    run_length = save_run_length;
  427. X    last_c = buf_start[-1];
  428. X    fast_buf = buf_start;
  429. X    fast_line = line_ptr;
  430. X    state86 = save_state;
  431. X    nibble = save_nibble;
  432. X    while (fast_buf < buf_ptr) {
  433. X        c = *fast_buf++;
  434. X        if (dont_look_for_runs) dont_look_for_runs = FALSE;
  435. X        else if (last_c == c &&  run_length < MAXRUN) {run_length++; continue;}
  436. X        else {
  437. X            if (run_length >1) {
  438. X                --fast_buf;
  439. X                if (run_length == 2 && last_c != RUNCHAR) c = last_c;
  440. X                else {
  441. X                    c = RUNCHAR;
  442. X                    *--fast_buf = run_length;
  443. X                    dont_look_for_runs = TRUE;
  444. X                    }
  445. X                run_length = 1;
  446. X                }
  447. X            else last_c = c;
  448. X            if (c == RUNCHAR && !dont_look_for_runs) {
  449. X                *--fast_buf = 0;
  450. X                dont_look_for_runs = TRUE;
  451. X                }
  452. X            }
  453. X
  454. X        if (fast_line == line_end) {
  455. X            if (line_count++ == maxlines) new_out_hqx_file();
  456. X            fputs(line_start, hqxfile);
  457. X            fast_line = line_start;
  458. X            }
  459. X
  460. X        switch (state86++) {
  461. X        case 0:
  462. X            *fast_line++ = tr86[ c >> 2 ];
  463. X            nibble = (c << 4) & 0x3f;
  464. X            break;
  465. X        case 1:
  466. X            *fast_line++ = tr86[ (c >> 4) | nibble ];
  467. X            nibble = (c << 2) & 0x3f;
  468. X            break;
  469. X        case 2:
  470. X            *fast_line++ = tr86[ (c >> 6) | nibble ];
  471. X            if (fast_line == line_end) {
  472. X                if (line_count++ == maxlines) new_out_hqx_file();
  473. X                fputs(line_start, hqxfile);
  474. X                fast_line = line_start;
  475. X                }
  476. X            *fast_line++ = tr86[ c & 0x3f ];
  477. X            state86 = 0;
  478. X            break;
  479. X            }
  480. X        }
  481. X    save_run_length = run_length;
  482. X    buf_start[-1] = last_c;
  483. X    buf_ptr = buf_start;
  484. X    line_ptr = fast_line;
  485. X    save_state = state86;
  486. X    save_nibble = nibble;
  487. X    }
  488. X
  489. Xnew_out_hqx_file()
  490. X{   char filename[NAMELEN + 7];
  491. X    extern int maxlines;
  492. X    fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
  493. X    fclose(hqxfile);
  494. X    file_count++;
  495. X    if (maxlines) sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
  496. X    else sprintf(filename, "%s.hqx", hqxfname);
  497. X    if ((hqxfile = fopen(filename, "w")) == NULL)
  498. X        error("Can't create %s", filename);
  499. X    if (file_count > 1)
  500. X        fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
  501. X    else fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
  502. X    line_count = 3;
  503. X    }
  504. X
  505. Xcheck_hqx_crc(calc_crc, msg, name)
  506. Xword calc_crc;
  507. Xchar msg[], name[];
  508. X{   word read_crc;
  509. X    if (buf_ptr >= buf_end) fill_hqxbuf();
  510. X    read_crc = *buf_ptr++ << 8;
  511. X    if (buf_ptr >= buf_end) fill_hqxbuf();
  512. X    read_crc |= *buf_ptr++;
  513. X    if (read_crc != calc_crc) error(msg, name);
  514. X    }
  515. X
  516. Xwrite_hqx_crc(calc_crc)
  517. Xword calc_crc;
  518. X{   if (buf_ptr == buf_end) empty_hqxbuf();
  519. X    *buf_ptr++ = calc_crc >> 8;
  520. X    if (buf_ptr == buf_end) empty_hqxbuf();
  521. X    *buf_ptr++ = calc_crc;
  522. X    }
  523. X
  524. Xun_hqx(unpit_flag)
  525. Xint unpit_flag;
  526. X{   char type[4];
  527. X    ulong hqx_datalen, hqx_rsrclen;
  528. X    word un_pit();
  529. X    int unpitting, bytes_read;
  530. X    word calc_crc;
  531. X    extern char **hqxnames_left;
  532. X
  533. X    hqxfile = fopen("/dev/null", "r");
  534. X    line_end = line_start + HQXLINELEN;
  535. X    buf_end = buf_start + HQXBUFLEN;
  536. X    for (;;) {
  537. X        total_bytes = 0;
  538. X        line_ptr = line_start;
  539. X        line_ptr[0] = SKIP;
  540. X        save_state = 0;
  541. X        save_run_length = 0;
  542. X
  543. X        hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen); /* binfname */
  544. X
  545. X        unpitting = unpit_flag && !strcmp(type, "PIT ");
  546. X        if (unpitting) {
  547. X            fclose(binfile);
  548. X            unlink(binfname);
  549. X            bytes_read = total_bytes - (buf_end - buf_ptr);
  550. X            calc_crc = un_pit();
  551. X            bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
  552. X            if (bytes_read != hqx_datalen)
  553. X                fprintf(stderr,
  554. X                  "Warning - Extraneous characters ignored in %s\n", binfname);
  555. X            }
  556. X        else calc_crc = hqx_to_bin_fork(hqx_datalen);
  557. X        check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
  558. X
  559. X        calc_crc = hqx_to_bin_fork(hqx_rsrclen);
  560. X        check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
  561. X
  562. X        if (!unpitting) fclose(binfile);
  563. X        }
  564. X    }
  565. X
  566. Xre_hqx()
  567. X{   word calc_crc;
  568. X    ulong hqx_datalen, hqx_rsrclen;
  569. X    extern char **hqxnames_left;
  570. X    extern int maxlines;
  571. X    line_end = line_start + HQXLINELEN;
  572. X    buf_end = buf_start + HQXBUFLEN;
  573. X    while (*hqxnames_left[0] != '-') {
  574. X        hqxfile = fopen("/dev/null", "w");
  575. X        line_count = maxlines;
  576. X        file_count = 0;
  577. X        line_ptr = line_start;
  578. X        *line_ptr++ = ':';
  579. X        strcpy(line_end, "\n");
  580. X        buf_ptr = buf_start;
  581. X        save_state = 0;
  582. X        save_run_length = 1;
  583. X
  584. X        bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen);   /* calculates hqxfname */
  585. X
  586. X        calc_crc = bin_to_hqx_fork(hqx_datalen);
  587. X        write_hqx_crc(calc_crc);
  588. X
  589. X        calc_crc = bin_to_hqx_fork(hqx_rsrclen);
  590. X        write_hqx_crc(calc_crc);
  591. X        *buf_ptr = !buf_ptr[-1];      /* To end a run and to get the last */
  592. X        buf_ptr++;
  593. X        empty_hqxbuf();                 /* stray bits, temporarily add a char */
  594. X        if (save_state != 2) --line_ptr;
  595. X        if (line_ptr == line_end) {
  596. X            fputs(line_start, hqxfile);
  597. X            line_ptr = line_start;
  598. X            }
  599. X        strcpy(line_ptr, ":\n");
  600. X        fputs(line_start, hqxfile);
  601. X        fclose(hqxfile);
  602. X        }
  603. X    }
  604. END_OF_FILE
  605. if test 19992 -ne `wc -c <'mcvert/hqxify.c'`; then
  606.     echo shar: \"'mcvert/hqxify.c'\" unpacked with wrong size!
  607. fi
  608. # end of 'mcvert/hqxify.c'
  609. fi
  610. if test -f 'mcvert/mcvert.c' -a "${1}" != "-c" ; then 
  611.   echo shar: Will not clobber existing file \"'mcvert/mcvert.c'\"
  612. else
  613. echo shar: Extracting \"'mcvert/mcvert.c'\" \(13666 characters\)
  614. sed "s/^X//" >'mcvert/mcvert.c' <<'END_OF_FILE'
  615. X/* mcvert.c - version 1.05 - 10 January, 1990 modified 12 March, 1990 by NP
  616. X * Written by Doug Moore - Rice University - dougm@rice.edu - April '87
  617. X * Sun bug fixes, assorted stuff - Jim Sasaki, March '89
  618. X * Changed default max_line_size from 2000 to unlimited - Doug Moore, April, '89
  619. X * Sun 3/60 doesn't like odd-sized structs.  Bug fixed - Doug Moore, April, '89
  620. X *                                              - aided by Spencer W. Thomas
  621. X * Didn't handle properly many hqx files combined in one file.  Bug fixed -
  622. X *                                           Doug Moore, June, '89
  623. X * Modified to handle MacBinaryII specification. Jim Van Verth, Sept, '89
  624. X *
  625. X * Fixed a bug when there are blank lines in hqx data, as happens when newline
  626. X * get translated to CRLF and then to \n\n, common for some file transfers.
  627. X * The last hqx line would be lost if the previous line was blank or junk.
  628. X *    Glenn Trewitt, Stanford University, 1990    (1.05)
  629. X *
  630. X * Mcvert would hiccup on mail header lines "X-Mailer: ELM [version 2.2 PL14]"
  631. X * as "X-Mailer:" is a vaild hqx line! Added in code to special case this
  632. X * line and keep scanning for the real hqx data.
  633. X *      Nigel Perry, Imperial College, 12 March 1990 [NP]
  634. X *
  635. X * This program may be freely distributed for non-profit purposes.  It may not
  636. X * be sold, by itself or as part of a collection of software.  It may be freely
  637. X * modified as long as no modified version is distributed.  Modifications of
  638. X * interest to all can be incorporated into the program by sending them to me
  639. X * for distribution.  Parts of the code can be used in other programs.  I am not
  640. X * responsible for any damage caused by this program.  I hope you enjoy it.
  641. X */
  642. X
  643. X#include "mactypes.h"
  644. X
  645. X#define HQX 0
  646. X#define TEXT 1
  647. X#define DATA 2
  648. X#define RSRC 3
  649. X#define HOST 4
  650. X#define FORWARDS 0
  651. X#define BACKWARDS 1
  652. X
  653. XFILE *verbose;
  654. Xchar **hqxnames, **hqxnames_left;
  655. Xchar *dir, *ext, *text_author;
  656. Xchar *maxlines_str;
  657. Xint maxlines;
  658. X
  659. Xmain(argc, argv)
  660. Xint argc;
  661. Xchar **argv;
  662. X{   char *flags, *getenv();
  663. X    int direction, mode, unpit_flag;
  664. X
  665. X    argv++;
  666. X    argc--;
  667. X    verbose = stderr;
  668. X    direction = FORWARDS;
  669. X    mode = HQX;
  670. X    unpit_flag = 0;
  671. X
  672. X    if ((text_author = getenv("MAC_EDITOR"))    == NULL)    text_author = "MACA";
  673. X    if ((ext =         getenv("MAC_EXT"))       == NULL)    ext = ".bin";
  674. X    if ((dir =         getenv("MAC_DLOAD_DIR")) == NULL)    dir = ".";
  675. X    if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL)  maxlines = 0;
  676. X    else                                         maxlines = atoi(maxlines_str);
  677. X    
  678. X    /* Make command line arguments globally accessible */
  679. X    hqxnames = (char **) calloc(argc+1, sizeof(char *));
  680. X    hqxnames_left = hqxnames;
  681. X    while (argc--)  *hqxnames_left++ = *argv++;
  682. X    *hqxnames_left = "-";
  683. X    hqxnames_left = hqxnames;
  684. X
  685. X    while (strcmp(*hqxnames_left, "-")) {
  686. X        if (hqxnames_left[0][0] == '-') {
  687. X            flags = *hqxnames_left++;
  688. X            while (*++flags)
  689. X                switch (*flags) {
  690. X                case 'x':
  691. X                    mode = HQX;
  692. X                    break;
  693. X                case 'u':
  694. X                    mode = TEXT;
  695. X                    break;
  696. X                case 'd':
  697. X                    mode = DATA;
  698. X                    break;
  699. X                case 'r':
  700. X                    mode = RSRC;
  701. X                    break;
  702. X        case 'h':
  703. X            mode = HOST;
  704. X            break;
  705. X                case 'D':
  706. X                    direction = FORWARDS;
  707. X                    break;
  708. X                case 'U':
  709. X                    direction = BACKWARDS;
  710. X                    break;
  711. X                case 'q':
  712. X                    unpit_flag = 0;
  713. X                    break;
  714. X                case 'p':
  715. X                    unpit_flag = 1;
  716. X                    break;
  717. X                case 's':
  718. X                    verbose = fopen("/dev/null", "w");
  719. X                    break;
  720. X                case 'v':
  721. X                    verbose = stderr;
  722. X                    break;
  723. X                default:
  724. X                    error(
  725. X                    "Usage: mcvert [ -[r|d|u|x|h] [D|U] [p|q] [s|v] ] filename...",
  726. X                    NULL);
  727. X                    }
  728. X            }
  729. X
  730. X        if (direction == BACKWARDS)
  731. X            if (mode == HQX && unpit_flag) re_hqx();/* no re_pit() yet */
  732. X            else if (mode == HQX) re_hqx();
  733. X            else re_other(mode);
  734. X        else
  735. X            if (mode == HQX) un_hqx(unpit_flag);
  736. X            else un_other(mode);
  737. X        }
  738. X    }
  739. X
  740. X/* An array useful for CRC calculations that use 0x1021 as the "seed" */
  741. Xword magic[] = {
  742. X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  743. X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  744. X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  745. X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  746. X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  747. X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  748. X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  749. X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  750. X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  751. X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  752. X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  753. X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  754. X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  755. X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  756. X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  757. X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  758. X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  759. X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  760. X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  761. X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  762. X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  763. X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  764. X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  765. X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  766. X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  767. X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  768. X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  769. X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  770. X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  771. X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  772. X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  773. X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  774. X    };
  775. X
  776. X
  777. X/*
  778. X * calc_crc() --
  779. X *   Compute the MacBinary II-style CRC for the data pointed to by p, with the
  780. X *   crc seeded to seed.
  781. X *
  782. X *   Modified by Jim Van Verth to use the magic array for efficiency.
  783. X */
  784. Xshort calc_mb_crc(p, len, seed)
  785. Xunsigned char *p;
  786. Xlong len;
  787. Xshort seed;
  788. X{
  789. X  short hold;      /* crc computed so far */
  790. X  long  i;         /* index into data */
  791. X
  792. X  extern unsigned short magic[];   /* the magic array */
  793. X
  794. X  hold = seed;     /* start with seed */
  795. X  for (i = 0; i < len; i++, p++) {
  796. X    hold ^= (*p << 8);
  797. X    hold = (hold << 8) ^ magic[(unsigned char)(hold >> 8)];
  798. X  }
  799. X
  800. X  return (hold);
  801. X} /* calc_crc() */
  802. X
  803. X
  804. X/* Report a fatal error */
  805. Xerror(msg, name)
  806. Xchar msg[], name[];
  807. X{   fprintf(stderr, msg, name);
  808. X    putc('\n', stderr);
  809. X    exit(1);
  810. X    }
  811. X
  812. X/* replace illegal Unix characters in file name */
  813. X/* make sure host file name doesn't get truncated beyond recognition */
  814. Xunixify(np)
  815. Xregister byte *np;
  816. X{   register ulong c;
  817. X    c = strlen(np);
  818. X    if (c > SYSNAMELEN - 4) c = SYSNAMELEN - 4;
  819. X    np[c] = '\0';
  820. X    np--;
  821. X    while (c = *++np)
  822. X        if (c <= ' ' || c == '/' || c > '~') *np = '_';
  823. X    }
  824. X
  825. X/* Convert Unix time (GMT since 1-1-1970) to Mac
  826. X                                    time (local since 1-1-1904) */
  827. X#define MACTIMEDIFF 0x7c25b080 /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  828. X
  829. Xulong time2mac(time)
  830. Xulong time;
  831. X{   struct timeb tp;
  832. X    ftime(&tp);
  833. X    return long2mac(time + MACTIMEDIFF
  834. X                    - 60 * (tp.timezone - 60 * tp.dstflag));
  835. X    }
  836. X
  837. X
  838. X/* This procedure copies the input file to the output file, basically, although
  839. X    in TEXT mode it changes LF's to CR's and in any mode it forges a Mac info 
  840. X    header.  Author type for TEXT mode can come from the MAC_EDITOR environ-
  841. X    ment variable if it is defined. */
  842. X
  843. Xun_other(mode)
  844. Xint mode;
  845. X{   register ulong b;
  846. X    register ulong nchars;
  847. X    char txtfname[BINNAMELEN], binfname[BINNAMELEN];
  848. X    FILE *txtfile, *binfile; 
  849. X    char *suffix;
  850. X    struct stat stbuf;
  851. X    info_header info;
  852. X    int extra_chars;
  853. X    ulong dlen, rlen, mtim, ctim;
  854. X    short crc, calc_mb_crc();
  855. X
  856. X    if (mode == DATA) suffix = ".data";
  857. X    else if (mode == RSRC) suffix = ".rsrc";
  858. X    else suffix = ".text";
  859. X
  860. X    while (hqxnames_left[0][0] != '-') {
  861. X
  862. X        strcpy(txtfname, *hqxnames_left++);
  863. X        if (!(txtfile = fopen(txtfname, "r"))) {
  864. X            /* Maybe we are supposed to figure out the suffix ourselves? */
  865. X            strcat(txtfname, suffix);
  866. X            if (!(txtfile = fopen(txtfname, "r")))
  867. X                error("Cannot open %s", txtfname);
  868. X            }
  869. X
  870. X        if (stat(txtfname, &stbuf))
  871. X            error("Cannot read %s", txtfname);
  872. X
  873. X        /* stuff header data into the info header */
  874. X        bzero(&info, sizeof(info_header));
  875. X        info.nlen = strlen(txtfname);
  876. X        info.nlen = (info.nlen > NAMELEN) ? NAMELEN : info.nlen;
  877. X    info.name[info.nlen] = '\0';
  878. X        strcpy(info.name, txtfname);           /* name */
  879. X        mtim = time2mac(stbuf.st_mtime);
  880. X        ctim = time2mac(stbuf.st_ctime);
  881. X        bcopy(&mtim, info.mtim, 4);
  882. X        bcopy(&ctim, info.ctim, 4);
  883. X    info.uploadvers = '\201';
  884. X    info.readvers = '\201';
  885. X
  886. X        if (mode == RSRC) {
  887. X            /* dlen is already zero */
  888. X            rlen = long2mac(stbuf.st_size);
  889. X            bcopy(&rlen, info.rlen, 4);
  890. X            bcopy("APPL", info.type, 4);
  891. X            bcopy("CCOM", info.auth, 4);
  892. X            }
  893. X        else {
  894. X            dlen = long2mac(stbuf.st_size);
  895. X            bcopy(&dlen, info.dlen, 4);
  896. X            /* rlen is already zero */
  897. X            bcopy("TEXT", info.type, 4);
  898. X            if (mode == DATA) bcopy("????", info.auth, 4);
  899. X            else bcopy(text_author, info.auth, 4);
  900. X            }
  901. X
  902. X    /* calculate CRC */
  903. X    crc = calc_mb_crc(&info, 124, 0);
  904. X    info.crc[0] = (char) (crc >> 8);
  905. X    info.crc[1] = (char) crc;
  906. X
  907. X        /* Create the .bin file and write the info to it */
  908. X        sprintf(binfname, "%s/%s%s", dir, txtfname, ext);
  909. X        if ((binfile = fopen(binfname, "w")) == NULL)
  910. X            error("Cannot open %s", binfname);
  911. X        fprintf(verbose,
  912. X                "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  913. X                txtfname, info.type, info.auth);
  914. X        fwrite(&info, sizeof(info), 1, binfile);
  915. X
  916. X        nchars = stbuf.st_size;
  917. X        extra_chars = 127 - (nchars+127) % 128;
  918. X        if (mode == TEXT) while (nchars--) {
  919. X            b = getc(txtfile);
  920. X            if (b == LF) b = CR;
  921. X            putc(b, binfile);
  922. X            }
  923. X        else while (nchars--) putc(getc(txtfile), binfile);
  924. X
  925. X        while (extra_chars--) putc(0, binfile);
  926. X        fclose(binfile);
  927. X        fclose(txtfile);
  928. X        }
  929. X    }
  930. X
  931. X/* This procedure copies the input file to the output file, basically, although
  932. X    in TEXT mode it changes CR's to LF's and in any mode it skips over the Mac
  933. X    info header. */
  934. X
  935. Xre_other(mode)
  936. Xint mode;
  937. X{   register ulong b;
  938. X    register ulong nchars;
  939. X    char txtfname[BINNAMELEN], binfname[BINNAMELEN];
  940. X    FILE *txtfile, *binfile; 
  941. X    char *suffix;
  942. X    info_header info;
  943. X
  944. X    if (mode == DATA) suffix = ".data";
  945. X    else if (mode == RSRC) suffix = ".rsrc";
  946. X    else suffix = ".text";
  947. X
  948. X    while (hqxnames_left[0][0] != '-') {
  949. X
  950. X        strcpy(binfname, *hqxnames_left++);
  951. X        if ((binfile = fopen(binfname, "r")) == NULL) {
  952. X            /* Maybe we are supposed to figure out the suffix ourselves? */
  953. X            strcat(binfname, ext);
  954. X            if (!(binfile = fopen(binfname, "r")))
  955. X                error("Cannot open %s", binfname);
  956. X            }
  957. X
  958. X        /* Read the info from the .bin file, create the output file */
  959. X        fread(&info, sizeof(info), 1, binfile);
  960. X        strncpy(txtfname, info.name, info.nlen);
  961. X    txtfname[info.nlen] = '\0';
  962. X        fprintf(verbose,
  963. X                "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  964. X                txtfname, info.type, info.auth);
  965. X        if ((txtfile = fopen(txtfname, "r")) == NULL) {
  966. X            if ((txtfile = fopen(txtfname, "w")) == NULL)
  967. X                error("Cannot open %s", txtfname);
  968. X            }
  969. X        else {
  970. X            fclose(txtfile);
  971. X            strcat(txtfname, suffix);
  972. X            if ((txtfile = fopen(txtfname, "w")) == NULL)
  973. X                error("Cannot open %s", txtfname);
  974. X            }
  975. X
  976. X        nchars = mac2long(* (ulong *) info.dlen);
  977. X        if (mode == TEXT) while (nchars--) {
  978. X            b = getc(binfile);
  979. X            if (b == CR) b = LF;
  980. X            putc(b, txtfile);
  981. X            }
  982. X        else if (mode == DATA) while (nchars--)
  983. X            putc(getc(binfile), txtfile);
  984. X        else {
  985. X            while (nchars--) getc(binfile);
  986. X            nchars = mac2long(* (ulong *) info.rlen);
  987. X            while (nchars--) putc(getc(binfile), txtfile);
  988. X            }
  989. X
  990. X        fclose(binfile);
  991. X        fclose(txtfile);
  992. X        }
  993. X    }
  994. END_OF_FILE
  995. if test 13666 -ne `wc -c <'mcvert/mcvert.c'`; then
  996.     echo shar: \"'mcvert/mcvert.c'\" unpacked with wrong size!
  997. fi
  998. # end of 'mcvert/mcvert.c'
  999. fi
  1000. if test -f 'stuffit/sit.c' -a "${1}" != "-c" ; then 
  1001.   echo shar: Will not clobber existing file \"'stuffit/sit.c'\"
  1002. else
  1003. echo shar: Extracting \"'stuffit/sit.c'\" \(12417 characters\)
  1004. sed "s/^X//" >'stuffit/sit.c' <<'END_OF_FILE'
  1005. X/*
  1006. X * sit - Stuffit for UNIX
  1007. X *  Puts unix data files into stuffit archive suitable for downloading
  1008. X *    to a Mac.  Automatically processes files output from xbin.
  1009. X *
  1010. X *  Reverse engineered from unsit by Allan G. Weber, which was based on
  1011. X *  macput, which was based on ...
  1012. X *  Just like unsit this uses the host's version of compress to do the work.
  1013. X *
  1014. X * Examples:
  1015. X *   1) take collection of UNIX text files and make them LSC text files 
  1016. X *    when uncompressed on the mac:
  1017. X *       sit -u -T TEXT -C KAHL file ...
  1018. X *   2) Process output from xbin:
  1019. X *       xbin file1     (produces FileOne.{info,rsrc,data})
  1020. X *       sit file1
  1021. X *
  1022. X *  Tom Bereiter
  1023. X *    ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
  1024. X *
  1025. X * This version for CAP aufs files based on info from aufs source + mcvert etc.
  1026. X * Aufs version is program is called AUFSNAME (default stuffit)
  1027. X *
  1028. X * Aug 90. Nigel Perry, np@doc.ic.ac.uk
  1029. X *
  1030. X */
  1031. X#define BSD
  1032. X
  1033. X#include <sys/types.h>
  1034. X#include <sys/stat.h>
  1035. X#include <stdio.h>
  1036. X#include "sit.h"
  1037. X#ifdef BSD
  1038. X#include <sys/time.h>
  1039. X#include <sys/timeb.h>
  1040. X#else
  1041. X#include <time.h>
  1042. Xextern long timezone;
  1043. X#endif
  1044. X
  1045. X#ifndef min
  1046. X#define min(a,b) ((a)<(b)?(a):(b))
  1047. X#endif
  1048. X
  1049. X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  1050. X#define TIMEDIFF 0x7c25b080
  1051. X
  1052. X/* if called by this name, program will work on aufs files */
  1053. X#define AUFSNAME "stuffit"
  1054. X
  1055. Xstruct sitHdr sh;
  1056. Xstruct fileHdr fh;
  1057. X
  1058. Xchar buf[BUFSIZ];
  1059. Xchar *defoutfile = "archive.sit";
  1060. Xint ofd;
  1061. Xushort crc;
  1062. Xint clen;
  1063. Xint rmfiles;
  1064. Xint    unixf;
  1065. Xchar *Creator, *Type;
  1066. Xint aufs;
  1067. X
  1068. Xusage() { fprintf(stderr,"Usage: sit file\n"); }
  1069. Xextern char *optarg;
  1070. Xextern int optind;
  1071. X
  1072. X/********************************************************************************/
  1073. X/* added for aufs, nicked from various places... */
  1074. X
  1075. X/* following from mcvert program */
  1076. X
  1077. X/* Useful, though not particularly Mac related, values */
  1078. Xtypedef unsigned char byte;     /* one byte, obviously */
  1079. Xtypedef unsigned short word;    /* must be 2 bytes */
  1080. Xtypedef unsigned long ulong;    /* 4 bytes */
  1081. X
  1082. X#define NAMELEN 63              /* maximum legal Mac file name length */
  1083. X
  1084. X/* Format of a bin file:
  1085. XA bin file is composed of 128 byte blocks.  The first block is the
  1086. Xinfo_header (see below).  Then comes the data fork, null padded to fill the
  1087. Xlast block.  Then comes the resource fork, padded to fill the last block.  A
  1088. Xproposal to follow with the text of the Get Info box has not been implemented,
  1089. Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
  1090. Xprogram looks at to determine if a MacBinary transfer is being initiated.
  1091. X*/ 
  1092. Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
  1093. X                        longs don't align to word boundaries */
  1094. X            byte version;           /* there is only a version 0 at this time */
  1095. X            byte nlen;              /* Length of filename. */
  1096. X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
  1097. X            byte type[4];           /* File type. */
  1098. X            byte auth[4];           /* File creator. */
  1099. X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
  1100. X            byte zero1;             /* Locked, Invisible,Bundle, System */
  1101. X                                    /* Bozo, Busy, Changed, Init */
  1102. X            byte icon_vert[2];      /* Vertical icon position within window */
  1103. X            byte icon_horiz[2];     /* Horizontal icon postion in window */
  1104. X            byte window_id[2];      /* Window or folder ID. */
  1105. X            byte protect;           /* = 1 for protected file, 0 otherwise */
  1106. X            byte zero2;
  1107. X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
  1108. X            byte rflen[4];          /* Resource Fork length         byte first */
  1109. X            byte cdate[4];          /* File's creation date. */
  1110. X            byte mdate[4];          /* File's "last modified" date. */
  1111. X            byte ilen[2];           /* GetInfo message length */
  1112. X        byte flags2;            /* Finder flags, bits 0-7 */
  1113. X        byte unused[14];       
  1114. X        byte packlen[4];        /* length of total files when unpacked */
  1115. X        byte headlen[2];        /* length of secondary header */
  1116. X        byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
  1117. X        byte readvers;          /* Minimum MacBinary II version needed to read this file */
  1118. X            byte crc[2];            /* CRC of the previous 124 bytes */
  1119. X        byte padding[2];        /* two trailing unused bytes */
  1120. X            } info_header;
  1121. X
  1122. X/* end of mcvert stuff */
  1123. X/* from CAP aufs documentation */
  1124. X
  1125. X#define FINFOLEN 32
  1126. X#define MAXCLEN 199
  1127. Xtypedef struct
  1128. X{  /* byte fi_fndr[FINFOLEN]; */    /* finder info */
  1129. X   /* what I think the above is... */
  1130. X   ulong fndr_type, fndr_creator;
  1131. X   word fndr_flags;
  1132. X   ulong fndr_loc;
  1133. X   word fndr_fldr;
  1134. X   word fndr_icon;
  1135. X   byte fndr_unused[8];
  1136. X   word fndr_comment;
  1137. X   ulong fndr_putaway;
  1138. X   /* end of fi_fndr */
  1139. X
  1140. X   word fi_attr;            /* attributes */
  1141. X#define FI_MAGIC1 255
  1142. X   byte fi_magic1;        /* was: length of comment */
  1143. X#define FI_VERSION 0x10        /* version major 1, minor 0 */
  1144. X                /* if more than 8 versions then */
  1145. X                /* something wrong anyway */
  1146. X   byte fi_version;        /* version number */
  1147. X#define FI_MAGIC 0xda
  1148. X   byte fi_magic;        /* magic word check */
  1149. X   byte fi_bitmap;        /* bitmap of included info */
  1150. X#define FI_BM_SHORTFILENAME 0x1    /* is this included? */
  1151. X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
  1152. X   byte fi_shortfilename[12+1];    /* possible short file name */
  1153. X   byte fi_macfilename[32+1];    /* possible macintosh file name */
  1154. X   byte fi_comln;        /* comment length */
  1155. X   byte fi_comnt[MAXCLEN+1];    /* comment string */
  1156. X} FileInfo;
  1157. X
  1158. XFileInfo fndr_info;
  1159. X
  1160. X/* end aufs */
  1161. X/********************************************************************************/
  1162. X
  1163. Xmain(argc,argv) char **argv; {
  1164. X    int i,n;
  1165. X    int total, nfiles;
  1166. X    int c;
  1167. X
  1168. X    rmfiles = unixf = 0;
  1169. X    aufs = strcmp(argv[0], AUFSNAME) == 0;
  1170. X
  1171. X    while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
  1172. X    switch (c) {
  1173. X        case 'r':
  1174. X            rmfiles++;    /* remove files when done */
  1175. X            break;
  1176. X        case 'o':        /* specify output file */
  1177. X            defoutfile = optarg;
  1178. X            break;
  1179. X        case 'u':        /* unix file -- change '\n' to '\r' */
  1180. X            unixf++;
  1181. X            break;
  1182. X        case 'C':        /* set Mac creator */
  1183. X            Creator = optarg;
  1184. X            break;
  1185. X        case 'T':        /* set Mac file type */
  1186. X            Type = optarg;
  1187. X            break;
  1188. X        case '?':
  1189. X            usage();
  1190. X            exit(1);
  1191. X    }
  1192. X
  1193. X    if(aufs && (strlen(defoutfile) > 32))
  1194. X    {   fprintf(stderr, "Output name must not exceed 32 characters: %s\n", defoutfile);
  1195. X        exit(-1);
  1196. X    }
  1197. X
  1198. X    if(aufs)
  1199. X    {    /* make the .finderinfo file */
  1200. X        char buf[32+12+1];
  1201. X
  1202. X        strcpy(buf, ".finderinfo/");
  1203. X        strcat(buf, defoutfile);
  1204. X        if ((ofd=creat(buf,0644))<0)
  1205. X        {   perror(buf);
  1206. X            exit(1);
  1207. X        }
  1208. X        bzero(&fndr_info, sizeof(FileInfo));
  1209. X        bcopy("SIT!", &fndr_info.fndr_type, 4);
  1210. X        bcopy("SIT!", &fndr_info.fndr_creator, 4);
  1211. X        fndr_info.fi_magic1 = FI_MAGIC1;
  1212. X        fndr_info.fi_version = FI_VERSION;
  1213. X        fndr_info.fi_magic = FI_MAGIC;
  1214. X        fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
  1215. X        strcpy(fndr_info.fi_macfilename, defoutfile);
  1216. X        write(ofd, &fndr_info, sizeof(FileInfo));
  1217. X        close(ofd);
  1218. X    }
  1219. X
  1220. X    if ((ofd=creat(defoutfile,0644))<0) {
  1221. X        perror(defoutfile);
  1222. X        exit(1);
  1223. X    }
  1224. X    /* empty header, will seek back and fill in later */
  1225. X    write(ofd,&sh,sizeof sh);
  1226. X
  1227. X    for (i=optind; i<argc; i++) {
  1228. X        n = put_file(argv[i]);
  1229. X        if (n) {
  1230. X            total += n;
  1231. X            nfiles++;
  1232. X        }
  1233. X    }
  1234. X    lseek(ofd,0,0);
  1235. X
  1236. X    total += sizeof(sh);
  1237. X    /* header header */
  1238. X    strncpy(sh.sig1,"SIT!",4);
  1239. X    cp2(nfiles,sh.numFiles);
  1240. X    cp4(total,sh.arcLen);
  1241. X    strncpy(sh.sig2,"rLau",4);
  1242. X    sh.version = 1;
  1243. X
  1244. X    write(ofd,&sh,sizeof sh);
  1245. X}
  1246. X
  1247. Xput_file(name)
  1248. Xchar name[];
  1249. X{
  1250. X    struct stat st;
  1251. X    struct infohdr ih;
  1252. X    int i,n,fd;
  1253. X    long fpos1, fpos2;
  1254. X    char nbuf[256], *p;
  1255. X    int fork=0;
  1256. X    long tdiff;
  1257. X    struct tm *tp;
  1258. X#ifdef BSD
  1259. X    struct timeb tbuf;
  1260. X#else
  1261. X    long bs;
  1262. X#endif
  1263. X
  1264. X    fpos1 = lseek(ofd,0,1); /* remember where we are */
  1265. X    /* write empty header, will seek back and fill in later */
  1266. X    bzero(&fh,sizeof fh);
  1267. X    write(ofd,&fh,sizeof fh);
  1268. X
  1269. X    /* look for resource fork */
  1270. X    if(aufs)
  1271. X    {   strcpy(nbuf, ".resource/");
  1272. X        strcat(nbuf, name);
  1273. X    }
  1274. X    else
  1275. X    {   strcpy(nbuf,name);
  1276. X        strcat(nbuf,".rsrc");
  1277. X    }
  1278. X    if (stat(nbuf,&st)>=0 && st.st_size) {    /* resource fork exists */
  1279. X        dofork(nbuf);
  1280. X        cp4(st.st_size,fh.rLen);
  1281. X        cp4(clen,fh.cRLen);
  1282. X        cp2(crc,fh.rsrcCRC);
  1283. X        fh.compRMethod = lpzComp;
  1284. X        fork++;
  1285. X    }
  1286. X    if (rmfiles) unlink(nbuf);    /* ignore errors */
  1287. X
  1288. X    /* look for data fork */
  1289. X    st.st_size = 0;
  1290. X    strcpy(nbuf,name);
  1291. X    if (stat(nbuf,&st)<0) {        /* first try plain name */
  1292. X        strcat(nbuf,".data");
  1293. X        stat(nbuf,&st);
  1294. X    }
  1295. X    if (st.st_size) {        /* data fork exists */
  1296. X        dofork(nbuf);
  1297. X        cp4(st.st_size,fh.dLen);
  1298. X        cp4(clen,fh.cDLen);
  1299. X        cp2(crc,fh.dataCRC);
  1300. X        fh.compDMethod = lpzComp;
  1301. X        fork++;
  1302. X    }
  1303. X    if (fork == 0) {
  1304. X        fprintf(stderr,"%s: no data or resource files\n",name);
  1305. X        return 0;
  1306. X    }
  1307. X    if (rmfiles) unlink(nbuf);    /* ignore errors */
  1308. X
  1309. X    /* look for .info file */
  1310. X    if(aufs)
  1311. X    {   strcpy(nbuf, ".finderinfo/");
  1312. X        strcat(nbuf, name);
  1313. X    }
  1314. X    else
  1315. X    {   strcpy(nbuf,name);
  1316. X        strcat(nbuf,".info");
  1317. X    }
  1318. X    if((fd=open(nbuf,0))>=0
  1319. X       && ((!aufs && read(fd,&ih,sizeof(ih))==sizeof(ih))
  1320. X           || (aufs && read(fd,&fndr_info,sizeof(FileInfo))==sizeof(FileInfo))
  1321. X          )
  1322. X      )
  1323. X    {   if(aufs)
  1324. X        {   char *np;
  1325. X        
  1326. X        np = (char *)(fndr_info.fi_bitmap & FI_BM_MACINTOSHFILENAME ? fndr_info.fi_macfilename
  1327. X                                        : fndr_info.fi_shortfilename);
  1328. X        fh.fName[0] = (char)strlen(np);
  1329. X        strncpy(fh.fName+1, np, 64);
  1330. X        bcopy(&fndr_info.fndr_type, fh.fType, 4);
  1331. X        bcopy(&fndr_info.fndr_creator, fh.fCreator, 4);
  1332. X        bcopy(&fndr_info.fndr_flags, fh.FndrFlags, 2);
  1333. X#ifdef BSD
  1334. X        ftime(&tbuf);
  1335. X        tp = localtime(&tbuf.time);
  1336. X        tdiff = TIMEDIFF - tbuf.timezone * 60;
  1337. X        if (tp->tm_isdst)
  1338. X            tdiff += 60 * 60;
  1339. X#else
  1340. X        /* I hope this is right! -andy */
  1341. X        time(&bs);
  1342. X        tp = localtime(&bs);
  1343. X        tdiff = TIMEDIFF - timezone;
  1344. X        if (tp->tm_isdst)
  1345. X            tdiff += 60 * 60;
  1346. X#endif
  1347. X        cp4(st.st_ctime + tdiff, fh.cDate);
  1348. X        cp4(st.st_mtime + tdiff, fh.mDate);
  1349. X        }
  1350. X        else
  1351. X        {   strncpy(fh.fName, ih.name,64);
  1352. X        strncpy(fh.fType, ih.type, 4);
  1353. X        strncpy(fh.fCreator, ih.creator, 4);
  1354. X        strncpy(fh.FndrFlags, ih.flag, 2);
  1355. X        strncpy(fh.cDate, ih.ctime, 4);
  1356. X        strncpy(fh.mDate, ih.mtime, 4);
  1357. X        }
  1358. X    }
  1359. X    else {    /* no info file so fake it */
  1360. X        strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
  1361. X        /* default to LSC text file */
  1362. X        strncpy(fh.fType, Type ? Type : "TEXT", 4);
  1363. X        strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
  1364. X        /* convert unix file time to mac time format */
  1365. X#ifdef BSD
  1366. X        ftime(&tbuf);
  1367. X        tp = localtime(&tbuf.time);
  1368. X        tdiff = TIMEDIFF - tbuf.timezone * 60;
  1369. X        if (tp->tm_isdst)
  1370. X            tdiff += 60 * 60;
  1371. X#else
  1372. X        /* I hope this is right! -andy */
  1373. X        time(&bs);
  1374. X        tp = localtime(&bs);
  1375. X        tdiff = TIMEDIFF - timezone;
  1376. X        if (tp->tm_isdst)
  1377. X            tdiff += 60 * 60;
  1378. X#endif
  1379. X        cp4(st.st_ctime + tdiff, fh.cDate);
  1380. X        cp4(st.st_mtime + tdiff, fh.mDate);
  1381. X    }
  1382. X    close(fd);
  1383. X    if (rmfiles) unlink(nbuf);    /* ignore errors */
  1384. X
  1385. X    crc = updcrc(0,&fh,(sizeof fh)-2);
  1386. X    cp2(crc, fh.hdrCRC);
  1387. X
  1388. X    fpos2 = lseek(ofd,0,1);        /* remember where we are */
  1389. X    lseek(ofd,fpos1,0);                /* seek back over file(s) and header */
  1390. X    write(ofd,&fh,sizeof fh);        /* write back header */
  1391. X    fpos2=lseek(ofd,fpos2,0);                /* seek forward file */
  1392. X
  1393. X    return (fpos2 - fpos1);
  1394. X}
  1395. X    
  1396. Xdofork(name)
  1397. Xchar name[];
  1398. X{
  1399. X    FILE *fs;
  1400. X    int n, fd, ufd;
  1401. X    char *p;
  1402. X
  1403. X    if ((fd=open(name,0))<0) {
  1404. X        perror(name);
  1405. X        return 0;
  1406. X    }   
  1407. X    if (unixf)        /* build conversion file */
  1408. X        if ((ufd=creat("sit+temp",0644))<0) {
  1409. X            perror("sit+temp");
  1410. X            return 0;
  1411. X        }   
  1412. X    /* do crc of file: */
  1413. X    crc = 0;
  1414. X    while ((n=read(fd,buf,BUFSIZ))>0) {
  1415. X        if (unixf) {    /* convert '\n' to '\r' */
  1416. X            for (p=buf; p<&buf[n]; p++)
  1417. X                if (*p == '\n') *p = '\r';
  1418. X            write(ufd,buf,n);
  1419. X        }
  1420. X        crc = updcrc(crc,buf,n);
  1421. X    }
  1422. X    close(fd);
  1423. X    /*
  1424. X     * open pipe to compress file
  1425. X     *   If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
  1426. X     *   with the conversion done.    Otherwise, 'sit+temp' is just a link to 
  1427. X     *   the input file.
  1428. X     */
  1429. X    if (unixf)
  1430. X        close(ufd);
  1431. X    else link(name,"sit+temp");
  1432. X    fs = popen("compress -c -n -b 14 sit+temp","r");
  1433. X    if (fs == NULL) {
  1434. X        perror(name);
  1435. X        return 0;
  1436. X    }
  1437. X    /* write out compressed file */
  1438. X    clen = 0;
  1439. X    while ((n=fread(buf,1,BUFSIZ,fs))>0) {
  1440. X        write(ofd,buf,n);
  1441. X        clen += n;
  1442. X    }
  1443. X    pclose(fs);
  1444. X    unlink("sit+temp");
  1445. X}
  1446. X
  1447. Xcp2(x,dest)
  1448. Xunsigned short x;
  1449. Xchar dest[];
  1450. X{
  1451. X    dest[0] = x>>8;
  1452. X    dest[1] = x;
  1453. X}
  1454. X
  1455. Xcp4(x,dest)
  1456. Xunsigned long x;
  1457. Xchar dest[];
  1458. X{
  1459. X    dest[0] = x>>24;
  1460. X    dest[1] = x>>16;
  1461. X    dest[2] = x>>8;
  1462. X    dest[3] = x;
  1463. X}
  1464. END_OF_FILE
  1465. if test 12417 -ne `wc -c <'stuffit/sit.c'`; then
  1466.     echo shar: \"'stuffit/sit.c'\" unpacked with wrong size!
  1467. fi
  1468. # end of 'stuffit/sit.c'
  1469. fi
  1470. echo shar: End of archive 3 \(of 4\).
  1471. cp /dev/null ark3isdone
  1472. MISSING=""
  1473. for I in 1 2 3 4 ; do
  1474.     if test ! -f ark${I}isdone ; then
  1475.     MISSING="${MISSING} ${I}"
  1476.     fi
  1477. done
  1478. if test "${MISSING}" = "" ; then
  1479.     echo You have unpacked all 4 archives.
  1480.     rm -f ark[1-9]isdone
  1481. else
  1482.     echo You still need to unpack the following archives:
  1483.     echo "        " ${MISSING}
  1484. fi
  1485. ##  End of shell archive.
  1486. exit 0
  1487. --- end of part 3 ---
  1488.  
  1489.  
  1490.