home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
xbin_25.shr
/
xbin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-20
|
20KB
|
998 lines
#ifndef lint
static char version[] = "@(#)xbin.c Version 2.5, April '88 (moriarty@tc.fluke.COM)";
#endif lint
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#ifdef MAXNAMLEN /* 4.2 BSD */
#define FNAMELEN MAXNAMLEN
#else
#define FNAMELEN DIRSIZ
#endif
#ifdef BSD
#include <sys/time.h>
#include <sys/timeb.h>
#define search_last rindex
extern char *rindex();
#else
#include <time.h>
extern long timezone;
#define search_last strrchr
extern char *strrchr();
#endif
/* 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 no_crc;
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
*
* (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 -- (Darin Adler, TMQ Software) 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 jcb 03/30/85 -- (Jim Budler, amdcad!jimb), revised for compatibility
* with 16-bit int machines
* revised dl 06/16/85 -- (Dan LaLiberte, liberte@uiucdcs) character
* translation speedup
* revised ddj 09/30/85 -- fixed problem with run of RUNCHAR
* revised gvr 11/15/86 -- speed-up: rewrote .hqx decoding (mcvax!guido)
* revised jwm 4/26/88 -- now recognizes "(Convert with" as a starting line
* -- the widely-used Stuffit uses this as a header
*/
char usage[] = "usage: \"xbin [-v] [-l] [-o] [-f] [-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 'f':
no_crc++;
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];
char **ep;
struct stat stbuf;
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);
if (stat(namebuf, &stbuf) == 0)
break;
}
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;
mh.m_modifytime = curtime;
}
else {
mh.m_createtime = stbuf.st_mtime;
mh.m_modifytime = stbuf.st_mtime;
}
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_everything(macname, namebuf);
else {
do_o_header(macname, filename);
name_stuffing(macname);
}
}
name_stuffing(namebuf)
char *namebuf;
{
int n;
char *np;
/* 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 */
/* I replaced the following code to avoid a core-dump when the file to */
/* be created by xbin contains characters which could not be handled */
/* Werner Uhrig, June 6, 1988. <werner@rascal.ics.utexas.edu> */
/* I give credit to Earle Horton, who posted the C-code fraction */
/* I used as replacement. */
/* for (np = namebuf; *np; np++)
if (*np == ' ' || *np == '/')
*np = '_';
*/
for (np = namebuf; *np; np++){
if (*np == ' ' || *np == '/' || *np == '!' ||
*np == '(' || *np == ')' || *np == '[' || *np == ']'
|| *np == '*' || *np == '<' || *np == '>' ||
*np == '?' || *np == '\'' || *np == '"' || *np == '$')
*np = '_';
*np &= 0x7f;
}
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);
}
/* 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: %ld, ", mh.m_datalen);
printf("rsrc length: %ld\n", mh.m_rsrclen);
}
if (!pre_beta) {
printf("create time: %s", ctime(&mh.m_createtime));
}
}
process_forks()
{
if (qformat) {
/* Forks have already been read. */
}
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;
long tdiff;
struct tm *tp;
#ifdef BSD
struct timeb tbuf;
#else
long bs;
#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 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
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, at_bol;
char ibuf[BUFSIZ];
/* look for "(This file ...)" of "(Convert with...)"line */
while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
if ((strncmp(ibuf, "(This file", 10) == 0) ||
(strncmp(ibuf, "(Convert with", 13) == 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);
/* NOTREACHED */
}
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;
unsigned 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);
}
/* verify_crc(); -- check if crc's check out */
verify_crc(calc_crc, file_crc)
unsigned int calc_crc, file_crc;
{
calc_crc &= WORDMASK;
file_crc &= WORDMASK;
if (calc_crc != file_crc) {
fprintf(stderr, "CRC error\n---------\n");
fprintf(stderr, "CRC in file:\t0x%x\n", file_crc);
fprintf(stderr, "calculated CRC:\t0x%x\n", calc_crc);
exit(3);
}
}
/* New stuff which hopes to improve the speed. */
#define RUNCHAR 0x90
#define DONE 0x7F
#define SKIP 0x7E
#define FAIL 0x7D
char lookup[256] = {
/* 0*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
/* \n \r */
FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
/* 2*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
/* 4*/ FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
/* 6*/ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
/* : */
0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
/* 8*/ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
/*10*/ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
/*12*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
/*14*/ 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
/*16*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
};
char *g_macname;
char *g_namebuf;
int stop= 0;
get_header()
{
do_q_header(g_macname);
name_stuffing(g_namebuf);
if (listmode) {
stop= 1;
return;
}
}
unsigned char obuf[BUFSIZ];
unsigned char *op= obuf;
unsigned char *oq;
#define S_HEADER 0
#define S_DATAOPEN 1
#define S_DATAWRITE 2
#define S_DATAC1 3
#define S_DATAC2 4
#define S_RSRCOPEN 5
#define S_RSRCWRITE 6
#define S_RSRCC1 7
#define S_RSRCC2 8
#define S_EXCESS 9
int ostate= S_HEADER;
unsigned int calc_crc;
unsigned int file_crc;
long todo;
FILE *ofp;
oflush()
{
int n;
oq= obuf;
while (oq < op && !stop) {
switch (ostate) {
case S_HEADER:
get_header();
++ostate;
break;
case S_DATAOPEN:
ofp= fopen(files.f_data, "w");
todo= mh.m_datalen;
crc= 0;
++ostate;
break;
case S_RSRCOPEN:
ofp= fopen(files.f_rsrc, "w");
todo= mh.m_rsrclen;
crc= 0;
++ostate;
break;
case S_DATAWRITE:
case S_RSRCWRITE:
n= op-oq;
if (n > todo)
n= todo;
if (fwrite(oq, 1, n, ofp) != n) {
perror("fwrite");
exit(1);
}
if (!no_crc) {
register unsigned char *end= oq+n;
register unsigned char *p= oq;
while (p < end)
comp_q_crc(*p++);
}
oq += n;
todo -= n;
if (todo <= 0) {
fclose(ofp);
++ostate;
}
break;
case S_DATAC1:
case S_RSRCC1:
comp_q_crc(0);
comp_q_crc(0);
calc_crc= crc;
file_crc= getq() << 8;
++ostate;
break;
case S_DATAC2:
case S_RSRCC2:
/* Skip crc bytes */
file_crc |= getq();
if (!no_crc)
verify_crc(calc_crc, file_crc);
++ostate;
break;
case S_EXCESS:
fprintf(stderr, "%d excess bytes ignored\n", op-oq);
oq= op;
break;
}
}
op= obuf;
}
getq()
{
int c;
if (oq >= op) {
fprintf(stderr, "premature EOF\n");
exit(1);
}
c= *oq++;
comp_q_crc((unsigned)c);
return c;
}
/* get2q(); q format -- read 2 bytes from input, return short */
short
get2q()
{
short high= getq() << 8;
return high | getq();
}
/* get4q(); q format -- read 4 bytes from input, return long */
long
get4q()
{
int i;
long value= 0;
for (i= 0; i < 4; i++)
value= (value<<8) | getq();
return value;
}
/* getqbuf(); q format -- read n characters from input into buf */
getqbuf(buf, n)
char *buf;
int n;
{
int i;
for (i = 0; i < n; i++)
*buf++ = getq();
}
#define output(c) { *op++ = (c); if (op >= &obuf[BUFSIZ]) oflush(); }
do_q_everything(macname, namebuf)
char *macname;
char *namebuf;
{
unsigned char buf[BUFSIZ];
int n;
register unsigned char *in, *out;
register int b6, b8, data, lastc= 0;
char state68= 0, run= 0;
g_macname= macname;
g_namebuf= namebuf;
ostate= S_HEADER;
stop= 0;
while (!stop && (n= fread(buf, 1, BUFSIZ, ifp)) > 0) {
in= buf;
out= buf+n;
do {
if ((b6= lookup[*in]) >= 64) {
switch (b6) {
case DONE:
goto done;
case SKIP:
break;
default:
fprintf(stderr,
"bad char '%c'(%d)\n",
*in, *in);
goto done;
}
}
else {
/* Pack 6 bits to 8 bits */
switch (state68++) {
case 0:
b8= b6<<2;
continue; /* No data byte */
case 1:
data= b8 | (b6>>4);
b8= (b6&0xF) << 4;
break;
case 2:
data= b8 | (b6>>2);
b8= (b6&0x3) << 6;
break;
case 3:
data= b8 | b6;
state68= 0;
break;
}
if (!run) {
if (data == RUNCHAR)
run= 1;
else
output(lastc= data);
}
else {
if (data == 0) {
output(lastc= RUNCHAR);
}
else {
while (--data > 0) {
output(lastc);
}
}
run= 0;
}
}
} while (++in < out);
}
done: oflush();
if (!stop && ostate != S_EXCESS) {
fprintf(stderr, "premature EOF\n");
exit(1);
}
}
/* Ahh, too bad. The following routine takes up half of the CPU time.
But in this form it's far to complicated to turn it into a macro! */
#define CRCCONSTANT 0x1021
comp_q_crc(c)
register unsigned int c;
{
register int i;
register unsigned long temp = crc;
/* Never mind why I call it WOP... */
#define WOP { \
c <<= 1; \
if ((temp <<= 1) & WORDBIT) \
temp = (temp & WORDMASK) ^ CRCCONSTANT; \
temp ^= (c >> 8); \
c &= BYTEMASK; \
}
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
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;
unsigned int calc_crc, file_crc;
extern long make_file();
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);
}
}
long
make_file(fname, compressed)
char *fname;
int compressed;
{
char ibuf[BUFSIZ];
FILE *outf;
register long nbytes = 0L;
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 << 3) & WORDMASK) | (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]) << 2) | (SIXB(ip[1]) >> 4);
incount = ((outcount / 3) + 1) * 4;
for (n = numread; n < incount; n++) /* restore lost spaces */
ibuf[n] = ' ';
n = 0;
while (n <= outcount) {
*op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4;
*op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2;
*op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]);
ip += 4;
n += 3;
}
for (n=1; n <= outcount; n++)
comp_c_crc((unsigned)obuf[n]);
fwrite(obuf+1, 1, outcount, outf);
return outcount;
}
hex_to_bin(ibuf, outf)
char ibuf[];
FILE *outf;
{
register char *ip = ibuf;
register int n, outcount;
int c;
n = strlen(ibuf) - 1;
outcount = n / 2;
for (n = 0; n < outcount; n++) {
c = hexit(*ip++);
comp_e_crc((unsigned)(c = (c << 4) | hexit(*ip++)));
fputc(c, outf);
}
return outcount;
}
hexit(c)
int c;
{
if ('0' <= c && c <= '9')
return c - '0';
if ('A' <= c && c <= 'F')
return c - 'A' + 10;
fprintf(stderr, "illegal hex digit: %c", c);
exit(4);
/* NOTREACHED */
}
put2(bp, value)
char *bp;
short value;
{
*bp++ = (value >> 8) & BYTEMASK;
*bp++ = value & BYTEMASK;
}
put4(bp, value)
char *bp;
long value;
{
register int i, c;
for (i = 0; i < 4; i++) {
c = (value >> 24) & BYTEMASK;
value <<= 8;
*bp++ = c;
}
}