Create macutils repository

This commit is contained in:
Will Nayes 2018-03-22 19:30:02 -05:00
commit 72ea2b578a
162 changed files with 17091 additions and 0 deletions

483
README Executable file
View File

@ -0,0 +1,483 @@
This is version 2.0b3 of macutil (22-OCT-1992).
This package contains the following utilities:
macunpack
hexbin
macsave
macstream
binhex
tomac
frommac
Requirements:
a. Of course a C compiler.
b. A 32-bit machine with large memory (or at least the ability to 'malloc'
large chunks of memory). For reasons of efficiency and simplicity the
programs work 'in-core', also many files are first read in core.
If somebody can take the trouble to do it differently, go ahead!
There are also probably in a number of places implicit assumptions that
an int is 32 bits. If you encounter such occurrences feel free to
notify me.
c. A Unix (tm) machine, or something very close. There are probably quite
a lot of Unix dependencies. Also here, if you have replacements, feel
free to send comments.
d. This version normally uses the 'mkdir' system call available on BSD Unix
and some versions of SysV Unix. You can change that, see the makefile for
details.
File name translation:
The programs use a table driven program to do Mac filename -> Unix filename
translation. When compiled without further changes the translation is as
follows:
Printable ASCII characters except space and slash are not changed.
Slash and space are changed to underscore, as are all characters that
do not fall in the following group.
Accented letters are translated to their unaccented counterparts.
If your system supports the Latin-1 character set, you can change this
translation scheme by specifying '-DLATIN1' for the 'CF' macro in the
makefile. This will translate all accented letters (and some symbols)
to their Latin-1 counterpart. This feature is untested (I do not have
access to systems that cater for Latin-1), so use with care.
Future revisions of the program will have user settable conversions.
Another feature of filename translation is that when the -DNODOT flag is
specified in the CF macro an initial period will be translated to underscore.
MacBinary stream:
Most programs allow MacBinary streams as either input or output. A
MacBinary stream is a series of files in MacBinary format pasted
together. Embedded within a MacBinary stream can be information about
folders. So a MacBinary stream can contain all information about a
folder and its constituents.
Appleshare support:
Optionally the package can be compiled for systems that support the sharing
of Unix and Mac filesystems. The package supports AUFS (AppleTalk Unix File
Server) from CAP (Columbia AppleTalk Package) and AppleDouble (from Apple).
It will not support both at the same time. Moreover this support requires
the existence of the 'mkdir' system call. And finally, as implemented it
probably will work on big-endian BSD compatible systems. If you have a SysV
system with restricted filename lengths you can get problems. I do not know
also whether the structures are stored native or Apple-wise on little-endian
systems. And also, I did not test it fully; having no access to either AUFS
or AppleDouble systems.
Acknowledgements:
a. Macunpack is for a large part based on the utilities 'unpit' and 'unsit'
written by:
Allan G. Weber
weber%brand.usc.edu@oberon.usc.edu
(wondering whether that is still valid!). I combined the two into a
single program and did a lot of modification. For information on the
originals, see the files README.unpit and README.unsit.
b. The crc-calculating routines are based on a routine originally written by:
Mark G. Mendel
UUCP: ihnp4!umn-cs!hyper!mark
(this will not work anymore for sure!). Also here I modified the stuff
and expanded it, see the files README.crc and README.crc.orig.
c. LZW-decompression is taken from the sources of compress that are floating
around. Probably I did not use the most efficient version, but this
program was written to get it done. The version I based it on (4.0) is
authored by:
Steve Davies (decvax!vax135!petsd!peora!srd)
Jim McKie (decvax!mcvax!jim) (Hi Jim!)
Joe Orost (decvax!vax135!petsd!joe)
Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
Ken Turkowski (decvax!decwrl!turtlevax!ken)
James A. Woods (decvax!ihnp4!ames!jaw)
I am sure those e-mail addresses also will not work!
d. Optional AUFS support comes from information supplied by:
Casper H.S. Dik
University of Amsterdam
Kruislaan 409
1098 SJ Amsterdam
Netherlands
phone: +31205922022
email: casper@fwi.uva.nl
This is an e-mail address that will workm but the address and phone
number ar no longer valid.
See the makefile.
Some caveats are applicable:
1. I did not fully test it (we do not use it). But the unpacking
appears to be correct. Anyhow, as the people who initially compile
it and use it will be system administrators I am confident they are
able to locate bugs! (What if an archive contains a Macfile with
the name .finderinfo or .resource? I have had two inputs for AUFS
support [I took Caspers; his came first], but both do not deal with
that. Does CAP deal with it?) Also I have no idea whether this
version supports it under SysV, so beware.
2. From one of the README's supplied by Casper:
Files will not appear in an active folder, because Aufs doesn't like
people working behind it's back.
Simply opening and closing the folder will suffice.
Appears to be the same problem as when you are unpacking or in some
other way creating files in a folder open to multifinder. I have seen
bundle bits disappear this way. So if after unpacking you see the
generic icon; check whether a different icon should appear and check
the bundle bit.
The desktop isn't updated, but that doesn't seem to matter.
I dunno, not using it.
e. Man pages are now supplied. The base was provided by:
Douglas Siebert
ISCA
dsiebert@icaen.uiowa.edu
f. Because of some problems the Uncompactor has been rewritten, it is now
based on sources from the dearchiver unzip (of PC fame). Apparently the
base code is by:
Samuel H. Smith
I have no further address available, but as soon as I find a better
attribution, I will include it.
g. UnstuffIt's LZAH code comes from lharc (also of PC fame) by:
Haruhiko Okumura,
Haruyasu Yoshizaki,
Yooichi Tagawa.
h. Zoom's code comes from information supplied by Jon W{tte
(d88-jwa@nada.kth.se). The Zoo decompressor is based on the routine
written by Rahul Dhesi (dhesi@cirrus.COM). This again is based on
code by Haruhiko Okumura. See also the file README.zoom.
i. MacLHa's decompressors are identical to the ones mentioned in g and h.
j. Most of hexbin's code is based on code written/modified by:
Dave Johnson, Brown University Computer Science
Darin Adler, TMQ Software
Jim Budler, amdcad!jimb
Dan LaLiberte, liberte@uiucdcs
ahm (?)
Jeff Meyer, John Fluke Company
Guido van Rossum, guido@cwi.nl (Hi!)
(most of the e-mail addresses will not work, the affiliation may also
be incorrect by now.) See also the file README.hexbin.
k. The dl code in hexbin comes is based on the original distribution of
SUMacC.
l. The mu code in hexbin is a slight modification of the hcx code (the
compressions are identical).
m. The MW code for StuffIt is loosely based on code by Daniel H. Bernstein
(brnstnd@acf10.nyu.edu).
n. Tomac and frommac are loosely based on the original macput and macget
by (the e-mail address will not work anymore):
Dave Johnson
ddj%brown@csnet-relay.arpa
Brown University Computer Science
-------------------------------------------------------------------------------
Macunpack will unpack PackIt, StuffIt, Diamond, Compactor/Compact Pro, most
StuffItClassic/StuffItDeluxe, and all Zoom and LHarc/MacLHa archives, and
archives created by later versions of DiskDoubler.
Also it will decode files created by BinHex5.0, MacBinary, UMCP,
Compress It, ShrinkToFit, MacCompress, DiskDoubler and AutoDoubler.
(PackIt, StuffIt, Diamond, Compactor, Compact/Pro, Zoom and LHarc/MacLHa are
archivers written by respectively: Harry R. Chesley, Raymond Lau, Denis Sersa,
Bill Goodman, Jon W{tte* and Kazuaki Ishizaki. BinHex 5.0, MacBinary and
UMCP are by respectively: Yves Lempereur, Gregory J. Smith, Information
Electronics. ShrinkToFit is by Roy T. Hashimoto, Compress It by Jerry
Whitnell, and MacCompress, DiskDoubler and AutoDoubler are all by
Lloyd Chambers.)
* from his signature:
Jon W{tte - Yes, that's a brace - Damn Swede.
Actually it is an a with two dots above; some (German inclined) people
refer to it (incorrectly) as a-umlaut.
It does not deal with:
a. Password protected archives.
b. Multi-segment archives.
c. Plugin methods for Zoom.
d. MacLHa archives not packed in MacBinary mode (the program deals very
poorly with that!).
Background:
There are millions of ways to pack files, and unfortunately, all have been
implemented one way or the other. Below I will give some background
information about the packing schemes used by the different programs
mentioned above. But first some background about compression (I am no
expert, more comprehensive information can be found in for instance:
Tomothy Bell, Ian H. Witten and John G. Cleary, Modelling for Text
Compression, ACM Computing Surveys, Vol 21, No 4, Dec 1989, pp 557-591).
Huffman encoding (also called Shannon-Fano coding or some other variation
of the name). An encoding where the length of the code for the symbols
depends on the frequency of the symbols. Frequent symbols have shorter
codes than infrequent symbols. The normal method is to first scan the
file to be compressed, and to assign codes when this is done (see for
instance: D. E. Knuth, the Art of Computer Programming). Later methods
have been designed to create the codes adaptively; for a survey see:
Jeremy S. Vetter, Design and Analysis of Dynamic Huffman Codes, JACM,
Vol 34, No 4, Oct 1987, pp 825-845.
LZ77: The first of two Ziv-Lempel methods. Using a window of past encoded
text, output consists of triples for each sequence of newly encoded
symbols: a back pointer and length of past text to be repeated and the
first symbol that is not part of that sequence. Later versions allowed
deviation from the strict alternation of pointers and uncoded symbols
(LZSS by Bell). Later Brent included Huffman coding of the pointers
(LZH).
LZ78: While LZ77 uses a window of already encoded text as a dictionary,
LZ78 dynamically builds the dictionary. Here again pointers are strictly
alternated with unencoded new symbols. Later Welch (LZW) managed to
eliminate the output of unencoded symbols. This algorithm is about
the same as the one independently invented by Miller and Wegman (MW).
A problem with these two schemes is that they are patented. Thomas
modified LZW to LZC (as used in the Unix compress command). While LZ78
and LZW become static once the dictionary is full, LZC has possibilities
to reset the dictionary. Many LZC variants are in use, depending on the
size of memory available. They are distinguished by the maximum number
of bits that are used in a code.
A number of other schemes are proposed and occasionally used. The main
advantage of the LZ type schemes is that (especially) decoding is fairly fast.
Programs background:
Plain programs:
BinHex 5.0:
Unlike what its name suggest this is not a true successor of BinHex 4.0.
BinHex 5.0 takes the MacBinary form of a file and stores it in the data
fork of the newly created file.
Although BinHex 5.0 does not create BinHex 4.0 compatible files, StuffIt
will give the creator type of BinHex 5.0 (BnHq) to its binhexed files,
rather than the creator type of BinHex 4.0 (BNHQ). The program knows
about that.
MacBinary:
As its name suggests, it does the same as BinHex 5.0.
UMCP:
Looks similar, but the file as stored by UMCP is not true MacBinary.
Size fields are modified, the result is not padded to a multiple of 128,
etc. Macunpack deals with all that, but until now is not able to
correctly restore the finder flags of the original file. Also, UMCP
created files have type "TEXT" and creator "ttxt", which can create a
bit of confusion. Macunpack will recognize these files only if the
creator has been modified to "UMcp".
Compressors:
ShrinkToFit:
This program uses a Huffman code to compress. It has an option (default
checked for some reason), COMP, for which I do not yet know the
meaning. Compressing more than a single file in a single run results
in a failure for the second and subsequent files.
Compress It:
Also uses a Huffman code to compress.
MacCompress:
MacCompress has two modes of operation, the first mode is (confusingly)
MacCompress, the second mode is (again confusingly) UnixCompress. In
MacCompress mode both forks are compressed using the LZC algorithm.
In UnixCompress mode only the data fork is compressed, and some shuffling
of resources is performed. Upto now macunpack only deals with MacCompress
mode. The LZC variant MacCompress uses depends on memory availability.
12 bit to 16 bit LZC can be used.
Archivers:
ArcMac:
Nearly PC-Arc compatible. Arc knows 8 compression methods, I have seen
all of them used by ArcMac, except the LZW techniques. Here they are:
1: No compression, shorter header
2: No compression
3: (packing) Run length encoding
4: (squeezing) RLE followed by Huffman encoding
5: (crunching) LZW
6: (crunching) RLE followed by LZW
7: (crunching) as the previous but with a different hash function
8: (crunching) RLE followed by 12-bit LZC
9: (squashing) 13-bit LZC
PackIt:
When archiving a file PackIt either stores the file uncompressed or
stores the file Huffman encoded. In the latter case both forks are
encoded using the same Huffman tree.
StuffIt and StuffIt Classic/Deluxe:
These have the ability to use different methods for the two forks of a
file. The following standard methods I do know about (the last three
are only used by the Classic/Deluxe version 2.0 of StuffIt):
0: No compression
1: Run length encoding
2: 14-bit LZC compression
3: Huffman encoding
5: LZAH: like LZH, but the Huffman coding used is adaptive
6: A Huffman encoding using a fixed (built-in) Huffman tree
8: A MW encoding
Diamond:
Uses a LZ77 like frontend plus a Fraenkel-Klein like backend (see
Apostolico & Galil, Combinatorial Algorithms on Words, pages 169-183).
Compactor/Compact Pro:
Like StuffIt, different encodings are possible for data and resource fork.
Only two possible methods are used:
0: Run length encoding
1: RLE followed by some form of LZH
Zoom:
Data and resource fork are compressed with the same method. The standard
uses either no compression or some form of LZH
MacLHa:
Has two basic modes of operation, Mac mode and Normal mode. In Mac mode
the file is archived in MacBinary form. In normal mode only the forks
are archived. Normal mode should not be used (and can not be unpacked
by macunpack) as all information about data fork size/resource fork size,
type, creator etc. is lost. It knows quite a few methods, some are
probably only used in older versions, the only methods I have seen used
are -lh0-, -lh1- and -lh5-. Methods known by MacLHa:
-lz4-: No compression
-lz5-: LZSS
-lzs-: LZSS, another variant
-lh0-: No compression
-lh1-: LZAH (see StuffIt)
-lh2-: Another form of LZAH
-lh3-: A form of LZH, different from the next two
-lh4-: LZH with a 4096 byte buffer (as far as I can see the coding in
MacLHa is wrong)
-lh5-: LZH with a 8192 byte buffer
DiskDoubler:
The older version of DiskDoubler is compatible with MacCompress. It does
not create archives, it only compresses files. The newer version (since
3.0) does both archiving and compression. The older version uses LZC as
its compression algorithm, the newer version knows a number of different
compression algorithms. Many (all?) are algorithms used in other
archivers. Probably this is done to simplify conversion from other formats
to DiskDoubler format archives. I have seen actual DiskDoubler archives
that used methods 0, 1 and 8:
0: No compression
1: LZC
2: unknown
3: RLE
4: Huffman (or no compression)
5: unknown
6: unknown
7: An improved form of LZSS
8: Compactor/Compact Pro compatible RLE/LZH or RLE only
9: unknown
The DiskDoubler archive format contains many subtle twists that make it
difficult to properly read the archive (or perhaps this is on purpose?).
Naming:
Some people have complained about the name conflict with the unpack utility
that is already available on Sys V boxes. I had forgotten it, so there
really was a problem. The best way to solve it was to trash pack/unpack/pcat
and replace it by compress/uncompress/zcat. Sure, man uses it; but man uses
pcat, so you can retain pcat. If that was not an option you were able to feel
free to rename the program. But finally I relented. It is now macunpack.
When you have problems unpacking an archive feel free to ask for information.
I am especially keen when the program detects an unknown method. If you
encounter such an archive, please, mail a 'binhexed' copy of the archive
to me so that I can deal with it. Password protected archives are (as
already stated) not implemented. I do not have much inclination to do that.
Also I feel no inclination to do multi-segment archives.
-------------------------------------------------------------------------------
Hexbin will de-hexify files created in BinHex 4.0 compatible format (hqx)
but also the older format (dl, hex and hcx). Moreover it will uudecode
files uuencoded by UUTool (the only program I know that does UU hexification
of all Mac file information).
There are currently many programs that are able to create files in BinHex 4.0
compatible format. There are however some slight differences, and most
de-hexifiers are not able to deal with all the variations. This program is
very simple minded. First it will intuit (based on the input) whether the
file is in dl, hex, hcx or hqx format. Next it will de-hexify the file.
When the format is hqx, it will check whether more files follow, and continue
processing. So you can catenate multiple (hqx) hexified files together and
feed them as a single file to hexbin. Also hexbin does not mind whether lines
are separated by CR's, LF's or combinations of the two. Moreover, it will
strip all leading, trailing and intermediate garbage introduced by mailers
etc. Next, it does not mind if a file is not terminated by a CR or an LF
(as StuffIt 1.5.1 and earlier did), but in that case a second file is not
allowed to follow it. Last, while most hexifiers output lines of equal length,
some do not. Hexbin will deal with that, but there are some caveats; see the
-c option in the man page.
Background:
dl format:
This was the first hexified format used. Programs to deal with it came
from SUMacC. This format only coded resource forks, 4 bits in a byte.
hex format:
I think this is the first format from Yves Lempereur. Like dl format,
it codes 4 bits in a byte, but is able to code both resource and
data fork. Is it BinHex 2.0?
hcx format:
A compressing variant of hex format. Codes 6 bits in a byte.
Is it BinHex 3.0?
hqx format:
Like hcx, but using a different coding (possibly to allow for ASCII->EBCDIC
and EBCDIC->ASCII translation, which not always results in an identical
file). Moreover this format also encodes the original Mac filename.
mu format:
The conversion can be done by the UUTool program from Octavian Micro
Development. It encodes both forks and also some finder info. You will
in general not use this with uudecode on non Mac systems, with uudecode
only the data fork will be uudecoded. UU hexification is well known (and
fairly old) in Unix environments. Moreover it has been ported to lots of
other systems.
-------------------------------------------------------------------------------
Macsave reads a MacBinary stream from standard input and writes the
files according to the options.
-------------------------------------------------------------------------------
Macstream reads files from the Unix host and will output a MacBinary stream
containing all those files together with information about the directory
structure.
-------------------------------------------------------------------------------
Binhex will read a MacBinary stream, or will read files/directories as
indicated on the command line, and will output all files in binhexed (.hqx)
format. Information about the directory structure is lost.
-------------------------------------------------------------------------------
Tomac will transmit a MacBinary stream, or named files to the Mac using
the XMODEM protocol.
-------------------------------------------------------------------------------
Frommac will receive one or more files from the Mac using the XMODEM protocol.
-------------------------------------------------------------------------------
This is an ongoing project, more stuff will appear.
All comments are still welcome. Thanks for the comments I already received.
dik t. winter, amsterdam, nederland
email: dik@cwi.nl
--
Note:
In these programs all algorithms are implemented based on publicly available
software to prevent any claim that would prevent redistribution due to
Copyright. Although parts of the code would indeed fall under the Copyright
by the original author, use and redistribution of all such code is explicitly
allowed. For some parts of it the GNU software license does apply.
--
Appendix.
BinHex 4.0 compatible file creators:
Type Creator Created by
"TEXT" "BthX" BinHqx
"TEXT" "BNHQ" BinHex
"TEXT" "BnHq" StuffIt and StuffIt Classic
"TEXT" "ttxt" Compactor
Files recognized by macunpack:
Type Creator Recognized as
"APPL" "DSEA" "DiskDoubler" Self extracting
"APPL" "EXTR" "Compactor" Self extracting
"APPL" "Mooz" "Zoom" Self extracting
"APPL" "Pack" "Diamond" Self extracting
"APPL" "arc@" "ArcMac" Self extracting (not yet)
"APPL" "aust" "StuffIt" Self extracting
"ArCv" "TrAS" "AutoSqueeze" (not yet)
"COMP" "STF " "ShrinkToFit"
"DD01" "DDAP" "DiskDoubler"
"DDAR" "DDAP" "DiskDoubler"
"DDF." "DDAP" "DiskDoubler" (any fourth character)
"DDf." "DDAP" "DiskDoubler" (any fourth character)
"LARC" "LARC" "MacLHa (LHARC)"
"LHA " "LARC" "MacLHa (LHA)"
"PACT" "CPCT" "Compactor"
"PIT " "PIT " "PackIt"
"Pack" "Pack" "Diamond"
"SIT!" "SIT!" "StuffIt"
"SITD" "SIT!" "StuffIt Deluxe"
"Smal" "Jdw " "Compress It"
"TEXT" "BnHq" "BinHex 5.0"
"TEXT" "GJBU" "MacBinary 1.0"
"TEXT" "UMcp" "UMCP"
"ZIVM" "LZIV" "MacCompress(M)"
"ZIVU" "LZIV" "MacCompress(U)" (not yet)
"mArc" "arc*" "ArcMac" (not yet)
"zooM" "zooM" "Zoom"

174
binhex/binhex.c Executable file
View File

@ -0,0 +1,174 @@
#include <stdio.h>
#include "../fileio/machdr.h"
#include "../fileio/rdfile.h"
#include "../util/patchlevel.h"
extern char *malloc();
extern char *realloc();
extern char *strcat();
extern void exit();
extern void transname();
extern void do_indent();
extern void dofile();
#define LOCALOPT "RilqVH"
static void usage();
static char options[128];
static char *dir_stack;
static int dir_ptr = -64;
static int dir_max;
int dorep = 1;
int main(argc, argv)
int argc;
char **argv;
{
int c, i, j, n;
extern int optind;
extern char *optarg;
int errflg;
char text[32], ftype[5], fauth[5];
int dir_skip = 0, write_it, query = 0, list = 0, info_only = 0;
int indent = 0;
(void)strcat(options, get_rdfileopt());
(void)strcat(options, LOCALOPT);
errflg = 0;
while((c = getopt(argc, argv, options)) != EOF) {
if(!rdfileopt((char)c)) {
switch(c) {
case 'R':
dorep = 0;
break;
case 'l':
list++;
break;
case 'q':
query++;
break;
case 'i':
info_only++;
break;
case '?':
errflg++;
break;
case 'H':
give_rdfileopt();
(void)fprintf(stderr, "Binhex specific options:\n");
(void)fprintf(stderr, "-r:\tdo not use run length encoding\n");
(void)fprintf(stderr,
"-i:\tgive information only, do not write\n");
(void)fprintf(stderr, "-l:\tgive listing\n");
(void)fprintf(stderr,
"-q:\tquery for every file/folder before writing\n");
(void)fprintf(stderr,
"-V:\tgive information about this version\n");
(void)fprintf(stderr, "-H:\tthis message\n");
(void)fprintf(stderr, "Default is silent writing\n");
exit(0);
case 'V':
(void)fprintf(stderr, "Version %s, ", VERSION);
(void)fprintf(stderr, "patchlevel %d", PATCHLEVEL);
(void)fprintf(stderr, "%s.\n", get_minb());
exit(0);
}
}
}
if(errflg) {
usage();
exit(1);
}
if(info_only || query) {
list++;
}
setup(argc - optind, argv + optind);
while((i = nextfile()) != ISATEND) {
if(dir_skip) {
if(i == ISDIR) {
dir_skip++;
} else if(i == ENDDIR) {
dir_skip--;
}
continue;
}
write_it = 1;
n = file_info[I_NAMEOFF] & 0x7f;
transname(file_info + I_NAMEOFF + 1, text, n);
if(i == ISFILE) {
transname(file_info + I_TYPEOFF, ftype, 4);
transname(file_info + I_AUTHOFF, fauth, 4);
}
if(list) {
if(i == ISFILE) {
do_indent(indent);
(void)fprintf(stderr,
"name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
text, ftype, fauth, (long)data_size, (long)rsrc_size);
} else if(i == ISDIR) {
do_indent(indent);
dir_ptr += 64;
if(dir_ptr == dir_max) {
if(dir_max == 0) {
dir_stack = malloc(64);
} else {
dir_stack = realloc(dir_stack, (unsigned)dir_max + 64);
}
dir_max += 64;
if(dir_stack == NULL) {
(void)fprintf(stderr, "Insufficient memory\n");
exit(1);
}
}
for(j = 0; j <= n; j++) {
dir_stack[dir_ptr + j] = text[j];
}
(void)fprintf(stderr, "folder=\"%s\"", text);
indent++;
} else {
indent--;
do_indent(indent);
(void)fprintf(stderr, "leaving folder \"%s\"",
dir_stack + dir_ptr);
dir_ptr -= 64;
}
if(info_only) {
write_it = 0;
}
if(query) {
if(i != ENDDIR) {
write_it = do_query();
} else {
(void)fputc('\n', stderr);
}
if(!write_it && i == ISDIR) {
dir_skip = 1;
indent--;
dir_ptr -= 64;
}
} else {
(void)fputc('\n', stderr);
}
}
if(write_it) {
if(i == ISFILE) {
dofile();
}
}
}
exit(0);
/* NOTREACHED */
}
static void usage()
{
(void)fprintf(stderr, "Usage: binhex [-%s] [files]\n", options);
(void)fprintf(stderr, "Use \"binhex -H\" for help.\n");
}

192
binhex/dofile.c Executable file
View File

@ -0,0 +1,192 @@
#include "../fileio/machdr.h"
#include "../fileio/rdfile.h"
extern int dorep;
extern unsigned long binhex_crcinit;
extern unsigned long binhex_updcrc();
#define RUNCHAR 0x90
static int pos_ptr;
static char codes[] =
"!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
static int state;
static int savebits;
static int rep_char;
static int rep_count;
void doheader();
void dofork();
void outbyte();
void finish();
void outbyte1();
void out6bit();
void outchar();
void dofile()
{
(void)printf("(This file must be converted; you knew that already.)\n");
(void)printf("\n");
pos_ptr = 1;
state = 0;
rep_char = -1;
rep_count = 0;
outchar(':');
doheader();
dofork(data_fork, data_size);
dofork(rsrc_fork, rsrc_size);
finish();
(void)putchar(':');
(void)putchar('\n');
}
void doheader()
{
unsigned long crc;
int i, n;
crc = binhex_crcinit;
n = file_info[I_NAMEOFF];
crc = binhex_updcrc(crc, file_info + I_NAMEOFF, n + 1);
for(i = 0; i <= n; i++) {
outbyte(file_info[I_NAMEOFF + i]);
}
n = 0;
crc = binhex_updcrc(crc, (char *)&n, 1);
outbyte(0);
crc = binhex_updcrc(crc, file_info + I_TYPEOFF, 4);
for(i = 0; i < 4; i++) {
outbyte(file_info[I_TYPEOFF + i]);
}
crc = binhex_updcrc(crc, file_info + I_AUTHOFF, 4);
for(i = 0; i < 4; i++) {
outbyte(file_info[I_AUTHOFF + i]);
}
crc = binhex_updcrc(crc, file_info + I_FLAGOFF, 2);
for(i = 0; i < 2; i++) {
outbyte(file_info[I_FLAGOFF + i]);
}
crc = binhex_updcrc(crc, file_info + I_DLENOFF, 4);
for(i = 0; i < 4; i++) {
outbyte(file_info[I_DLENOFF + i]);
}
crc = binhex_updcrc(crc, file_info + I_RLENOFF, 4);
for(i = 0; i < 4; i++) {
outbyte(file_info[I_RLENOFF + i]);
}
outbyte((int)(crc >> 8));
outbyte((int)(crc & 0xff));
}
void dofork(fork, size)
char *fork;
int size;
{
unsigned long crc;
int i;
crc = binhex_updcrc(binhex_crcinit, fork, size);
for(i = 0; i < size; i++) {
outbyte(fork[i]);
}
outbyte((int)(crc >> 8));
outbyte((int)(crc & 0xff));
}
void outbyte(b)
int b;
{
b &= 0xff;
if(dorep && (b == rep_char)) {
if(++rep_count == 254) {
outbyte1(RUNCHAR);
outbyte1(255);
rep_char = -1;
rep_count = 0;
}
} else {
if(rep_count > 0) {
if(rep_count > 3) {
outbyte1(RUNCHAR);
outbyte1(rep_count + 1);
} else {
while(rep_count-- > 0) {
outbyte1(rep_char);
}
}
}
outbyte1(b);
if(b == RUNCHAR) {
outbyte1(0);
rep_char = -1;
} else {
rep_char = b;
}
rep_count = 0;
}
}
void finish()
{
if(rep_count > 0) {
if(rep_count > 3) {
outbyte1(RUNCHAR);
outbyte1(rep_count + 1);
} else {
while(rep_count-- > 0) {
outbyte1(rep_char);
}
}
}
switch(state) {
case 1:
out6bit(savebits << 4);
break;
case 2:
out6bit(savebits << 2);
break;
default:
break;
}
}
void outbyte1(b)
int b;
{
switch(state) {
case 0:
out6bit(b >> 2);
savebits = b & 0x3;
state = 1;
break;
case 1:
b |= (savebits << 8);
out6bit(b >> 4);
savebits = b & 0xf;
state = 2;
break;
case 2:
b |= (savebits << 8);
out6bit(b >> 6);
out6bit(b & 0x3f);
state = 0;
break;
}
}
void out6bit(c)
char c;
{
outchar(codes[c & 0x3f]);
}
void outchar(c)
char c;
{
(void)putchar(c);
if(++pos_ptr > 64) {
(void)putchar('\n');
pos_ptr = 1;
}
}

51
binhex/makefile Executable file
View File

@ -0,0 +1,51 @@
CFLAGS = -O $(CF)
SRCS = binhex.c dofile.c
OBJS = binhex.o dofile.o
LIB = ../crc/libcrc.a
TNAME = ../util/transname
BNAME = ../util/backtrans
UNAME = ../util/util
INAME = ../fileio/rdfile
GNAME = ../fileio/fileglob
XOBJS = $(TNAME).o $(BNAME).o $(UNAME).o $(INAME).o $(GNAME).o
XSRCS = $(TNAME).c $(BNAME).c $(UNAME).c $(INAME).c $(GNAME).c
binhex: $(OBJS) $(XOBJS) $(LIB)
$(CC) $(CFLAGS) -o binhex $(OBJS) $(XOBJS) $(LIB)
$(LIB): ../crc/makecrc.c
(cd ../crc; make CC=$(CC) CF="$(CF)" )
$(TNAME).o: $(TNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(BNAME).o: $(BNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(UNAME).o: $(UNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(INAME).o: $(INAME).c
(cd ../fileio; make CC=$(CC) CF="$(CF)" )
$(GNAME).o: $(GNAME).c
(cd ../fileio; make CC=$(CC) CF="$(CF)" )
lint:
lint $(CF) $(LFLAGS) $(SRCS) $(XSRCS)
clean:
-rm -f *.o
clobber:clean
-rm -f binhex
binhex.o: ../fileio/machdr.h
binhex.o: ../fileio/rdfile.h
binhex.o: ../util/patchlevel.h
dofile.o: ../fileio/machdr.h
dofile.o: ../fileio/rdfile.h

4
comm/comm.h Executable file
View File

@ -0,0 +1,4 @@
#define XM /* Know about XMODEM */
#undef YM /* Know about YMODEM */
#undef ZM /* Know about ZMODEM */

167
comm/frommac.c Executable file
View File

@ -0,0 +1,167 @@
#include <stdio.h>
#include "comm.h"
#include "../util/patchlevel.h"
#include "../fileio/machdr.h"
#include "globals.h"
#include "../fileio/fileglob.h"
#include "../fileio/wrfile.h"
#define LOCALOPT "lmxyzoTVH"
extern void exit();
extern void setup_tty();
extern void reset_tty();
extern char info[];
static void usage();
static char options[128];
static int multi_file = 0;
static int listmode = 0;
int main(argc, argv)
int argc;
char **argv;
{
extern int optind;
extern char *optarg;
int errflg;
int c;
char tname[64];
char fauth[5];
char ftype[5];
set_wrfileopt(0);
(void)strcat(options, get_wrfileopt());
(void)strcat(options, LOCALOPT);
errflg = 0;
while((c = getopt(argc, argv, options)) != EOF) {
if(!wrfileopt((char)c)) {
switch(c) {
case 'l':
listmode++;
break;
case 'm':
multi_file++;
break;
case 'x':
xfertype = XMODEM;
#ifndef XM
(void)fprintf(stderr, "XMODEM not supported\n");
exit(1);
#else /* XM */
break;
#endif /* XM */
case 'y':
xfertype = YMODEM;
#ifndef YM
(void)fprintf(stderr, "YMODEM not supported\n");
exit(1);
#else /* YM */
break;
#endif /* YM */
case 'z':
xfertype = ZMODEM;
#ifndef ZM
(void)fprintf(stderr, "ZMODEM not supported\n");
exit(1);
#else /* ZM */
break;
#endif /* ZM */
case 'o':
pre_beta++;
break;
case 'T':
time_out++;
break;
case '?':
errflg++;
break;
case 'H':
give_wrfileopt();
(void)fprintf(stderr, "Frommac specific options:\n");
(void)fprintf(stderr, "-l:\tgive listing\n");
(void)fprintf(stderr, "-m:\tmulti-file transfer\n");
#ifdef XM
(void)fprintf(stderr, "-x:\tuse XMODEM protocol\n");
#endif /* XM */
#ifdef YM
(void)fprintf(stderr, "-y:\tuse YMODEM protocol\n");
#endif /* YM */
#ifdef ZM
(void)fprintf(stderr, "-z:\tuse ZMODEM protocol\n");
#endif /* ZM */
(void)fprintf(stderr, "-o:\tuse pre-beta protocol\n");
(void)fprintf(stderr, "-T:\tdetect time-outs\n");
(void)fprintf(stderr,
"-V:\tgive information about this version\n");
(void)fprintf(stderr, "-H:\tthis message\n");
(void)fprintf(stderr,
"Default is silent receival of a single file using XMODEM\n");
exit(0);
case 'V':
(void)fprintf(stderr, "Version %s, ", VERSION);
(void)fprintf(stderr, "patchlevel %d", PATCHLEVEL);
(void)fprintf(stderr, "%s.\n", get_mina());
(void)fprintf(stderr, "Supported protocols:\n");
#ifdef XM
(void)fprintf(stderr, "\tXMODEM\n");
#endif /* XM */
#ifdef YM
(void)fprintf(stderr, "\tYMODEM\n");
#endif /* YM */
#ifdef ZM
(void)fprintf(stderr, "\tZMODEM\n");
#endif /* ZM */
exit(0);
}
}
}
if(errflg) {
usage();
exit(1);
}
do {
setup_tty();
switch(xfertype) {
case XMODEM:
#ifdef XM
xm_from();
break;
#endif /* XM */
#ifdef YM
case YMODEM:
ym_from();
break;
#endif /* YM */
#ifdef ZM
case ZMODEM:
zm_from();
break;
#endif /* ZM */
}
reset_tty();
if(listmode) {
transname(info + I_NAMEOFF + 1, tname, info[I_NAMEOFF]);
transname(info + I_AUTHOFF, fauth, 4);
transname(info + I_TYPEOFF, ftype, 4);
(void)fprintf(stderr,
"name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
tname, ftype, fauth,
get4(info + I_DLENOFF), get4(info + I_RLENOFF));
(void)fprintf(stderr, "\n");
}
} while(multi_file);
exit(0);
/* NOTREACHED */
}
static void usage()
{
(void)fprintf(stderr, "Usage: frommac [-%s]\n", options);
(void)fprintf(stderr, "Use \"frommac -H\" for help.\n");
}

6
comm/globals.c Executable file
View File

@ -0,0 +1,6 @@
#include "globals.h"
int xfertype = XMODEM;
int pre_beta = 0;
int time_out = 0;

8
comm/globals.h Executable file
View File

@ -0,0 +1,8 @@
#define XMODEM 0
#define YMODEM 1
#define ZMODEM 2
extern int xfertype;
extern int pre_beta;
extern int time_out;

91
comm/makefile Executable file
View File

@ -0,0 +1,91 @@
CFLAGS = -O $(CF)
SRCS1 = tomac.c xm_to.c ym_to.c zm_to.c tty.c globals.c
SRCS2 = frommac.c xm_from.c ym_from.c zm_from.c tty.c globals.c
OBJS1 = tomac.o xm_to.o ym_to.o zm_to.o tty.o globals.o
OBJS2 = frommac.o xm_from.o ym_from.o zm_from.o tty.o globals.o
LIB = ../crc/libcrc.a
TNAME = ../util/transname
BNAME = ../util/backtrans
UNAME = ../util/util
INAME = ../fileio/rdfile
ONAME = ../fileio/wrfile
GNAME = ../fileio/fileglob
XOBJS1 = $(TNAME).o $(BNAME).o $(UNAME).o $(INAME).o $(GNAME).o
XOBJS2 = $(TNAME).o $(UNAME).o $(ONAME).o $(GNAME).o
XSRCS1 = $(TNAME).c $(BNAME).c $(UNAME).c $(INAME).c $(GNAME).c
XSRCS2 = $(TNAME).c $(UNAME).c $(ONAME).c $(GNAME).c
all: tomac frommac
touch all
tomac: $(OBJS1) $(XOBJS1)
$(CC) $(CFLAGS) -o tomac $(OBJS1) $(XOBJS1)
frommac: $(OBJS2) $(XOBJS2)
$(CC) $(CFLAGS) -o frommac $(OBJS2) $(XOBJS2)
$(LIB): ../crc/makecrc.c
(cd ../crc; make CC=$(CC) CF="$(CF)" )
$(TNAME).o: $(TNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(BNAME).o: $(BNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(UNAME).o: $(UNAME).c
(cd ../util; make CC=$(CC) CF="$(CF)" )
$(INAME).o: $(INAME).c
(cd ../fileio; make CC=$(CC) CF="$(CF)" )
$(ONAME).o: $(ONAME).c
(cd ../fileio; make CC=$(CC) CF="$(CF)" )
$(GNAME).o: $(GNAME).c
(cd ../fileio; make CC=$(CC) CF="$(CF)" )
lint:
lint $(CF) $(LFLAGS) $(SRCS1) $(XSRCS)
clean:
-rm -f *.o
clobber:clean
-rm -f all tomac frommac
tomac.o: comm.h
tomac.o: ../fileio/machdr.h
tomac.o: ../fileio/rdfile.h
tomac.o: ../util/patchlevel.h
tomac.o: globals.h
xm_to.o: comm.h
xm_to.o: ../fileio/machdr.h
xm_to.o: ../fileio/rdfile.h
xm_to.o: ../util/masks.h
xm_to.o: globals.h
xm_to.o: protocol.h
ym_to.o: comm.h
zm_to.o: comm.h
frommac.o: comm.h
frommac.o: ../util/patchlevel.h
frommac.o: ../fileio/machdr.h
frommac.o: globals.h
frommac.o: ../fileio/fileglob.h
frommac.o: ../fileio/wrfile.h
xm_from.o: comm.h
xm_from.o: ../fileio/machdr.h
xm_from.o: ../fileio/wrfile.h
xm_from.o: ../util/masks.h
xm_from.o: globals.h
xm_from.o: protocol.h
ym_from.o: comm.h
zm_from.o: comm.h
globals.o: globals.h
tty.o: ../util/masks.h
tty.o: protocol.h
tty.o: globals.h

22
comm/protocol.h Executable file
View File

@ -0,0 +1,22 @@
#define RECORDBYTES 132
#define DATABYTES 128
#define NAMEBYTES 63
#define RETRIES 10
#define SOHTIMO 10
#define ACKTIMO 10
#define LINTIMO 20
#define CHRTIMO 2
#define MAXRECNO 0xff
#define TMO -1
#define DUP '\000'
#define SOH '\001'
#define EOT '\004'
#define ACK '\006'
#define NAK '\025'
#define CAN '\030'
#define EEF '\032'
#define ESC '\033'

242
comm/tomac.c Executable file
View File

@ -0,0 +1,242 @@
#include <stdio.h>
#include "comm.h"
#include "../fileio/machdr.h"
#include "../fileio/rdfile.h"
#include "../util/patchlevel.h"
#include "globals.h"
extern char *malloc();
extern char *realloc();
extern char *strcat();
extern void exit();
extern void transname();
extern void do_indent();
extern void dofile();
extern void setup_tty();
extern void reset_tty();
#define LOCALOPT "ilqxyzoTVH"
static void usage();
static char options[128];
static char *dir_stack;
static int dir_ptr = -64;
static int dir_max;
int main(argc, argv)
int argc;
char **argv;
{
int c, i, j, n;
extern int optind;
extern char *optarg;
int errflg;
char text[32], ftype[5], fauth[5];
int dir_skip = 0, write_it, query = 0, list = 0, info_only = 0;
int indent = 0;
(void)strcat(options, get_rdfileopt());
(void)strcat(options, LOCALOPT);
errflg = 0;
while((c = getopt(argc, argv, options)) != EOF) {
if(!rdfileopt((char)c)) {
switch(c) {
case 'l':
list++;
break;
case 'q':
query++;
break;
case 'i':
info_only++;
break;
case 'o':
pre_beta++;
case 'x':
xfertype = XMODEM;
#ifndef XM
(void)fprintf(stderr, "XMODEM not supported\n");
exit(1);
#else /* XM */
break;
#endif /* XM */
case 'y':
xfertype = YMODEM;
#ifndef YM
(void)fprintf(stderr, "YMODEM not supported\n");
exit(1);
#else /* YM */
break;
#endif /* YM */
case 'z':
xfertype = ZMODEM;
#ifndef ZM
(void)fprintf(stderr, "ZMODEM not supported\n");
exit(1);
#else /* ZM */
break;
#endif /* ZM */
case 'T':
time_out++;
break;
case '?':
errflg++;
break;
case 'H':
give_rdfileopt();
(void)fprintf(stderr, "Tomac specific options:\n");
(void)fprintf(stderr,
"-i:\tgive information only, do not write\n");
(void)fprintf(stderr, "-l:\tgive listing\n");
(void)fprintf(stderr,
"-q:\tquery for every file/folder before writing\n");
#ifdef XM
(void)fprintf(stderr, "-x:\tuse XMODEM protocol\n");
#endif /* XM */
#ifdef YM
(void)fprintf(stderr, "-y:\tuse YMODEM protocol\n");
#endif /* YM */
#ifdef ZM
(void)fprintf(stderr, "-z:\tuse ZMODEM protocol\n");
#endif /* ZM */
(void)fprintf(stderr, "-o:\tuse pre-beta protocol\n");
(void)fprintf(stderr, "-T:\tdetect time-outs\n");
(void)fprintf(stderr,
"-V:\tgive information about this version\n");
(void)fprintf(stderr, "-H:\tthis message\n");
(void)fprintf(stderr,
"Default is silent sending with XMODEM\n");
exit(0);
case 'V':
(void)fprintf(stderr, "Version %s, ", VERSION);
(void)fprintf(stderr, "patchlevel %d", PATCHLEVEL);
(void)fprintf(stderr, "%s.\n", get_minb());
(void)fprintf(stderr, "Supported protocols:\n");
#ifdef XM
(void)fprintf(stderr, "\tXMODEM\n");
#endif /* XM */
#ifdef YM
(void)fprintf(stderr, "\tYMODEM\n");
#endif /* YM */
#ifdef ZM
(void)fprintf(stderr, "\tZMODEM\n");
#endif /* ZM */
exit(0);
}
}
}
if(errflg) {
usage();
exit(1);
}
if(info_only || query) {
list++;
}
setup(argc - optind, argv + optind);
while((i = nextfile()) != ISATEND) {
if(dir_skip) {
if(i == ISDIR) {
dir_skip++;
} else if(i == ENDDIR) {
dir_skip--;
}
continue;
}
write_it = 1;
n = file_info[I_NAMEOFF] & 0x7f;
transname(file_info + I_NAMEOFF + 1, text, n);
if(i == ISFILE) {
transname(file_info + I_TYPEOFF, ftype, 4);
transname(file_info + I_AUTHOFF, fauth, 4);
}
if(list) {
if(i == ISFILE) {
do_indent(indent);
(void)fprintf(stderr,
"name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
text, ftype, fauth, (long)data_size, (long)rsrc_size);
} else if(i == ISDIR) {
do_indent(indent);
dir_ptr += 64;
if(dir_ptr == dir_max) {
if(dir_max == 0) {
dir_stack = malloc(64);
} else {
dir_stack = realloc(dir_stack, (unsigned)dir_max + 64);
}
dir_max += 64;
if(dir_stack == NULL) {
(void)fprintf(stderr, "Insufficient memory\n");
exit(1);
}
}
for(j = 0; j <= n; j++) {
dir_stack[dir_ptr + j] = text[j];
}
(void)fprintf(stderr, "folder=\"%s\"", text);
indent++;
} else {
indent--;
do_indent(indent);
(void)fprintf(stderr, "leaving folder \"%s\"",
dir_stack + dir_ptr);
dir_ptr -= 64;
}
if(info_only) {
write_it = 0;
}
if(query) {
if(i != ENDDIR) {
write_it = do_query();
} else {
(void)fputc('\n', stderr);
}
if(!write_it && i == ISDIR) {
dir_skip = 1;
indent--;
dir_ptr -= 64;
}
} else {
(void)fputc('\n', stderr);
}
}
if(write_it) {
if(i == ISFILE) {
setup_tty();
switch(xfertype) {
#ifdef XM
case XMODEM:
xm_to();
break;
#endif /* XM */
#ifdef YM
case YMODEM:
ym_to();
break;
#endif /* YM */
#ifdef ZM
case ZMODEM:
zm_to();
break;
#endif /* ZM */
}
reset_tty();
}
}
}
exit(0);
/* NOTREACHED */
}
static void usage()
{
(void)fprintf(stderr, "Usage: tomac [-%s] [files]\n", options);
(void)fprintf(stderr, "Use \"tomac -H\" for help.\n");
}

146
comm/tty.c Executable file
View File

@ -0,0 +1,146 @@
#include <stdio.h>
#include <signal.h>
#ifndef TERMIOS_H
#include <sgtty.h>
#else /* TERMIOS_H */
#include <termios.h>
#endif /* TERMIOS_H */
#include <setjmp.h>
#include "../util/masks.h"
#include "protocol.h"
#include "globals.h"
void cleanup();
void timedout();
int tgetc();
void tputc();
static jmp_buf timobuf;
#ifndef TERMIOS_H
static struct sgttyb otty, ntty;
#else /* TERMIOS_H */
static struct termios otty, ntty;
#endif /* TERMIOS_H */
static int ttyfd;
static int signal_set;
void setup_tty()
{
ttyfd = fileno(stderr);
if(!signal_set) {
(void)signal(SIGHUP, cleanup);
(void)signal(SIGINT, cleanup);
(void)signal(SIGQUIT, cleanup);
(void)signal(SIGTERM, cleanup);
if(time_out) {
(void)signal(SIGALRM, timedout);
}
signal_set = 1;
}
#ifndef TERMIOS_H
(void)ioctl(ttyfd, TIOCGETP, &otty);
ntty = otty;
ntty.sg_flags = RAW | ANYP;
(void)ioctl(ttyfd, TIOCSETP, &ntty);
#else /* TERMIOS_H */
(void)tcgetattr(ttyfd, &otty);
ntty = otty;
ntty.c_lflag &= ~(ICANON | ISIG | ECHO);
ntty.c_iflag &= IXOFF;
ntty.c_oflag &= ~(OPOST);
ntty.c_cflag &= ~(PARENB | PARODD);
ntty.c_cc[VMIN] = 1;
ntty.c_cc[VTIME] = 0;
(void)tcsetattr(ttyfd, TCSAFLUSH, &ntty);
#endif /* TERMIOS_H */
}
void reset_tty()
{
(void)sleep(1); /* Wait for output to drain */
#ifndef TERMIOS_H
(void)ioctl(ttyfd, TIOCSETP, &otty);
#else /* TERMIOS_H */
(void)tcsetattr(ttyfd, TCSAFLUSH, &otty);
#endif /* TERMIOS_H */
}
void cleanup(sig) int sig;
{
reset_tty();
exit(sig);
}
void timedout()
{
(void)signal(SIGALRM, timedout);
longjmp(timobuf, 1);
}
int tgetc(timeout)
int timeout;
{
char c;
int i;
if(time_out) {
if(setjmp(timobuf)) {
return TMO;
}
(void)alarm(timeout);
}
i = read(ttyfd, &c, 1);
if(time_out) {
(void)alarm(0);
}
if(i == 0) {
return EOT;
} else {
return c & BYTEMASK;
}
}
tgetrec(buf, count, timeout)
char *buf;
int count, timeout;
{
int i, tot = 0, cc = count;
if(time_out) {
if(setjmp(timobuf)) {
return TMO;
}
(void)alarm(timeout);