Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site uw-beaver
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!vax135!cornell!uw-beaver!info-mac
From: info-mac@uw-beaver
Newsgroups: fa.info-mac
Subject: New VMS Versions of macput, macget, xbin
Message-ID:
Date: Fri, 5-Apr-85 20:48:02 EST
Article-I.D.: uw-beave.989
Posted: Fri Apr 5 20:48:02 1985
Date-Received: Sat, 6-Apr-85 04:14:45 EST
Sender: daemon@uw-beaver
Organization: U of Washington Computer Science
Lines: 2589
From: stew%[email protected]
$ COPY SYS$INPUT: 00README.TXT
$ DECK/DOLLAR=">> End > End > End 0) {
fcount = fgen(*++argv, mtchs, MAXFILE, "*.inf");
for (i = 0; i > End > End
#include
int
fgen(pat, resarry, maxfiles, dfltname)
char *pat, *resarry[];
int maxfiles;
char *dfltname;
{
struct dsc$descriptor_s file_spec, result, deflt;
long context;
int count, slen, status;
char result_string[256], *strchr();
file_spec.dsc$w_length = strlen(pat);
file_spec.dsc$b_dtype = DSC$K_DTYPE_T;
file_spec.dsc$b_class = DSC$K_CLASS_S;
file_spec.dsc$a_pointer = pat;
result.dsc$w_length = sizeof result_string;
result.dsc$b_dtype = DSC$K_DTYPE_T;
result.dsc$b_class = DSC$K_CLASS_S;
result.dsc$a_pointer = result_string;
deflt.dsc$w_length = strlen(dfltname);
deflt.dsc$b_dtype = DSC$K_DTYPE_T;
deflt.dsc$b_class = DSC$K_CLASS_S;
deflt.dsc$a_pointer = dfltname;
count = 0;
context = 0;
while (count > End > End 0) {
fcount = fgen(*++argv, mtchs, MAXFILE, "*.inf");
for (i = 0; i > End > End 127)
{
*outptr++ = '&';
c &= 127;
}
if (c > End > End NAMEBYTES) n = NAMEBYTES;
strncpy(mh.m_name, name, n);
mh.m_name[n] = '\0';
}
else {
n = buf[H_NLENOFF] & BYTEMASK;
if (n > NAMEBYTES) n = NAMEBYTES;
strncpy(mh.m_name, buf + H_NAMEOFF, n);
mh.m_name[n] = '\0';
}
for (np = mh.m_name; *np; np++)
if (*np == ' ') *np = '_';
if (mode == FULL) {
make_name(files.f_info, "info", mh.m_name);
rename(tmpname, files.f_info);
tmpname[0] = '\0';
make_name(files.f_data, "data", mh.m_name);
make_name(files.f_rsrc, "rsrc", mh.m_name);
}
else {
delete(tmpname);
tmpname[0] = '\0';
switch (mode) {
case RSRC:
strcpy(files.f_data, "_NL:");
make_name(files.f_rsrc, "rsrc", mh.m_name);
break;
case DATA:
make_name(files.f_data, "data", mh.m_name);
strcpy(files.f_rsrc, "_NL:");
break;
case TEXT:
make_name(files.f_data, "text", mh.m_name);
strcpy(files.f_rsrc, "_NL:");
break;
}
}
strncpy(mh.m_type, buf + H_TYPEOFF, 4);
strncpy(mh.m_author, buf + H_AUTHOFF, 4);
if (pre_beta) {
mh.m_datalen = get4(buf + H_OLD_DLENOFF);
mh.m_rsrclen = get4(buf + H_OLD_RLENOFF);
}
else {
mh.m_datalen = get4(buf + H_DLENOFF);
mh.m_rsrclen = get4(buf + H_RLENOFF);
mh.m_createtime = get4(buf + H_CTIMOFF);
mh.m_modifytime = get4(buf + H_MTIMOFF);
}
}
recv_file(fname, bytes, more)
char *fname;
long bytes;
int more;
{
register int status, n;
FILE *outf;
int naks = 0;
lastack = 0;
outf = fopen(fname, "w");
if (outf == NULL) {
perror(fname);
cleanup(-1);
}
for (;;) {
status = rec_read(buf, DATABYTES);
switch (status) {
case EOT:
if (!pre_beta)
tputc(ACK);
if (more)
tputc(NAK);
fclose(outf);
return;
case ACK:
tputc(ACK);
naks = 0;
n = (bytes > DATABYTES) ? DATABYTES : bytes;
bytes -= n;
fwrite(buf, n, 1, outf);
break;
case DUP:
tputc(ACK);
naks = 0;
break;
case NAK:
purge(CHRTIMO);
if (naks++ > End > End > End > End 80 is the FInfo structure */
#define H_TYPEOFF 65
#define H_AUTHOFF 69
#define H_FFLGOFF 73
#define H_LOCOFF 75
#define H_FOLDOFF 79
#define H_LOCKOFF 81
#define H_DLENOFF 83
#define H_RLENOFF 87
#define H_CTIMOFF 91
#define H_MTIMOFF 95
#define H_OLD_DLENOFF 81
#define H_OLD_RLENOFF 85
#define TEXT 0
#define DATA 1
#define RSRC 2
#define FULL 3
/* In VMS version 4, we will be able to do something better. */
#ifdef vax11c
# define rename(old, new)
# define unlink(file) delete(file)
#else
# ifdef NO_RENAME
# define rename(old, new) link(old, new); unlink(old)
# endif
#endif
struct macheader {
char m_name[NAMEBYTES+1];
char m_type[4];
char m_author[4];
long m_datalen;
long m_rsrclen;
long m_createtime;
long m_modifytime;
};
struct filenames {
char f_info[256];
char f_data[256];
char f_rsrc[256];
};
>> End > End 1) {
ac--; av++;
n = strlen(av[0]);
if (n > NAMEBYTES) n = NAMEBYTES;
strncpy(mh.m_name, av[0], n);
mh.m_name[n] = '\0';
break;
}
else goto bad_usage;
case 't':
if (ac > 1) {
ac--; av++;
strncpy(mh.m_type, av[0], 4);
break;
}
else goto bad_usage;
case 'a':
if (ac > 1) {
ac--; av++;
strncpy(mh.m_author, av[0], 4);
break;
}
else goto bad_usage;
case 'o':
pre_beta++;
break;
default:
bad_usage:
fprintf(stderr, usage);
exit(1);
}
}
else {
filename = av[0];
}
ac--; av++;
}
setup_tty();
find_files(filename, mode);
if (mode != FULL)
forge_info();
if (send_sync() == ACK) {
txtmode = 0;
send_file(files.f_info, 1);
if (mode != FULL)
delete(files.f_info);
if (mode == TEXT) txtmode++;
send_file(files.f_data, 1);
txtmode = 0;
send_file(files.f_rsrc, 0);
}
reset_tty();
}
find_files(filename, mode)
char *filename;
{
int n, tdiff, fd, status;
struct tm *tp;
struct timeb tbuf;
time_t mtime;
sprintf(files.f_data, "%s.dat", filename);
sprintf(files.f_rsrc, "%s.rsr", filename);
if (mode == FULL) {
sprintf(files.f_info, "%s.inf", filename);
if ((fd = open(files.f_info, 0)) tm_isdst)
tdiff += 60 * 60;
mh.m_createtime = mtime + tdiff;
mh.m_modifytime = mtime + tdiff;
}
if (mh.m_name[0] == '\0') {
n = strlen(filename);
if (n > NAMEBYTES) n = NAMEBYTES;
strncpy(mh.m_name, filename, n);
mh.m_name[n] = '\0';
}
}
forge_info()
{
int n;
char *np;
FILE *fp;
for (np = mh.m_name; *np; np++)
if (*np == '_') *np = ' ';
buf[H_NLENOFF] = n = np - mh.m_name;
strncpy(buf + H_NAMEOFF, mh.m_name, n);
strncpy(buf + H_TYPEOFF, mh.m_type, 4);
strncpy(buf + H_AUTHOFF, mh.m_author, 4);
if (pre_beta) {
put4(buf + H_OLD_DLENOFF, mh.m_datalen);
put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
}
else {
put4(buf + H_DLENOFF, mh.m_datalen);
put4(buf + H_RLENOFF, mh.m_rsrclen);
put4(buf + H_CTIMOFF, mh.m_createtime);
put4(buf + H_MTIMOFF, mh.m_modifytime);
}
fp = fopen(files.f_info, "w");
if (fp == NULL) {
perror("temp file");
cleanup(-1);
}
fwrite(buf, 1, DATABYTES, fp);
fclose(fp);
}
send_sync()
{
int c, i;
for (i = 0; i 0) {
for (i = 0; i > 24) & BYTEMASK;
value > End > End > End > End > End > End > End > End
MSG2: .ASCIZ /TEST_INPUT: INCNT = %d, CHAR = %d/
MSG3: .ASCIZ /TEST_INPUT: SYSBUF = %d, CHAR = %d/
MSG4: .ASCIZ /TIMED_IN: CHAR = %d/
MSG5: .ASCIZ /OUT: CHAR = %d/
MSG6: .ASCIZ /PURGE/
MSG7: .ASCIZ /FLUSH/
.PSECT DBG_FILE, LONG, WRT, NOEXE, OVR, PIC, GBL, SHR
DBG_FILE: .BLKL 1
.ENDC
.PSECT $CODE NOWRT, EXE, SHR, CON, PIC
.ENTRY IN, ^M
; SUBROUTINE IN(CHAR)
;++
; IN reads a single character from the terminal and returns it in CHAR.
;--
BSBB TEST_INPUT
TSTL R0
BLSS 1$
MOVL R0, @4(AP)
RET
1$: CALLS #0, FLUSH
$QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_NOFILTR, -
P1=@4(AP), -
P2=#1, -
P4=#TRMMSK
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
MOVZBL @4(AP), -(SP)
PUSHAB MSG1
PUSHL DBG_FILE
CALLS #3, FPRINTF
80$:
.ENDC
RET
; The local subroutine, TEST_INPUT, checks to see if any input has
; already arrived, either in the local input buffer, or in the system
; typeahead buffer. It returns the resulting character in R0. If there
; is no character ready, it returns -1.
TEST_INPUT:
TSTW INCNT ; Anything already read in?
BEQL 1$ ; If not, go check system typeahead buffer
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
MOVZBL @INPTR, -(SP)
CVTWL INCNT, -(SP)
PUSHAB MSG2
PUSHL DBG_FILE
CALLS #4, FPRINTF
80$:
.ENDC
MOVL INPTR, R0 ; Get address of this character
INCL INPTR ; Point to next
DECW INCNT ; Update count of remaining chars
MOVZBL (R0)+, R0 ; Return this character
RSB
1$: TSTW TTYCHN ; Have we initialized?
BNEQ 2$ ; If so, skip GETTRM call
BSBW GETTRM ; Get the tty channel, etc.
2$: ; Snarf up anything in the system input buffer
$QIOW_S CHAN=TTYCHN, -
IOSB=TTIOSB, -
FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_TIMED, -
P1=INBUF, -
P2=#INBUF_SIZE, -
P3=#0, -
P4=#TRMMSK
TSTW TTIOSB+2 ; Were there any?
BEQL 3$ ; If not, return with flags set
MOVAL INBUF+1, INPTR ; Yes, reset pointer to next character
SUBW3 #1, TTIOSB+2, INCNT ; Save the count of characters remaining
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 81$
MOVZBL INBUF, -(SP)
CVTWL TTIOSB+2, -(SP)
PUSHAB MSG3
PUSHL DBG_FILE
CALLS #4, FPRINTF
81$:
.ENDC
MOVZBL INBUF, R0 ; Return the first character
RSB
3$: MCOML #0, R0
RSB
.ENTRY TIMED_IN, ^M
; SUBROUTINE TIMED_IN(CHAR, TIME)
;++
; TIMED_IN reads a single character from the grpahics terminal.
; If no such character is available within TIME seconds, -1 is
; returned.
;--
BSBW TEST_INPUT
TSTL R0
BLSS 2$
MOVL R0, @4(AP)
RET
2$: TSTL @8(AP)
BEQL 3$
CALLS #0, FLUSH
CLRL @4(AP)
$QIOW_S CHAN=TTYCHN, -
IOSB=TTIOSB, -
FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_TIMED, -
P1=@4(AP), -
P2=#1, -
P3=@8(AP), -
P4=#TRMMSK
CMPW TTIOSB, #SS$_TIMEOUT
BNEQ 1$
3$: MCOML #0, @4(AP)
1$:
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
PUSHL @4(AP)
PUSHAB MSG4
PUSHL DBG_FILE
CALLS #3, FPRINTF
80$:
.ENDC
RET
.ENTRY PURGE, ^M
; SUBROUTINE PURGE
;++
; PURGE clears the input buffer of the graphics terminal.
;--
TSTW TTYCHN
BNEQ 1$
BSBW GETTRM
1$: CLRW INCNT
$QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_TIMED!IO$M_PURGE, -
P1=BUFF, -
P2=#1, -
P3=#0
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
PUSHAB MSG6
PUSHL DBG_FILE
CALLS #2, FPRINTF
80$:
.ENDC
RET
.ENTRY OUT,0
; SUBROUTINE OUT(CHAR)
;++
; OUT writes a single character, CHAR, to the terminal.
; Actually, the characters are buffered locally, and then sent
; out by a call to FLUSH, IN or GETLN. OUT is used for character
; output in graphics mode.
;--
MOVB @4(AP), @OUTPTR
INCL OUTPTR
MOVAL OUTBUF+OUTBUF_SIZE, R0
CMPL OUTPTR, R0
BNEQ 1$
CALLS #0, FLUSH
1$:
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
MOVZBL @4(AP), -(SP)
PUSHAB MSG5
PUSHL DBG_FILE
CALLS #3, FPRINTF
80$:
.ENDC
RET
.ENTRY FLUSH,^M
; SUBROUTINE FLUSH
;++
; FLUSH writes out the characters accumulated with OUT to the terminal.
;--
MOVAL OUTBUF, R0
SUBL3 R0, OUTPTR, R2
BEQL 1$
TSTW TTYCHN
BNEQ 2$
BSBW GETTRM
2$: $QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_WRITEVBLK!IO$M_NOFORMAT, -
P1=OUTBUF, -
P2=R2
MOVAL OUTBUF, OUTPTR
1$:
.IF NE,DEBUGGING
TSTL DBG_FILE
BEQL 80$
PUSHAB MSG7
PUSHL DBG_FILE
CALLS #2, FPRINTF
80$:
.ENDC
RET
GETTRM:
PUSHL #^A/TT/
PUSHL SP
PUSHL #2
MOVL SP, R2
$ASSIGN_S DEVNAM=(R2), CHAN=TTYCHN
BLBS R0, 1$
$EXIT_S R0
1$: ADDL #12, SP
MOVAL OUTBUF, OUTPTR
CALLS #0, PURGE
RSB
.ENTRY RAW_MODE, ^M
; SUBROUTINE RAW_MODE
;++
; Puts the terminal in passall mode.
;--
TSTW TTYCHN
BNEQ 1$
BSBW GETTRM
1$: $QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_SENSEMODE, -
P1=TTMODE
BISL3 #TT$M_EIGHTBIT!TT$M_PASSALL, TTMODE+4, -(SP)
MOVL TTMODE, -(SP)
MOVL SP, R2
$QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_SETMODE, -
P1=(R2)
RET
.ENTRY RESET_TTY, 0
; SUBROUTINE RESET_TTY
;++
; Resets the terminal to the modes in effect before the call to RAW_MODE.
;--
$QIOW_S CHAN=TTYCHN, -
FUNC=#IO$_SETMODE, -
P1=TTMODE
RET
.END
>> End > End
#ifdef vax11c
#define FNAMELEN 256
#define search_last strrchr
#else
#include
#include
#include
#ifdef MAXNAMLEN /* 4.2 BSD */
#define FNAMELEN MAXNAMLEN
#else
#define FNAMELEN DIRSIZ
#endif
#ifdef BSD
#include
#include
#define search_last rindex
#else
#include
extern long timezone;
#define search_last strrchr
#endif
#endif
extern char *search_last();
/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
#define TIMEDIFF 0x7c25b080
#define DATABYTES 128
#define BYTEMASK 0xff
#define BYTEBIT 0x100
#define WORDMASK 0xffff
#define WORDBIT 0x10000
#define NAMEBYTES 63
#define H_NLENOFF 1
#define H_NAMEOFF 2
/* 65 80 is the FInfo structure */
#define H_TYPEOFF 65
#define H_AUTHOFF 69
#define H_FLAGOFF 73
#define H_LOCKOFF 81
#define H_DLENOFF 83
#define H_RLENOFF 87
#define H_CTIMOFF 91
#define H_MTIMOFF 95
#define H_OLD_DLENOFF 81
#define H_OLD_RLENOFF 85
#define F_BUNDLE 0x2000
#define F_LOCKED 0x8000
struct macheader {
char m_name[NAMEBYTES+1];
char m_type[4];
char m_author[4];
short m_flags;
long m_datalen;
long m_rsrclen;
long m_createtime;
long m_modifytime;
} mh;
struct filenames {
char f_info[256];
char f_data[256];
char f_rsrc[256];
} files;
int pre_beta; /* options */
int listmode;
int verbose;
int compressed; /* state variables */
int qformat;
FILE *ifp;
/*
* xbin -- unpack BinHex format file into suitable
* format for downloading with macput
* Dave Johnson, Brown University Computer Science
*
* VMS support by Stew Rubenstein, Harvard University Chemical Labs
*
* checksum code by Darin Adler, TMQ Software
*
* (c) 1984 Brown University
* may be used but not sold without permission
*
* created ddj 12/16/84
* revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
* revised ddj 03/11/85 -- strip LOCKED bit from m_flags
* revised ahm 03/12/85 -- System V compatibility
* revised dba 03/16/85 -- 4.0 EOF fixed, 4.0 checksum added
* revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
* revised ddj 03/24/85 -- check for filename truncation, allow multiple files
* revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
* revised sdr 03/29/85 -- vms version under #ifdef vax11c switches
*/
char usage[] = "usage: \"xbin [-v] [-l] [-o] [-n name] [-] filename\"\n";
main(ac, av)
char **av;
{
char *filename, *macname;
filename = ""; macname = "";
ac--; av++;
while (ac) {
if (av[0][0] == '-') {
switch (av[0][1]) {
case '\0':
filename = "-";
break;
case 'v':
verbose++;
break;
case 'l':
listmode++;
break;
case 'o':
pre_beta++;
break;
case 'n':
if (ac > 1) {
ac--; av++;
macname = av[0];
filename = "";
break;
}
else
goto bad_usage;
default:
goto bad_usage;
}
}
else
filename = av[0];
if (filename[0] != '\0') {
setup_files(filename, macname);
if (listmode) {
print_header();
}
else {
process_forks();
/* now that we know the size of the forks */
forge_info();
}
if (ifp != stdin)
fclose(ifp);
macname = "";
ifp = NULL; /* reset state */
qformat = 0;
compressed = 0;
}
ac--; av++;
}
if (*filename == '\0') {
bad_usage:
fprintf(stderr, usage);
exit(1);
}
}
static char *extensions[] = {
".hqx",
".hcx",
".hex",
"",
NULL
};
setup_files(filename, macname)
char *filename; /* input file name -- extension optional */
char *macname; /* name to use on the mac side of things */
{
char namebuf[256], *np;
char **ep;
int n;
#ifndef vax11c
struct stat stbuf;
#endif
long curtime;
if (filename[0] == '-') {
ifp = stdin;
filename = "stdin";
}
else {
/* find input file and open it */
for (ep = extensions; *ep != NULL; ep++) {
sprintf(namebuf, "%s%s", filename, *ep);
#ifdef vax11c
if ((n = open(namebuf, 0)) >= 0) {
close(n);
break;
}
#else
if (stat(namebuf, &stbuf) == 0)
break;
#endif
}
if (*ep == NULL) {
perror(namebuf);
exit(-1);
}
ifp = fopen(namebuf, "r");
if (ifp == NULL) {
perror(namebuf);
exit(-1);
}
}
if (ifp == stdin) {
curtime = time(0);
mh.m_createtime = curtime;
}
else {
#ifdef vax11c
revdate(namebuf, "", &mh.m_createtime);
#else
mh.m_createtime = stbuf.st_mtime;
#endif
}
mh.m_modifytime = mh.m_createtime;
if (listmode || verbose) {
fprintf(stderr, "%s %s%s",
listmode ? "\nListing" : "Converting",
namebuf, listmode ? ":\n" : " ");
}
qformat = find_header(); /* eat mailer header &cetera, intuit format */
if (qformat)
do_q_header(macname);
else
do_o_header(macname, filename);
/* make sure host file name doesn't get truncated beyond recognition */
n = strlen(mh.m_name);
if (n > FNAMELEN - 2)
n = FNAMELEN - 2;
strncpy(namebuf, mh.m_name, n);
namebuf[n] = '\0';
/* get rid of troublesome characters */
for (np = namebuf; *np; np++)
if (*np == ' ' || *np == '/')
*np = '_';
#ifdef vax11c
sprintf(files.f_data, "%s.dat", namebuf);
sprintf(files.f_rsrc, "%s.rsr", namebuf);
sprintf(files.f_info, "%s.inf", namebuf);
if (verbose)
fprintf(stderr, "==> %s.{inf,dat,rsr}\n", namebuf);
#else
sprintf(files.f_data, "%s.data", namebuf);
sprintf(files.f_rsrc, "%s.rsrc", namebuf);
sprintf(files.f_info, "%s.info", namebuf);
if (verbose)
fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf);
#endif
}
/* print out header information in human-readable format */
print_header()
{
char *ctime();
printf("macname: %s\n", mh.m_name);
printf("filetype: %.4s, ", mh.m_type);
printf("author: %.4s, ", mh.m_author);
printf("flags: 0x%x\n", mh.m_flags);
if (qformat) {
printf("data length: %d, ", mh.m_datalen);
printf("rsrc length: %d\n", mh.m_rsrclen);
}
if (!pre_beta) {
printf("create time: %s", ctime(&mh.m_createtime));
}
}
process_forks()
{
if (qformat) {
/* read data and resource forks of .hqx file */
do_q_fork(files.f_data, mh.m_datalen);
do_q_fork(files.f_rsrc, mh.m_rsrclen);
}
else
do_o_forks();
}
/* write out .info file from information in the mh structure */
forge_info()
{
static char buf[DATABYTES];
char *np;
FILE *fp;
int n, tdiff;
#ifndef vax11c
struct tm *tp;
#ifdef BSD
struct timeb tbuf;
#else
long bs;
#endif
#endif
for (np = mh.m_name; *np; np++)
if (*np == '_') *np = ' ';
buf[H_NLENOFF] = n = np - mh.m_name;
strncpy(buf + H_NAMEOFF, mh.m_name, n);
strncpy(buf + H_TYPEOFF, mh.m_type, 4);
strncpy(buf + H_AUTHOFF, mh.m_author, 4);
put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED);
if (pre_beta) {
put4(buf + H_OLD_DLENOFF, mh.m_datalen);
put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
}
else {
put4(buf + H_DLENOFF, mh.m_datalen);
put4(buf + H_RLENOFF, mh.m_rsrclen);
/* convert unix file time to mac time format */
#ifdef vax11c
tdiff = TIMEDIFF;
#else
#ifdef BSD
ftime(&tbuf);
tp = localtime(&tbuf.time);
tdiff = TIMEDIFF - tbuf.timezone * 60;
if (tp->tm_isdst)
tdiff += 60 * 60;
#else
/* I hope this is right! -andy */
time(&bs);
tp = localtime(&bs);
tdiff = TIMEDIFF - timezone;
if (tp->tm_isdst)
tdiff += 60 * 60;
#endif
#endif
put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
}
fp = fopen(files.f_info, "w");
if (fp == NULL) {
perror("info file");
exit(-1);
}
fwrite(buf, 1, DATABYTES, fp);
fclose(fp);
}
/* eat characters until header detected, return which format */
find_header()
{
int c, n, at_bol;
char ibuf[BUFSIZ];
/* look for "(This file ...)" line */
while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
if (strncmp(ibuf, "(This file", 10) == 0)
break;
}
at_bol = 1;
while ((c = getc(ifp)) != EOF) {
switch (c) {
case '\n':
case '\r':
at_bol = 1;
break;
case ':':
if (at_bol) /* q format */
return 1;
break;
case '#':
if (at_bol) { /* old format */
ungetc(c, ifp);
return 0;
}
break;
default:
at_bol = 0;
break;
}
}
fprintf(stderr, "unexpected EOF\n");
exit(2);
}
static unsigned int crc;
short get2q();
long get4q();
/* read header of .hqx file */
do_q_header(macname)
char *macname;
{
char namebuf[256]; /* big enough for both att & bsd */
int n;
int calc_crc, file_crc;
crc = 0; /* compute a crc for the header */
q_init(); /* reset static variables */
n = getq(); /* namelength */
n++; /* must read trailing null also */
getqbuf(namebuf, n); /* read name */
if (macname[0] == '\0')
macname = namebuf;
n = strlen(macname);
if (n > NAMEBYTES)
n = NAMEBYTES;
strncpy(mh.m_name, macname, n);
mh.m_name[n] = '\0';
getqbuf(mh.m_type, 4);
getqbuf(mh.m_author, 4);
mh.m_flags = get2q();
mh.m_datalen = get4q();
mh.m_rsrclen = get4q();
comp_q_crc(0);
comp_q_crc(0);
calc_crc = crc;
file_crc = get2q();
verify_crc(calc_crc, file_crc);
}
do_q_fork(fname, len)
char *fname;
register int len;
{
FILE *outf;
register int c, i;
int calc_crc, file_crc;
outf = fopen(fname, "w");
if (outf == NULL) {
perror(fname);
exit(-1);
}
crc = 0; /* compute a crc for a fork */
if (len)
for (i = 0; i > 4);
obuf[1] = (ibuf[1] > 2);
obuf[2] = (ibuf[2] = &obuf[eof]))
return EOF;
c = *op++;
if (op >= oend)
op = obuf;
return (c & BYTEMASK);
}
char tr[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
/* q format -- decode one byte into 6 bit binary */
get6bits()
{
register int c;
register char *where;
while (1) {
c = getc(ifp);
switch (c) {
case '\n':
case '\r':
continue;
case ':':
case EOF:
return EOF;
default:
where = tr;
while (*where != '\0' && *where != c)
where++;
if (*where == c)
return (where - tr);
else {
fprintf(stderr, "bad char\n");
return EOF;
}
}
}
}
#define CRCCONSTANT 0x1021
comp_q_crc(c)
register unsigned int c;
{
register int i;
register unsigned int temp = crc;
for (i=0; i> 8);
c &= BYTEMASK;
}
crc = temp;
}
/* old format -- process .hex and .hcx files */
do_o_header(macname, filename)
char *macname, *filename;
{
char namebuf[256]; /* big enough for both att & bsd */
char ibuf[BUFSIZ];
int n;
/* set up name for output files */
if (macname[0] == '\0') {
strcpy(namebuf, filename);
/* strip directories */
macname = search_last(namebuf, '/');
if (macname == NULL)
macname = namebuf;
else
macname++;
/* strip extension */
n = strlen(macname);
if (n > 4) {
n -= 4;
if (macname[n] == '.' && macname[n+1] == 'h'
&& macname[n+3] == 'x')
macname[n] = '\0';
}
}
n = strlen(macname);
if (n > NAMEBYTES)
n = NAMEBYTES;
strncpy(mh.m_name, macname, n);
mh.m_name[n] = '\0';
/* read "#TYPEAUTH$flag" line */
if (fgets(ibuf, BUFSIZ, ifp) == NULL) {
fprintf(stderr, "unexpected EOF\n");
exit(2);
}
n = strlen(ibuf);
if (n >= 7 && ibuf[0] == '#' && ibuf[n-6] == '$') {
if (n >= 11)
strncpy(mh.m_type, &ibuf[1], 4);
if (n >= 15)
strncpy(mh.m_author, &ibuf[5], 4);
sscanf(&ibuf[n-5], "%4hx", &mh.m_flags);
}
}
do_o_forks()
{
char ibuf[BUFSIZ];
int forks = 0, found_crc = 0;
int calc_crc, file_crc;
int n;
crc = 0; /* calculate a crc for both forks */
/* create empty files ahead of time */
close(creat(files.f_data, 0666));
close(creat(files.f_rsrc, 0666));
while (!found_crc && fgets(ibuf, BUFSIZ, ifp) != NULL) {
if (forks == 0 && strncmp(ibuf, "***COMPRESSED", 13) == 0) {
compressed++;
continue;
}
if (strncmp(ibuf, "***DATA", 7) == 0) {
mh.m_datalen = make_file(files.f_data, compressed);
forks++;
continue;
}
if (strncmp(ibuf, "***RESOURCE", 11) == 0) {
mh.m_rsrclen = make_file(files.f_rsrc, compressed);
forks++;
continue;
}
if (compressed && strncmp(ibuf, "***CRC:", 7) == 0) {
found_crc++;
calc_crc = crc;
sscanf(&ibuf[7], "%x", &file_crc);
break;
}
if (!compressed && strncmp(ibuf, "***CHECKSUM:", 12) == 0) {
found_crc++;
calc_crc = crc & BYTEMASK;
sscanf(&ibuf[12], "%x", &file_crc);
file_crc &= BYTEMASK;
break;
}
}
if (found_crc)
verify_crc(calc_crc, file_crc);
else {
fprintf(stderr, "missing CRC\n");
exit(3);
}
}
make_file(fname, compressed)
char *fname;
int compressed;
{
register int n;
char ibuf[BUFSIZ];
FILE *outf;
int nbytes = 0;
outf = fopen(fname, "w");
if (outf == NULL) {
perror(fname);
exit(-1);
}
while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
if (strncmp(ibuf, "***END", 6) == 0)
break;
if (compressed)
nbytes += comp_to_bin(ibuf, outf);
else
nbytes += hex_to_bin(ibuf, outf);
}
fclose(outf);
return nbytes;
}
comp_c_crc(c)
unsigned char c;
{
crc = (crc + c) & WORDMASK;
crc = ((crc > 13);
}
comp_e_crc(c)
unsigned char c;
{
crc += c;
}
#define SIXB(c) (((c)-0x20) & 0x3f)
comp_to_bin(ibuf, outf)
char ibuf[];
FILE *outf;
{
char obuf[BUFSIZ];
register char *ip = ibuf;
register char *op = obuf;
register int n, outcount;
int numread, incount;
numread = strlen(ibuf);
ip[numread-1] = ' '; /* zap out the newline */
outcount = (SIXB(ip[0]) > 4);
incount = ((outcount / 3) + 1) * 4;
for (n = numread; n > 4;
*op++ = SIXB(ip[1]) > 2;
*op++ = SIXB(ip[2]) > 8) & BYTEMASK;
*bp++ = value & BYTEMASK;
}
put4(bp, value)
char *bp;
long value;
{
register int i, c;
for (i = 0; i > 24) & BYTEMASK;
value > End > End > End > End > End <<
