home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
aufstols.zoo
/
aufstools.3
< prev
next >
Wrap
Text File
|
1991-02-26
|
50KB
|
1,490 lines
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 4)."
# Contents: mcvert/hqxify.c mcvert/mcvert.c stuffit/sit.c
# Wrapped by np@asun5 on Mon Dec 3 13:15:58 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mcvert/hqxify.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mcvert/hqxify.c'\"
else
echo shar: Extracting \"'mcvert/hqxify.c'\" \(19992 characters\)
sed "s/^X//" >'mcvert/hqxify.c' <<'END_OF_FILE'
X#include "mactypes.h"
X
X#define HQXBUFLEN 512
Xbyte hqxbuf[HQXBUFLEN+1], *buf_ptr, *buf_end, *buf_start=hqxbuf+1;
X
X#define MAXLINE 255
Xbyte line[MAXLINE+1], *line_ptr, *line_end, *line_start=line+1;
X
Xint line_count, file_count;
Xint save_state, total_bytes, save_run_length;
Xword save_nibble;
Xchar binfname[BINNAMELEN], hqxfname[BINNAMELEN];
XFILE *hqxfile, *binfile;
X
X/* This routine reads the header of a hqxed file and appropriately twiddles it,
X determines if it has CRC problems, creates the .bin file, and puts the info
X into the .bin file.
X Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile */
X
Xhqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen)
Xchar *type;
Xulong *hqx_datalen, *hqx_rsrclen;
X{ register byte *hqx_ptr, *hqx_end;
X register ulong calc_crc;
X hqx_buf *hqx_block;
X hqx_header *hqx;
X info_header info;
X ulong mtim;
X short crc;
X
X extern word magic[];
X extern FILE *verbose;
X extern char *dir, *ext;
X extern short calc_mb_crc();
X
X /* read the hqx header, assuming that I won't exhaust hqxbuf in so doing */
X fill_hqxbuf();
X hqx_block = (hqx_buf *) buf_ptr;
X hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
X hqx_ptr = buf_ptr;
X hqx_end = (byte *) hqx + sizeof(hqx_header) - 1;
X calc_crc = 0;
X while (hqx_ptr < hqx_end)
X calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X buf_ptr = hqx_ptr;
X
X /* stuff the hqx header data into the info header */
X bzero(&info, sizeof(info_header));
X info.nlen = hqx_block->nlen;
X strncpy(info.name, hqx_block->name, info.nlen); /* name */
X bcopy(hqx->type, info.type, 9); /* type, author, flag */
X info.flags &= 0x7e; /* reset lock bit, init bit */
X if (hqx->protect & 0x40) info.protect = 1; /* copy protect bit */
X bcopy(hqx->dlen, info.dlen, 8); /* dlen, rlen */
X mtim = time2mac(time(0));
X bcopy(&mtim, info.mtim, 4);
X bcopy(&mtim, info.ctim, 4);
X info.uploadvers = '\201';
X info.readvers = '\201';
X
X /* calculate MacBinary CRC */
X crc = calc_mb_crc(&info, 124, 0);
X info.crc[0] = (char) (crc >> 8);
X info.crc[1] = (char) crc;
X
X /* Create the .bin file and write the info to it */
X unixify(hqx_block->name);
X sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
X fprintf(verbose,
X "Converting %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X hqx_block->name, info.type, info.auth);
X if ((binfile = fopen(binfname, "w")) == NULL)
X error("Cannot open %s", binfname);
X check_hqx_crc(calc_crc, "File header CRC mismatch in %s", binfname);
X fwrite(&info, sizeof(info), 1, binfile);
X
X /* Get a couple of items we'll need later */
X bcopy(info.dlen, hqx_datalen, 4);
X *hqx_datalen = mac2long(*hqx_datalen);
X bcopy(info.rlen, hqx_rsrclen, 4);
X *hqx_rsrclen = mac2long(*hqx_rsrclen);
X bcopy(info.type, type, 4);
X }
X
X/* This routine reads the header of a bin file and appropriately twiddles it,
X creates the .hqx file, and puts the info into the .hqx file.
X Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
X
Xbin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
Xulong *hqx_datalen, *hqx_rsrclen;
X{ register byte *hqx_ptr, *hqx_end;
X register ulong calc_crc;
X hqx_buf *hqx_block;
X hqx_header *hqx;
X info_header info;
X extern word magic[];
X extern FILE *verbose;
X extern char **hqxnames_left;
X extern char *ext;
X
X strcpy(binfname, *hqxnames_left++);
X if (!(binfile = fopen(binfname, "r"))) {
X /* Maybe we are supposed to figure out the suffix ourselves? */
X strcat(binfname, ext);
X if (!(binfile = fopen(binfname, "r")))
X error("Cannot open %s", binfname);
X }
X if (!fread(&info, sizeof(info), 1, binfile))
X error("Unexpected EOF in header of %s", binfname);
X
X /* stuff the info header into the hqx header */
X hqx_block = (hqx_buf *) buf_ptr;
X hqx_block->nlen = info.nlen;
X strncpy(hqx_block->name, info.name, info.nlen);
X hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
X hqx->version = 0;
X bcopy(info.type, hqx->type, 9); /* type, author, flags */
X if (info.protect = 1) hqx->protect = 0; /* protect bit: 0x40 */
X else hqx->protect = 0;
X bcopy(info.dlen, hqx->dlen, 8); /* dlen, rlen */
X
X /* Create the .hqx file and write the info to it */
X strncpy(hqxfname, info.name, info.nlen);
X hqxfname[info.nlen] = '\0';
X unixify(hqxfname);
X fprintf(verbose,
X "Converting %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X hqxfname, info.type, info.auth);
X
X calc_crc = 0;
X hqx_ptr = (byte *) hqx_block;
X hqx_end = hqx_ptr + hqx_block->nlen + sizeof(hqx_header);
X while (hqx_ptr < hqx_end)
X calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X buf_ptr = hqx_end;
X write_hqx_crc(calc_crc);
X
X /* Get a couple of items we'll need later */
X bcopy(info.dlen, hqx_datalen, 4);
X *hqx_datalen = mac2long(*hqx_datalen);
X bcopy(info.rlen, hqx_rsrclen, 4);
X *hqx_rsrclen = mac2long(*hqx_rsrclen);
X }
X
X
X/* This routine copies bytes from the decoded input stream to the output.
X It also pads to a multiple of 128 bytes on the output, which is part
X of the .bin format */
Xword hqx_to_bin_fork(nbytes)
Xregister ulong nbytes;
X{ register byte *c;
X register ulong calc_crc;
X register int c_length;
X ulong extra_bytes;
X extern word magic[];
X
X extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
X calc_crc = 0;
X for (;;) {
X c = buf_ptr;
X c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
X nbytes -= c_length;
X fwrite(c, sizeof(byte), c_length, binfile);
X while (c_length--)
X calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
X if (!nbytes) break;
X fill_hqxbuf();
X }
X buf_ptr = c;
X while (extra_bytes--) putc(0, binfile);
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X return (word) calc_crc;
X }
X
X/* This routine copies bytes from the input stream to the encoded output.
X It also pads to a multiple of 128 bytes on the input, which is part
X of the .bin format */
Xword bin_to_hqx_fork(nbytes)
Xregister ulong nbytes;
X{ register byte *c;
X register ulong calc_crc;
X register int c_length;
X ulong extra_bytes;
X extern word magic[];
X
X extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
X calc_crc = 0;
X for (;;) {
X c = buf_ptr;
X c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
X nbytes -= c_length;
X fread(c, sizeof(byte), c_length, binfile);
X buf_ptr += c_length;
X while (c_length--)
X calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
X if (!nbytes) break;
X empty_hqxbuf();
X }
X buf_ptr = c;
X
X fseek(binfile, extra_bytes, 1);
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
X return (word) calc_crc;
X }
X
X/* Essentials for Binhex 8to6 run length encoding */
X#define RUNCHAR 0x90
X#define MAXRUN 255
X#define IS_LEGAL <0x40
X#define ISNT_LEGAL >0x3f
X#define DONE 0x7F /* tr68[':'] = DONE, since Binhex terminator is ':' */
X#define SKIP 0x7E /* tr68['\n'|'\r'] = SKIP, i. e. end of line char. */
X#define FAIL 0x7D /* character illegal in binhex file */
X
Xbyte tr86[] =
X "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
Xbyte tr68[] = {
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
X 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
X 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
X 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
X 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
X 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
X 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
X 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
X 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
X 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
X 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
X };
X
X/*
X * This procedure transparently reads and decodes the hqx input. It does run
X * length and 6 to 8 decoding.
X */
X#define READING 0
X#define SKIPPING 1
X#define FIND_START_COLON 2
X
X/* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
X#define X_MAIL_STR "\054\014\043\061\070\073\065\077\177"
X#define X_MAIL_LEN strlen(X_MAIL_STR)
X
Xfill_hqxbuf()
X{ register ulong c, nibble;
X register int not_in_a_run = TRUE, state68;
X register byte *fast_buf, *fast_line;
X static int status = FIND_START_COLON;
X
X buf_ptr = fast_buf = buf_start;
X fast_line = line_ptr;
X state68 = save_state;
X nibble = save_nibble;
X if (save_run_length > 0) {
X c = save_run_length;
X save_run_length = 0;
X goto continue_run;
X }
X while (fast_buf < buf_end) {
X next_char:
X if ((c = *fast_line++) ISNT_LEGAL) {
X if (c == DONE) break;
X next_line:
X if (!fgets(line_start, MAXLINE, hqxfile) && !new_in_hqx_file())
X if (status == FIND_START_COLON) exit(0);
X else error("Premature EOF in %s\n", hqxfname);
X line_ptr = line_start;
X scan_line:
X fast_line = line_ptr;
X while ((*fast_line = tr68[*fast_line]) IS_LEGAL) fast_line++;
X c = *fast_line;
X switch (status) {
X case READING:
X if (c == SKIP && fast_line == line_end) break;
X if (c == DONE) {
X status = FIND_START_COLON;
X break;
X }
X status = SKIPPING;
X goto next_line;
X case SKIPPING:
X if (c == SKIP && fast_line == line_end) {
X status = READING;
X break;
X }
X /* GMT, 1/9/90: Added this clause to avoid losing the last
X * line if it was preceeded by a skipped line. */
X if (c == DONE) {
X /* NP 12/3/90: A dirty hack to handle "X-Mailer: ELM [version 2.2 PL14]" */
X if( (fast_line - line_ptr == X_MAIL_LEN - 1)
X && (strncmp(line_ptr, X_MAIL_STR, X_MAIL_LEN) == 0)) goto next_line;
X status = FIND_START_COLON;
X break;
X }
X goto next_line;
X case FIND_START_COLON:
X if (*line_start == DONE) {
X status = READING;
X line_ptr++;
X goto scan_line;
X }
X goto next_line;
X }
X fast_line = line_ptr;
X c = *fast_line++;
X }
X
X /* Finally, we have the next 6 bits worth of data */
X switch (state68++) {
X case 0:
X nibble = c;
X goto next_char;
X case 1:
X nibble = (nibble << 6) | c;
X c = nibble >> 4;
X break;
X case 2:
X nibble = (nibble << 6) | c;
X c = (nibble >> 2) & 0xff;
X break;
X case 3:
X c = (nibble << 6) & 0xff | c;
X state68 = 0;
X break;
X }
X if (not_in_a_run)
X if (c != RUNCHAR) *fast_buf++ = c;
X else {not_in_a_run = FALSE; goto next_char;}
X else {
X if (c--) {
X not_in_a_run = buf_end - fast_buf;
X if (c > not_in_a_run) {
X save_run_length = c - not_in_a_run;
X c = not_in_a_run;
X }
X continue_run:
X not_in_a_run = fast_buf[-1];
X while (c--) *fast_buf++ = not_in_a_run;
X }
X else *fast_buf++ = RUNCHAR;
X not_in_a_run = TRUE;
X }
X }
X total_bytes += fast_buf - buf_ptr;
X buf_start[-1] = fast_buf[-1];
X line_ptr = fast_line;
X save_state = state68;
X save_nibble = nibble;
X }
X
X
Xnew_in_hqx_file()
X{ char *hqx_ext;
X extern char **hqxnames_left;
X if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') return FALSE;
X strcpy(hqxfname, *hqxnames_left++);
X hqx_ext = hqxfname + strlen(hqxfname) - 4;
X if (!strcmp(hqx_ext, ".hqx"))
X if (!freopen(hqxfname, "r", hqxfile))
X error("Cannot open %s\n", hqxfname);
X else;
X else {
X if (!freopen(hqxfname, "r", hqxfile)) {
X hqx_ext += 4;
X strcpy(hqx_ext, ".hqx");
X if (!freopen(hqxfname, "r", hqxfile)) {
X error("Cannot find %s\n", hqxfname);
X }
X }
X }
X fgets(line_start, MAXLINE, hqxfile);
X return TRUE;
X }
X
X/*
X * This procedure transparently encodes and writes the hqx output.
X * It does run length and 8 to 6 encoding.
X */
Xempty_hqxbuf()
X{ register ulong c, nibble, last_c;
X register byte *fast_buf, *fast_line;
X register int state86, dont_look_for_runs = FALSE, run_length;
X extern int maxlines;
X
X run_length = save_run_length;
X last_c = buf_start[-1];
X fast_buf = buf_start;
X fast_line = line_ptr;
X state86 = save_state;
X nibble = save_nibble;
X while (fast_buf < buf_ptr) {
X c = *fast_buf++;
X if (dont_look_for_runs) dont_look_for_runs = FALSE;
X else if (last_c == c && run_length < MAXRUN) {run_length++; continue;}
X else {
X if (run_length >1) {
X --fast_buf;
X if (run_length == 2 && last_c != RUNCHAR) c = last_c;
X else {
X c = RUNCHAR;
X *--fast_buf = run_length;
X dont_look_for_runs = TRUE;
X }
X run_length = 1;
X }
X else last_c = c;
X if (c == RUNCHAR && !dont_look_for_runs) {
X *--fast_buf = 0;
X dont_look_for_runs = TRUE;
X }
X }
X
X if (fast_line == line_end) {
X if (line_count++ == maxlines) new_out_hqx_file();
X fputs(line_start, hqxfile);
X fast_line = line_start;
X }
X
X switch (state86++) {
X case 0:
X *fast_line++ = tr86[ c >> 2 ];
X nibble = (c << 4) & 0x3f;
X break;
X case 1:
X *fast_line++ = tr86[ (c >> 4) | nibble ];
X nibble = (c << 2) & 0x3f;
X break;
X case 2:
X *fast_line++ = tr86[ (c >> 6) | nibble ];
X if (fast_line == line_end) {
X if (line_count++ == maxlines) new_out_hqx_file();
X fputs(line_start, hqxfile);
X fast_line = line_start;
X }
X *fast_line++ = tr86[ c & 0x3f ];
X state86 = 0;
X break;
X }
X }
X save_run_length = run_length;
X buf_start[-1] = last_c;
X buf_ptr = buf_start;
X line_ptr = fast_line;
X save_state = state86;
X save_nibble = nibble;
X }
X
Xnew_out_hqx_file()
X{ char filename[NAMELEN + 7];
X extern int maxlines;
X fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
X fclose(hqxfile);
X file_count++;
X if (maxlines) sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
X else sprintf(filename, "%s.hqx", hqxfname);
X if ((hqxfile = fopen(filename, "w")) == NULL)
X error("Can't create %s", filename);
X if (file_count > 1)
X fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
X else fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
X line_count = 3;
X }
X
Xcheck_hqx_crc(calc_crc, msg, name)
Xword calc_crc;
Xchar msg[], name[];
X{ word read_crc;
X if (buf_ptr >= buf_end) fill_hqxbuf();
X read_crc = *buf_ptr++ << 8;
X if (buf_ptr >= buf_end) fill_hqxbuf();
X read_crc |= *buf_ptr++;
X if (read_crc != calc_crc) error(msg, name);
X }
X
Xwrite_hqx_crc(calc_crc)
Xword calc_crc;
X{ if (buf_ptr == buf_end) empty_hqxbuf();
X *buf_ptr++ = calc_crc >> 8;
X if (buf_ptr == buf_end) empty_hqxbuf();
X *buf_ptr++ = calc_crc;
X }
X
Xun_hqx(unpit_flag)
Xint unpit_flag;
X{ char type[4];
X ulong hqx_datalen, hqx_rsrclen;
X word un_pit();
X int unpitting, bytes_read;
X word calc_crc;
X extern char **hqxnames_left;
X
X hqxfile = fopen("/dev/null", "r");
X line_end = line_start + HQXLINELEN;
X buf_end = buf_start + HQXBUFLEN;
X for (;;) {
X total_bytes = 0;
X line_ptr = line_start;
X line_ptr[0] = SKIP;
X save_state = 0;
X save_run_length = 0;
X
X hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen); /* binfname */
X
X unpitting = unpit_flag && !strcmp(type, "PIT ");
X if (unpitting) {
X fclose(binfile);
X unlink(binfname);
X bytes_read = total_bytes - (buf_end - buf_ptr);
X calc_crc = un_pit();
X bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
X if (bytes_read != hqx_datalen)
X fprintf(stderr,
X "Warning - Extraneous characters ignored in %s\n", binfname);
X }
X else calc_crc = hqx_to_bin_fork(hqx_datalen);
X check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
X
X calc_crc = hqx_to_bin_fork(hqx_rsrclen);
X check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
X
X if (!unpitting) fclose(binfile);
X }
X }
X
Xre_hqx()
X{ word calc_crc;
X ulong hqx_datalen, hqx_rsrclen;
X extern char **hqxnames_left;
X extern int maxlines;
X line_end = line_start + HQXLINELEN;
X buf_end = buf_start + HQXBUFLEN;
X while (*hqxnames_left[0] != '-') {
X hqxfile = fopen("/dev/null", "w");
X line_count = maxlines;
X file_count = 0;
X line_ptr = line_start;
X *line_ptr++ = ':';
X strcpy(line_end, "\n");
X buf_ptr = buf_start;
X save_state = 0;
X save_run_length = 1;
X
X bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen); /* calculates hqxfname */
X
X calc_crc = bin_to_hqx_fork(hqx_datalen);
X write_hqx_crc(calc_crc);
X
X calc_crc = bin_to_hqx_fork(hqx_rsrclen);
X write_hqx_crc(calc_crc);
X *buf_ptr = !buf_ptr[-1]; /* To end a run and to get the last */
X buf_ptr++;
X empty_hqxbuf(); /* stray bits, temporarily add a char */
X if (save_state != 2) --line_ptr;
X if (line_ptr == line_end) {
X fputs(line_start, hqxfile);
X line_ptr = line_start;
X }
X strcpy(line_ptr, ":\n");
X fputs(line_start, hqxfile);
X fclose(hqxfile);
X }
X }
END_OF_FILE
if test 19992 -ne `wc -c <'mcvert/hqxify.c'`; then
echo shar: \"'mcvert/hqxify.c'\" unpacked with wrong size!
fi
# end of 'mcvert/hqxify.c'
fi
if test -f 'mcvert/mcvert.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mcvert/mcvert.c'\"
else
echo shar: Extracting \"'mcvert/mcvert.c'\" \(13666 characters\)
sed "s/^X//" >'mcvert/mcvert.c' <<'END_OF_FILE'
X/* mcvert.c - version 1.05 - 10 January, 1990 modified 12 March, 1990 by NP
X * Written by Doug Moore - Rice University - dougm@rice.edu - April '87
X * Sun bug fixes, assorted stuff - Jim Sasaki, March '89
X * Changed default max_line_size from 2000 to unlimited - Doug Moore, April, '89
X * Sun 3/60 doesn't like odd-sized structs. Bug fixed - Doug Moore, April, '89
X * - aided by Spencer W. Thomas
X * Didn't handle properly many hqx files combined in one file. Bug fixed -
X * Doug Moore, June, '89
X * Modified to handle MacBinaryII specification. Jim Van Verth, Sept, '89
X *
X * Fixed a bug when there are blank lines in hqx data, as happens when newline
X * get translated to CRLF and then to \n\n, common for some file transfers.
X * The last hqx line would be lost if the previous line was blank or junk.
X * Glenn Trewitt, Stanford University, 1990 (1.05)
X *
X * Mcvert would hiccup on mail header lines "X-Mailer: ELM [version 2.2 PL14]"
X * as "X-Mailer:" is a vaild hqx line! Added in code to special case this
X * line and keep scanning for the real hqx data.
X * Nigel Perry, Imperial College, 12 March 1990 [NP]
X *
X * This program may be freely distributed for non-profit purposes. It may not
X * be sold, by itself or as part of a collection of software. It may be freely
X * modified as long as no modified version is distributed. Modifications of
X * interest to all can be incorporated into the program by sending them to me
X * for distribution. Parts of the code can be used in other programs. I am not
X * responsible for any damage caused by this program. I hope you enjoy it.
X */
X
X#include "mactypes.h"
X
X#define HQX 0
X#define TEXT 1
X#define DATA 2
X#define RSRC 3
X#define HOST 4
X#define FORWARDS 0
X#define BACKWARDS 1
X
XFILE *verbose;
Xchar **hqxnames, **hqxnames_left;
Xchar *dir, *ext, *text_author;
Xchar *maxlines_str;
Xint maxlines;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{ char *flags, *getenv();
X int direction, mode, unpit_flag;
X
X argv++;
X argc--;
X verbose = stderr;
X direction = FORWARDS;
X mode = HQX;
X unpit_flag = 0;
X
X if ((text_author = getenv("MAC_EDITOR")) == NULL) text_author = "MACA";
X if ((ext = getenv("MAC_EXT")) == NULL) ext = ".bin";
X if ((dir = getenv("MAC_DLOAD_DIR")) == NULL) dir = ".";
X if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL) maxlines = 0;
X else maxlines = atoi(maxlines_str);
X
X /* Make command line arguments globally accessible */
X hqxnames = (char **) calloc(argc+1, sizeof(char *));
X hqxnames_left = hqxnames;
X while (argc--) *hqxnames_left++ = *argv++;
X *hqxnames_left = "-";
X hqxnames_left = hqxnames;
X
X while (strcmp(*hqxnames_left, "-")) {
X if (hqxnames_left[0][0] == '-') {
X flags = *hqxnames_left++;
X while (*++flags)
X switch (*flags) {
X case 'x':
X mode = HQX;
X break;
X case 'u':
X mode = TEXT;
X break;
X case 'd':
X mode = DATA;
X break;
X case 'r':
X mode = RSRC;
X break;
X case 'h':
X mode = HOST;
X break;
X case 'D':
X direction = FORWARDS;
X break;
X case 'U':
X direction = BACKWARDS;
X break;
X case 'q':
X unpit_flag = 0;
X break;
X case 'p':
X unpit_flag = 1;
X break;
X case 's':
X verbose = fopen("/dev/null", "w");
X break;
X case 'v':
X verbose = stderr;
X break;
X default:
X error(
X "Usage: mcvert [ -[r|d|u|x|h] [D|U] [p|q] [s|v] ] filename...",
X NULL);
X }
X }
X
X if (direction == BACKWARDS)
X if (mode == HQX && unpit_flag) re_hqx();/* no re_pit() yet */
X else if (mode == HQX) re_hqx();
X else re_other(mode);
X else
X if (mode == HQX) un_hqx(unpit_flag);
X else un_other(mode);
X }
X }
X
X/* An array useful for CRC calculations that use 0x1021 as the "seed" */
Xword magic[] = {
X 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
X 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
X 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
X 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
X 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
X 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
X 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
X 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
X 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
X 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
X 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
X 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
X 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
X 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
X 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
X 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
X 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
X 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
X 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
X 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
X 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
X 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
X 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
X 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
X 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
X 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
X 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
X 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
X 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
X 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
X 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
X 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
X };
X
X
X/*
X * calc_crc() --
X * Compute the MacBinary II-style CRC for the data pointed to by p, with the
X * crc seeded to seed.
X *
X * Modified by Jim Van Verth to use the magic array for efficiency.
X */
Xshort calc_mb_crc(p, len, seed)
Xunsigned char *p;
Xlong len;
Xshort seed;
X{
X short hold; /* crc computed so far */
X long i; /* index into data */
X
X extern unsigned short magic[]; /* the magic array */
X
X hold = seed; /* start with seed */
X for (i = 0; i < len; i++, p++) {
X hold ^= (*p << 8);
X hold = (hold << 8) ^ magic[(unsigned char)(hold >> 8)];
X }
X
X return (hold);
X} /* calc_crc() */
X
X
X/* Report a fatal error */
Xerror(msg, name)
Xchar msg[], name[];
X{ fprintf(stderr, msg, name);
X putc('\n', stderr);
X exit(1);
X }
X
X/* replace illegal Unix characters in file name */
X/* make sure host file name doesn't get truncated beyond recognition */
Xunixify(np)
Xregister byte *np;
X{ register ulong c;
X c = strlen(np);
X if (c > SYSNAMELEN - 4) c = SYSNAMELEN - 4;
X np[c] = '\0';
X np--;
X while (c = *++np)
X if (c <= ' ' || c == '/' || c > '~') *np = '_';
X }
X
X/* Convert Unix time (GMT since 1-1-1970) to Mac
X time (local since 1-1-1904) */
X#define MACTIMEDIFF 0x7c25b080 /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
X
Xulong time2mac(time)
Xulong time;
X{ struct timeb tp;
X ftime(&tp);
X return long2mac(time + MACTIMEDIFF
X - 60 * (tp.timezone - 60 * tp.dstflag));
X }
X
X
X/* This procedure copies the input file to the output file, basically, although
X in TEXT mode it changes LF's to CR's and in any mode it forges a Mac info
X header. Author type for TEXT mode can come from the MAC_EDITOR environ-
X ment variable if it is defined. */
X
Xun_other(mode)
Xint mode;
X{ register ulong b;
X register ulong nchars;
X char txtfname[BINNAMELEN], binfname[BINNAMELEN];
X FILE *txtfile, *binfile;
X char *suffix;
X struct stat stbuf;
X info_header info;
X int extra_chars;
X ulong dlen, rlen, mtim, ctim;
X short crc, calc_mb_crc();
X
X if (mode == DATA) suffix = ".data";
X else if (mode == RSRC) suffix = ".rsrc";
X else suffix = ".text";
X
X while (hqxnames_left[0][0] != '-') {
X
X strcpy(txtfname, *hqxnames_left++);
X if (!(txtfile = fopen(txtfname, "r"))) {
X /* Maybe we are supposed to figure out the suffix ourselves? */
X strcat(txtfname, suffix);
X if (!(txtfile = fopen(txtfname, "r")))
X error("Cannot open %s", txtfname);
X }
X
X if (stat(txtfname, &stbuf))
X error("Cannot read %s", txtfname);
X
X /* stuff header data into the info header */
X bzero(&info, sizeof(info_header));
X info.nlen = strlen(txtfname);
X info.nlen = (info.nlen > NAMELEN) ? NAMELEN : info.nlen;
X info.name[info.nlen] = '\0';
X strcpy(info.name, txtfname); /* name */
X mtim = time2mac(stbuf.st_mtime);
X ctim = time2mac(stbuf.st_ctime);
X bcopy(&mtim, info.mtim, 4);
X bcopy(&ctim, info.ctim, 4);
X info.uploadvers = '\201';
X info.readvers = '\201';
X
X if (mode == RSRC) {
X /* dlen is already zero */
X rlen = long2mac(stbuf.st_size);
X bcopy(&rlen, info.rlen, 4);
X bcopy("APPL", info.type, 4);
X bcopy("CCOM", info.auth, 4);
X }
X else {
X dlen = long2mac(stbuf.st_size);
X bcopy(&dlen, info.dlen, 4);
X /* rlen is already zero */
X bcopy("TEXT", info.type, 4);
X if (mode == DATA) bcopy("????", info.auth, 4);
X else bcopy(text_author, info.auth, 4);
X }
X
X /* calculate CRC */
X crc = calc_mb_crc(&info, 124, 0);
X info.crc[0] = (char) (crc >> 8);
X info.crc[1] = (char) crc;
X
X /* Create the .bin file and write the info to it */
X sprintf(binfname, "%s/%s%s", dir, txtfname, ext);
X if ((binfile = fopen(binfname, "w")) == NULL)
X error("Cannot open %s", binfname);
X fprintf(verbose,
X "Converting %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X txtfname, info.type, info.auth);
X fwrite(&info, sizeof(info), 1, binfile);
X
X nchars = stbuf.st_size;
X extra_chars = 127 - (nchars+127) % 128;
X if (mode == TEXT) while (nchars--) {
X b = getc(txtfile);
X if (b == LF) b = CR;
X putc(b, binfile);
X }
X else while (nchars--) putc(getc(txtfile), binfile);
X
X while (extra_chars--) putc(0, binfile);
X fclose(binfile);
X fclose(txtfile);
X }
X }
X
X/* This procedure copies the input file to the output file, basically, although
X in TEXT mode it changes CR's to LF's and in any mode it skips over the Mac
X info header. */
X
Xre_other(mode)
Xint mode;
X{ register ulong b;
X register ulong nchars;
X char txtfname[BINNAMELEN], binfname[BINNAMELEN];
X FILE *txtfile, *binfile;
X char *suffix;
X info_header info;
X
X if (mode == DATA) suffix = ".data";
X else if (mode == RSRC) suffix = ".rsrc";
X else suffix = ".text";
X
X while (hqxnames_left[0][0] != '-') {
X
X strcpy(binfname, *hqxnames_left++);
X if ((binfile = fopen(binfname, "r")) == NULL) {
X /* Maybe we are supposed to figure out the suffix ourselves? */
X strcat(binfname, ext);
X if (!(binfile = fopen(binfname, "r")))
X error("Cannot open %s", binfname);
X }
X
X /* Read the info from the .bin file, create the output file */
X fread(&info, sizeof(info), 1, binfile);
X strncpy(txtfname, info.name, info.nlen);
X txtfname[info.nlen] = '\0';
X fprintf(verbose,
X "Converting %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
X txtfname, info.type, info.auth);
X if ((txtfile = fopen(txtfname, "r")) == NULL) {
X if ((txtfile = fopen(txtfname, "w")) == NULL)
X error("Cannot open %s", txtfname);
X }
X else {
X fclose(txtfile);
X strcat(txtfname, suffix);
X if ((txtfile = fopen(txtfname, "w")) == NULL)
X error("Cannot open %s", txtfname);
X }
X
X nchars = mac2long(* (ulong *) info.dlen);
X if (mode == TEXT) while (nchars--) {
X b = getc(binfile);
X if (b == CR) b = LF;
X putc(b, txtfile);
X }
X else if (mode == DATA) while (nchars--)
X putc(getc(binfile), txtfile);
X else {
X while (nchars--) getc(binfile);
X nchars = mac2long(* (ulong *) info.rlen);
X while (nchars--) putc(getc(binfile), txtfile);
X }
X
X fclose(binfile);
X fclose(txtfile);
X }
X }
END_OF_FILE
if test 13666 -ne `wc -c <'mcvert/mcvert.c'`; then
echo shar: \"'mcvert/mcvert.c'\" unpacked with wrong size!
fi
# end of 'mcvert/mcvert.c'
fi
if test -f 'stuffit/sit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'stuffit/sit.c'\"
else
echo shar: Extracting \"'stuffit/sit.c'\" \(12417 characters\)
sed "s/^X//" >'stuffit/sit.c' <<'END_OF_FILE'
X/*
X * sit - Stuffit for UNIX
X * Puts unix data files into stuffit archive suitable for downloading
X * to a Mac. Automatically processes files output from xbin.
X *
X * Reverse engineered from unsit by Allan G. Weber, which was based on
X * macput, which was based on ...
X * Just like unsit this uses the host's version of compress to do the work.
X *
X * Examples:
X * 1) take collection of UNIX text files and make them LSC text files
X * when uncompressed on the mac:
X * sit -u -T TEXT -C KAHL file ...
X * 2) Process output from xbin:
X * xbin file1 (produces FileOne.{info,rsrc,data})
X * sit file1
X *
X * Tom Bereiter
X * ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
X *
X * This version for CAP aufs files based on info from aufs source + mcvert etc.
X * Aufs version is program is called AUFSNAME (default stuffit)
X *
X * Aug 90. Nigel Perry, np@doc.ic.ac.uk
X *
X */
X#define BSD
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include "sit.h"
X#ifdef BSD
X#include <sys/time.h>
X#include <sys/timeb.h>
X#else
X#include <time.h>
Xextern long timezone;
X#endif
X
X#ifndef min
X#define min(a,b) ((a)<(b)?(a):(b))
X#endif
X
X/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
X#define TIMEDIFF 0x7c25b080
X
X/* if called by this name, program will work on aufs files */
X#define AUFSNAME "stuffit"
X
Xstruct sitHdr sh;
Xstruct fileHdr fh;
X
Xchar buf[BUFSIZ];
Xchar *defoutfile = "archive.sit";
Xint ofd;
Xushort crc;
Xint clen;
Xint rmfiles;
Xint unixf;
Xchar *Creator, *Type;
Xint aufs;
X
Xusage() { fprintf(stderr,"Usage: sit file\n"); }
Xextern char *optarg;
Xextern int optind;
X
X/********************************************************************************/
X/* added for aufs, nicked from various places... */
X
X/* following from mcvert program */
X
X/* Useful, though not particularly Mac related, values */
Xtypedef unsigned char byte; /* one byte, obviously */
Xtypedef unsigned short word; /* must be 2 bytes */
Xtypedef unsigned long ulong; /* 4 bytes */
X
X#define NAMELEN 63 /* maximum legal Mac file name length */
X
X/* Format of a bin file:
XA bin file is composed of 128 byte blocks. The first block is the
Xinfo_header (see below). Then comes the data fork, null padded to fill the
Xlast block. Then comes the resource fork, padded to fill the last block. A
Xproposal to follow with the text of the Get Info box has not been implemented,
Xto the best of my knowledge. Version, zero1 and zero2 are what the receiving
Xprogram looks at to determine if a MacBinary transfer is being initiated.
X*/
Xtypedef struct { /* info file header (128 bytes). Unfortunately, these
X longs don't align to word boundaries */
X byte version; /* there is only a version 0 at this time */
X byte nlen; /* Length of filename. */
X byte name[NAMELEN]; /* Filename (only 1st nlen are significant)*/
X byte type[4]; /* File type. */
X byte auth[4]; /* File creator. */
X byte flags; /* file flags: LkIvBnSyBzByChIt */
X byte zero1; /* Locked, Invisible,Bundle, System */
X /* Bozo, Busy, Changed, Init */
X byte icon_vert[2]; /* Vertical icon position within window */
X byte icon_horiz[2]; /* Horizontal icon postion in window */
X byte window_id[2]; /* Window or folder ID. */
X byte protect; /* = 1 for protected file, 0 otherwise */
X byte zero2;
X byte dflen[4]; /* Data Fork length (bytes) - most sig. */
X byte rflen[4]; /* Resource Fork length byte first */
X byte cdate[4]; /* File's creation date. */
X byte mdate[4]; /* File's "last modified" date. */
X byte ilen[2]; /* GetInfo message length */
X byte flags2; /* Finder flags, bits 0-7 */
X byte unused[14];
X byte packlen[4]; /* length of total files when unpacked */
X byte headlen[2]; /* length of secondary header */
X byte uploadvers; /* Version of MacBinary II that the uploading program is written for */
X byte readvers; /* Minimum MacBinary II version needed to read this file */
X byte crc[2]; /* CRC of the previous 124 bytes */
X byte padding[2]; /* two trailing unused bytes */
X } info_header;
X
X/* end of mcvert stuff */
X/* from CAP aufs documentation */
X
X#define FINFOLEN 32
X#define MAXCLEN 199
Xtypedef struct
X{ /* byte fi_fndr[FINFOLEN]; */ /* finder info */
X /* what I think the above is... */
X ulong fndr_type, fndr_creator;
X word fndr_flags;
X ulong fndr_loc;
X word fndr_fldr;
X word fndr_icon;
X byte fndr_unused[8];
X word fndr_comment;
X ulong fndr_putaway;
X /* end of fi_fndr */
X
X word fi_attr; /* attributes */
X#define FI_MAGIC1 255
X byte fi_magic1; /* was: length of comment */
X#define FI_VERSION 0x10 /* version major 1, minor 0 */
X /* if more than 8 versions then */
X /* something wrong anyway */
X byte fi_version; /* version number */
X#define FI_MAGIC 0xda
X byte fi_magic; /* magic word check */
X byte fi_bitmap; /* bitmap of included info */
X#define FI_BM_SHORTFILENAME 0x1 /* is this included? */
X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
X byte fi_shortfilename[12+1]; /* possible short file name */
X byte fi_macfilename[32+1]; /* possible macintosh file name */
X byte fi_comln; /* comment length */
X byte fi_comnt[MAXCLEN+1]; /* comment string */
X} FileInfo;
X
XFileInfo fndr_info;
X
X/* end aufs */
X/********************************************************************************/
X
Xmain(argc,argv) char **argv; {
X int i,n;
X int total, nfiles;
X int c;
X
X rmfiles = unixf = 0;
X aufs = strcmp(argv[0], AUFSNAME) == 0;
X
X while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
X switch (c) {
X case 'r':
X rmfiles++; /* remove files when done */
X break;
X case 'o': /* specify output file */
X defoutfile = optarg;
X break;
X case 'u': /* unix file -- change '\n' to '\r' */
X unixf++;
X break;
X case 'C': /* set Mac creator */
X Creator = optarg;
X break;
X case 'T': /* set Mac file type */
X Type = optarg;
X break;
X case '?':
X usage();
X exit(1);
X }
X
X if(aufs && (strlen(defoutfile) > 32))
X { fprintf(stderr, "Output name must not exceed 32 characters: %s\n", defoutfile);
X exit(-1);
X }
X
X if(aufs)
X { /* make the .finderinfo file */
X char buf[32+12+1];
X
X strcpy(buf, ".finderinfo/");
X strcat(buf, defoutfile);
X if ((ofd=creat(buf,0644))<0)
X { perror(buf);
X exit(1);
X }
X bzero(&fndr_info, sizeof(FileInfo));
X bcopy("SIT!", &fndr_info.fndr_type, 4);
X bcopy("SIT!", &fndr_info.fndr_creator, 4);
X fndr_info.fi_magic1 = FI_MAGIC1;
X fndr_info.fi_version = FI_VERSION;
X fndr_info.fi_magic = FI_MAGIC;
X fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
X strcpy(fndr_info.fi_macfilename, defoutfile);
X write(ofd, &fndr_info, sizeof(FileInfo));
X close(ofd);
X }
X
X if ((ofd=creat(defoutfile,0644))<0) {
X perror(defoutfile);
X exit(1);
X }
X /* empty header, will seek back and fill in later */
X write(ofd,&sh,sizeof sh);
X
X for (i=optind; i<argc; i++) {
X n = put_file(argv[i]);
X if (n) {
X total += n;
X nfiles++;
X }
X }
X lseek(ofd,0,0);
X
X total += sizeof(sh);
X /* header header */
X strncpy(sh.sig1,"SIT!",4);
X cp2(nfiles,sh.numFiles);
X cp4(total,sh.arcLen);
X strncpy(sh.sig2,"rLau",4);
X sh.version = 1;
X
X write(ofd,&sh,sizeof sh);
X}
X
Xput_file(name)
Xchar name[];
X{
X struct stat st;
X struct infohdr ih;
X int i,n,fd;
X long fpos1, fpos2;
X char nbuf[256], *p;
X int fork=0;
X long tdiff;
X struct tm *tp;
X#ifdef BSD
X struct timeb tbuf;
X#else
X long bs;
X#endif
X
X fpos1 = lseek(ofd,0,1); /* remember where we are */
X /* write empty header, will seek back and fill in later */
X bzero(&fh,sizeof fh);
X write(ofd,&fh,sizeof fh);
X
X /* look for resource fork */
X if(aufs)
X { strcpy(nbuf, ".resource/");
X strcat(nbuf, name);
X }
X else
X { strcpy(nbuf,name);
X strcat(nbuf,".rsrc");
X }
X if (stat(nbuf,&st)>=0 && st.st_size) { /* resource fork exists */
X dofork(nbuf);
X cp4(st.st_size,fh.rLen);
X cp4(clen,fh.cRLen);
X cp2(crc,fh.rsrcCRC);
X fh.compRMethod = lpzComp;
X fork++;
X }
X if (rmfiles) unlink(nbuf); /* ignore errors */
X
X /* look for data fork */
X st.st_size = 0;
X strcpy(nbuf,name);
X if (stat(nbuf,&st)<0) { /* first try plain name */
X strcat(nbuf,".data");
X stat(nbuf,&st);
X }
X if (st.st_size) { /* data fork exists */
X dofork(nbuf);
X cp4(st.st_size,fh.dLen);
X cp4(clen,fh.cDLen);
X cp2(crc,fh.dataCRC);
X fh.compDMethod = lpzComp;
X fork++;
X }
X if (fork == 0) {
X fprintf(stderr,"%s: no data or resource files\n",name);
X return 0;
X }
X if (rmfiles) unlink(nbuf); /* ignore errors */
X
X /* look for .info file */
X if(aufs)
X { strcpy(nbuf, ".finderinfo/");
X strcat(nbuf, name);
X }
X else
X { strcpy(nbuf,name);
X strcat(nbuf,".info");
X }
X if((fd=open(nbuf,0))>=0
X && ((!aufs && read(fd,&ih,sizeof(ih))==sizeof(ih))
X || (aufs && read(fd,&fndr_info,sizeof(FileInfo))==sizeof(FileInfo))
X )
X )
X { if(aufs)
X { char *np;
X
X np = (char *)(fndr_info.fi_bitmap & FI_BM_MACINTOSHFILENAME ? fndr_info.fi_macfilename
X : fndr_info.fi_shortfilename);
X fh.fName[0] = (char)strlen(np);
X strncpy(fh.fName+1, np, 64);
X bcopy(&fndr_info.fndr_type, fh.fType, 4);
X bcopy(&fndr_info.fndr_creator, fh.fCreator, 4);
X bcopy(&fndr_info.fndr_flags, fh.FndrFlags, 2);
X#ifdef BSD
X ftime(&tbuf);
X tp = localtime(&tbuf.time);
X tdiff = TIMEDIFF - tbuf.timezone * 60;
X if (tp->tm_isdst)
X tdiff += 60 * 60;
X#else
X /* I hope this is right! -andy */
X time(&bs);
X tp = localtime(&bs);
X tdiff = TIMEDIFF - timezone;
X if (tp->tm_isdst)
X tdiff += 60 * 60;
X#endif
X cp4(st.st_ctime + tdiff, fh.cDate);
X cp4(st.st_mtime + tdiff, fh.mDate);
X }
X else
X { strncpy(fh.fName, ih.name,64);
X strncpy(fh.fType, ih.type, 4);
X strncpy(fh.fCreator, ih.creator, 4);
X strncpy(fh.FndrFlags, ih.flag, 2);
X strncpy(fh.cDate, ih.ctime, 4);
X strncpy(fh.mDate, ih.mtime, 4);
X }
X }
X else { /* no info file so fake it */
X strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
X /* default to LSC text file */
X strncpy(fh.fType, Type ? Type : "TEXT", 4);
X strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
X /* convert unix file time to mac time format */
X#ifdef BSD
X ftime(&tbuf);
X tp = localtime(&tbuf.time);
X tdiff = TIMEDIFF - tbuf.timezone * 60;
X if (tp->tm_isdst)
X tdiff += 60 * 60;
X#else
X /* I hope this is right! -andy */
X time(&bs);
X tp = localtime(&bs);
X tdiff = TIMEDIFF - timezone;
X if (tp->tm_isdst)
X tdiff += 60 * 60;
X#endif
X cp4(st.st_ctime + tdiff, fh.cDate);
X cp4(st.st_mtime + tdiff, fh.mDate);
X }
X close(fd);
X if (rmfiles) unlink(nbuf); /* ignore errors */
X
X crc = updcrc(0,&fh,(sizeof fh)-2);
X cp2(crc, fh.hdrCRC);
X
X fpos2 = lseek(ofd,0,1); /* remember where we are */
X lseek(ofd,fpos1,0); /* seek back over file(s) and header */
X write(ofd,&fh,sizeof fh); /* write back header */
X fpos2=lseek(ofd,fpos2,0); /* seek forward file */
X
X return (fpos2 - fpos1);
X}
X
Xdofork(name)
Xchar name[];
X{
X FILE *fs;
X int n, fd, ufd;
X char *p;
X
X if ((fd=open(name,0))<0) {
X perror(name);
X return 0;
X }
X if (unixf) /* build conversion file */
X if ((ufd=creat("sit+temp",0644))<0) {
X perror("sit+temp");
X return 0;
X }
X /* do crc of file: */
X crc = 0;
X while ((n=read(fd,buf,BUFSIZ))>0) {
X if (unixf) { /* convert '\n' to '\r' */
X for (p=buf; p<&buf[n]; p++)
X if (*p == '\n') *p = '\r';
X write(ufd,buf,n);
X }
X crc = updcrc(crc,buf,n);
X }
X close(fd);
X /*
X * open pipe to compress file
X * If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
X * with the conversion done. Otherwise, 'sit+temp' is just a link to
X * the input file.
X */
X if (unixf)
X close(ufd);
X else link(name,"sit+temp");
X fs = popen("compress -c -n -b 14 sit+temp","r");
X if (fs == NULL) {
X perror(name);
X return 0;
X }
X /* write out compressed file */
X clen = 0;
X while ((n=fread(buf,1,BUFSIZ,fs))>0) {
X write(ofd,buf,n);
X clen += n;
X }
X pclose(fs);
X unlink("sit+temp");
X}
X
Xcp2(x,dest)
Xunsigned short x;
Xchar dest[];
X{
X dest[0] = x>>8;
X dest[1] = x;
X}
X
Xcp4(x,dest)
Xunsigned long x;
Xchar dest[];
X{
X dest[0] = x>>24;
X dest[1] = x>>16;
X dest[2] = x>>8;
X dest[3] = x;
X}
END_OF_FILE
if test 12417 -ne `wc -c <'stuffit/sit.c'`; then
echo shar: \"'stuffit/sit.c'\" unpacked with wrong size!
fi
# end of 'stuffit/sit.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--- end of part 3 ---