Submitted-by: marcel@duteca.tudelft.nl Posting-number: Volume 1, Source:27 Archive-name: archive/unix/marcel/part1 Architecture: UNIX Version-number: 1.00 This package contains Unix versions of the following tools: unbit - undoes the 6-bit executioner format. unexec - undoes the apple2 monitor format. unblu - view and extract from binary 2 archives. usq - usqueeze squeezed files (created by sq3 or extracted from binary 2 or shrinkit archives). sciibin - view and extract from binscii files. NOTE: This is part 1 of a 2 part posting. =README -Here are a bunch of C programs to process different kind -of files containing Apple stuff. -No functional changes from the previous versions. Only some cleanups and -ports to other machines/OS like MSDOS and Macintosh. - -The programs are: - -unbit - undoes the 6-bit executioner format. -unexec - undoes the apple2 monitor format. -unblu - view and extract from binary 2 archives. -usq - usqueeze squeezed files (created by sq3 or - extracted from binary 2 or shrinkit archives). -sciibin - view and extract from binscii files. - - -Use this for example to extract apple files posted -to the comp.binaries.apple2 newsgroup in one of the -above formats. -I use it to extract for example binary 2 or shrinkit -archives (with Andy Mccfaden's nulib) which can easily -be transfered to the Apple as binary files. -It also allows me to print doc files on a laser printer... -This saves me telephone costs and time. - -- Marcel marcel@duteca.tudelft.nl -######################################### -# Marcel J.E. Mol ###################################### -# Delft University of Technology Pink Elephant Management Services # -# The Netherlands Voorburg # -# UUCP: marcel@duteca.tudelft.nl Tel: 070-694231 # -# ###################################### -######################################### - -Version 1.00 =Manifest -Makefile -README -crc.h -filetype.h -getopt.c -sciibin.c -unbit.c -unblu.c -unexec.c -usq.c =Makefile -CFLAGS = -s - - -all: usq unblu unexec unbit sciibin - -usq: usq.o - cc $(CFLAGS) -o $@ $? - -unexec: unexec.o - cc $(CFLAGS) -o $@ $? - -unblu: unblu.o - cc $(CFLAGS) -o $@ $? - -unbit: unbit.o - cc $(CFLAGS) -o $@ $? - -sciibin: sciibin.o - cc $(CFLAGS) -o $@ $? - -unblu.c: filetype.h -sciibin.c: filetype.h crc.h =crc.h -/* - * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. - * NOTE: First srgument must be in range 0 to 255. - * Second argument is referenced twice. - * - * Programmers may incorporate any or all code into their programs, - * giving proper credit within the source. Publication of the - * source routines is permitted so long as proper credit is given - * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, - * Omen Technology. - */ - - /* #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp) */ -#define updcrc(cp, crc) ( (crctab[((crc >> 8) & 0xFF) ^ cp] ^ (crc << 8)) & 0xFFFF) - - -/* crctab calculated by Mark G. Mendel, Network Systems Corporation */ -static unsigned short crctab[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - =filetype.h -char * filetypes[] = { - "non", "bad", "pcd", "ptx", "txt", "pda", "bin", "chr", - "pic", "ba3", "da3", "wpd", "sos", "$0D", "$0E", "dir", - "rpd", "rpi", "$12", "out", "$14", "rpt", "$16", "$17", - "$18", "adb", "awp", "asp", "$1C", "$1D", "$1E", "$1F", - "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", - "$28", "$29", "$2A", "$2B", "$2C", "$2D", "$2E", "$2F", - "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", - "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", - "$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47", - "$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", - "$50", "$51", "$52", "$53", "$54", "$55", "$56", "$57", - "$58", "$59", "$5A", "$5B", "$5C", "$5D", "$5E", "$5F", - "pre", "$61", "$62", "$63", "$64", "$65", "$66", "$67", - "$68", "$69", "$6A", "nio", "$6C", "dvr", "$6E", "hdv", - "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", - "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", - "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", - "$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F", - "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", - "$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", - "wpf", "mac", "hlp", "dat", "$A4", "lex", "$A6", "$A7", - "$A8", "$A9", "$AA", "gsb", "arc", "$AD", "$AE", "$AF", - "src", "obj", "lib", "s16", "rtl", "exe", "str", "tsf", - "nda", "cda", "tol", "drv", "$BC", "fst", "$BE", "doc", - "pnt", "scr", "ani", "$C3", "$C4", "$C5", "$C6", "$C7", - "fon", "fnd", "icn", "$CB", "$CC", "$CD", "$CE", "$CF", - "$D0", "$D1", "$D2", "$D3", "$D4", "$D5", "$D6", "$D7", - "$D8", "$D9", "$DA", "$DB", "$DC", "$DD", "$DE", "$DF", - "lbr", "$E1", "ati", "$E3", "$E4", "$E5", "$E6", "$E7", - "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "$EE", "pas", - "cmd", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", - "$F8", "img", "int", "ivr", "bas", "var", "rel", "sys", - }; - -/* -ProDOS Filetypes - -Num Name OS Meaning -======================================================================== -$00 typeless -$01 BAD both BAD blocks file -$02 PCD SOS Pascal CoDe file -$03 PTX SOS Pascal TeXt file -$04 TXT both ASCII text file -$05 PDA SOS Pascal DAta file -$06 BIN both BINary file -$07 CHR SOS CHaRacter font file -$08 PIC both PICture file -$09 BA3 SOS Business BASIC (SOS) program file -$0A DA3 SOS Business BASIC (SOS) data file -$0B WPD SOS Word Processor Document -$0C SOS SOS SOS system file -$0D SOS SOS reserved file type -$0E SOS SOS reserved file type -$0F DIR Both subDIRectory file -$10 RPD SOS RPS data file -$11 RPI SOS RPS index file -$12 SOS Applefile diskcard file -$13 SOS Applefile model file -$14 SOS Applefile report format file -$15 SOS Screen library file -$16 SOS SOS reserved file type -$17 SOS SOS reserved file type -$18 SOS SOS reserved file type -$19 ADB ProDOS AppleWorks Database file -$1A AWP ProDOS AppleWorks WordProcessing file -$1B ASP ProDOS AppleWorks Spreadsheet file -$1C-$5F Reserved -$60-$6F ProDOS PC Transporter (Applied Engineering) reserved filetypes - $60 PRE ProDOS ProDOS preboot driver - $61-$6A ProDOS Reserved - $6B NIO ProDOS PC Transporter BIOS and drivers - $6C ProDOS Reserved - $6D DVR ProDOS PC Transporter device drivers - $6E ProDOS Reserved - $6F HDV ProDOS MSDOS HardDisk Volume -$70-$9F Reserved -$A0 WPF ProDOS WordPerfect document file -$A1 MAC ProDOS Macrofile -$A2 HLP ProDOS Help File -$A3 DAT ProDOS Data File -$A4 Reserved -$A5 LEX ProDOS Spelling dictionary -$A6-$AB Reserved -$AC ARC ProDOS General Purpose Archive file -$AD-$AF Reserved -$B0 SRC ProDOS ORCA/M & APW source file -$B1 OBJ ProDOS ORCA/M & APW object file -$B2 LIB ProDOS ORCA/M & APW library file -$B3 S16 ProDOS ProDOS16 system file -$B4 RTL ProDOS ProDOS16 runtime library -$B5 EXE ProDOS APW shell command file -$B6 STR ProDOS ProDOS16 startup init file -$B7 TSF ProDOS ProDOS16 temporary init file -$B8 NDA ProDOS ProDOS16 new desk accessory -$B9 CDA ProDOS ProDOS16 classic desk accessory -$BA TOL ProDOS ProDOS16 toolset file -$BB DRV ProDOS ProDOS16 driver file -$BC Reserved for ProDOS16 load file -$BD FST ??? -$BC Reserved for ProDOS16 load file -$BF DOC ProDOS document file -$C0 PNT ProDOS //gs paint document -$C1 SCR ProDOS //gs screen file -$C2 ANI ??? -$C3-$C7 Reserved -$C8 FNT ProDOS Printer font file -$C9 FND ProDOS finder files -$CA ICN ProDOS finder icons -$CB-$DF Reserved -$E0 LBR ProDOS Apple archive library file -$E1 Unknown (unlisted) -$E2 ATI ProDOS Appletalk init file -$E3-$EE Reserved -$EF PAS ProDOS ProDOS Pascal file -$F0 CMD ProDOS added command file -$F1-$F8 ProDOS User defined filetypes (popular ones include:) - $F1 OVL ProDOS Overlay file - $F2 DBF ProDOS Database file - $F3 PAD ProDOS MouseWrite file - $F4 MCR ProDOS AE Pro macro file - $F5 ECP ProDOS ECP batch file - $F6 DSC ProDOS description file - $F7 TMP ProDOS temporary work file - $F8 RSX ProDOS linkable object module -$F9 IMG ProDOS ProDOS image file -$FA INT ProDOS Integer BASIC program -$FB IVR ProDOS Integer BASIC variables file -$FC BAS ProDOS AppleSoft BASIC program -$FD VAR ProDOS AppleSoft BASIC variables file -$FE REL ProDOS ProDOS EDASM relocatable object module file -$FF SYS ProDOS ProDOS8 system file -*/ - =getopt.c -/* -* The official AT&T public domain version of getopt(3). -*/ -#include - -int optopt; /* For getopt */ -int opterr = 1; /* For getopt */ -int optind = 1; /* For getopt */ -char *optarg; /* For getopt */ - -#define ERR(s, c) \ - if (opterr) { \ - extern int strlen(), write(); \ - char errbuf[2]; \ - errbuf[0] = c; errbuf[1] = '\n';\ - (void) write(2, argv[0], (unsigned) strlen(argv[0])); \ - (void) write(2, s, (unsigned) strlen(s));\ - (void) write(2, errbuf, 2);\ - } - -int getopt(argc, argv, opstring) -int argc; -char **argv, - *opstring; -{ - static int sp = 1; - register int c; - register char *cp; - - if (sp == 1) - if (optind >= argc || - argv[optind][0] != '-' || - argv[optind][1] == '\0') - return (EOF); - else - if (strcmp(argv[optind], "--") == NULL) { - optind++; - return (EOF); - } - - optopt = c = argv[optind][sp]; - if (c == ':' || - (cp = strchr(opstring, c)) == NULL) { - ERR(": illegal option -- ", c); - if (argv[optind][++sp] == '\0') { - optind++; - sp = 1; - } - - return ('?'); - } - - if (*++cp == ':') { - if (argv[optind][sp+1] != '\0') - optarg = &argv[optind++][sp+1]; - else - if (++optind >= argc) { - ERR(": option requires an argument -- ", c); - sp = 1; - return ('?'); - } - else - optarg = argv[optind++]; - - sp = 1; - } - else { - if (argv[optind][++sp] == '\0') { - sp = 1; - optind++; - } - - optarg = NULL; - } - - return (c); - -} /* getopt */ - - -#if (0) -/* -* My own version of the UNIX getopt function for non-UNIX systems. It is not -* a fully functioning getopt but it will suffice for most anything -*/ -int getopt(argc, argv, opstring) -int argc; -char **argv, - *opstring; -{ - int option = -1, /* Option to be returned */ - index = 0, /* Index into opstring */ - get_args = 0, /* Boolean to flag arg val. */ - found = 0, /* Boolean flag found flag */ - loop; /* Loop counter for parsing */ - char flag = NULL; /* Flag/option to check for */ - - optarg = NULL; - - /* Check for no arguments */ - if (argc == 1) - return(option); - - if (argv[optind][0] != '-') - return(option); - - flag = opstring[index++]; - if (opstring[index] == ':') - get_args = 1; - - /* Scan 'next' argument until the last one */ - for (loop = optind; !found; ) { - if (flag == argv[loop][1]) { - if (get_args) - optarg = (char *) argv[loop] + 2; - - option = argv[loop][1]; - optind = loop + 1; - found = 1; - } - - if (!found) { - /* Didnt match so check next character in opstring */ - flag = opstring[index++]; - - /* Check to see if at end of opstring yet */ - if (flag == NULL) - return ('?'); - - if (opstring[index] == ':') - get_args = 1; - else - get_args = 0; - } - } /* for (loop = 1; loop < argc; loop++) */ - - return(option); - -} /* end getopt */ -#endif =unbit.c -/* - * unbit.c - * - * By Marcel J.E. Mol duteca!marcel - * marcel@duteca.tudelft.nl - * - * I hereby place this program into public domain ... - * ... all those all those if and whats etc.... - * I'm completely unresponsible for any damage this program may cause you, - * anyone, or anything else. - * - * - * Unbit expects a 6 bit encoding scheme of executioner output. - * Remove all stuff from the 'call -151' to 'F00G', and the last - * few lines containing the 'BSAVE ...' stuff. Fed the resulting - * ascii encoded data through unbit resulting in the binaru data. - * Thus each line in the input file should look something like this: - * - * 0A474CE30600AC02030053B2320F54B21E15020099030006444154452E430000 - * - * Usage: The program reads from a file or stdin, and outputs to - * stdout. I usually use the program as follows: - * - * unbit file.ex > file.blu - */ - -#include -#if defined(MSDOS) -# include -#endif - -char * copyright = "@(#) unbit.c 2.2 26/03/90 (c) M.J.E. Mol"; - -main(argc, argv) -int argc; -char **argv; -{ - FILE *fp; - - if ((argc == 1) || (!strcmp(argv[1], "-"))) { -#if defined(MSDOS) - setmode(fileno(stdout), O_BINARY); -#endif - fp = stdin; - } - else { -#if defined(MSDOS) - if ((fp = fopen(argv[1], "rb")) == NULL) { -#else - if ((fp = fopen(argv[1], "r")) == NULL) { -#endif - perror(argv[1]); - exit(1); - } - } - - unbit(fp); - - exit(0); - -} /* main */ - - - -unbit(fp) -FILE *fp; -{ - int c, co; - - while ((c = getc(fp)) != EOF) { - if ((c != ' ') && (c != '\n')) { - if ((c>='0') && (c<='9')) c-= '0'; - else if ((c>='a') && (c<='f')) c = c - 'a' + 10; - else if ((c>='A') && (c<='F')) c = c - 'A' + 10; - else fprintf(stderr, "illegal char %c\n",c); - co = c << 4; - c = getc(fp); - if ((c>='0') && (c<='9')) c-= '0'; - else if ((c>='a') && (c<='f')) c = c - 'a' + 10; - else if ((c>='A') && (c<='F')) c = c - 'A' + 10; - else fprintf(stderr, "illegal char %c\n",c); - co += c; - putchar(co); - } - } - -} /* unbit */ - =unexec.c - -/* - * unexec.c - * - * By Marcel J.E. Mol duteca!marcel - * marcel@duteca.tudelft.nl - * - * I hereby place this program into public domain ... - * ... all those all those if and whats etc.... - * I'm completely unresponsible for any damage this program may cause you, - * anyone, or anything else. - * - * - * Unexec expects a input file consisting of lines which are usually - * entered in the apple monitor. Remove the 'CALL -151' line from the file, - * and the 'BSAVE ..' at the end of the file. Fed the resulting data to - * unexec and binary data is output. When unexec has processed the file, - * it prints the address of the first and last databyte on stderr. The binary - * data contains all the bytes between the first and last address, even - * if no data was in the input file for a specific address (unexec just - * initializes a 64k byte array of zeros). - * Thus each line in the input file looks like: - * - * 01F0: A2 00 A0 10 A9 00 BD 00 20 E8 D0 FA - * - * Usage: The program reads from a file or stdin, and outputs to - * stdout. I usually use the program as follows: - * - * unexec file.ex > binfile - */ - -#include -#include -#if defined(MSDOS) -# include -#endif - -char * copyright = "@(#) unexec.c 2.2 26/03/90 (c) M.J.E. Mol"; - -unsigned char mem[65536]; -int addr; -int memmin, memmax; -int tmp; -int b; -unsigned char buf[128]; -int i; - - -main(argc, argv) -int argc; -char **argv; -{ - FILE *fp; - - if ((argc == 1) || (!strcmp(argv[1], "-"))) { -#if defined(MSDOS) - setmode(fileno(stdout), O_BINARY); -#endif - fp = stdin; - } - else { -#if defined(MSDOS) - if ((fp = fopen(argv[1], "rb")) == NULL) { -#else - if ((fp = fopen(argv[1], "r")) == NULL) { -#endif - perror(argv[1]); - exit(1); - } - } - - unexec(fp); - - exit(0); - -} /* main */ - - - -unexec(fp) -FILE *fp; -{ - addr = -1; - memmin = 100000; - memmax = 0; - tmp = 0; - while (fgets(buf, 128, fp) != NULL) { - i = 0; - while (i <= strlen(buf)) { - if (buf[i] == ':') { - addr = tmp; - if ((addr < memmin) && (addr >= 0)) - memmin = addr; - tmp = 0; - i++; - skipblank(); - } - else if ((isspace(buf[i])) || (buf[i] == '\0')) { - if (tmp > 255) - fprintf(stderr, "Assuming %d to be $FF\n", tmp); - mem[addr++] = tmp; - tmp = 0; - skipblank(); - } - else { - if ((buf[i] >= '0') && (buf[i] <= '9')) - tmp = (tmp << 4) + buf[i] - '0'; - else if ((buf[i] >= 'a') && (buf[i] <= 'f')) - tmp = (tmp << 4) + buf[i] - 'a' + 10; - else if ((buf[i] >= 'A') && (buf[i] <= 'F')) - tmp = (tmp << 4) + buf[i] - 'A' + 10; - else fprintf(stderr, "Illegal character %c\n", buf[i]); - i++; - } - } - if (addr > memmax) - memmax = addr; - } - for (i = memmin; i<= memmax; i++) - putchar(mem[i]); - fprintf(stderr, "Lower address: %x\n", memmin); - fprintf(stderr, "Higher address: %x\n", memmax); - -} /* unexec */ - - - -skipblank() -{ - - while ((isspace(buf[i]) || (buf[i] == '\0')) && i <= strlen(buf)) - i++; - -} /* skipblank */ - =usq.c - -/* - * usq.c - * - * By Marcel J.E. Mol duteca!marcel - * marcel@duteca.tudelft.nl - * - * I hereby place this program into public domain ... - * ... all those all those if and whats etc.... - * I'm completely unresposible for any damage this program may cause you. - * - * Usq unsqueezes a file squeezed with the apple sq3 program. - * Files extracted from a binary 2 file (using unblu for example) - * with a .QQ or .Q extensing are probably squeezed files. - * - * Usage: The program reads from a file or stdin, and outputs to - * the filename stored in the squeezed file. - * So use the program as follows: - * - * usq file.QQ - * - * Remember that the newline character on apple is different from Unix. - * Thus files extracted with unblu, and possibly unsqueezed with usq - * may have an ^M character instead of a \n character at the end of each line. - * To create a proper Unix file use the following 'tr' command: - * - * tr '\015' '\012' < applefile > unixfile - * - * This program is based on the unsqueeze program in the unix/PC - * ARC utility. - */ - -/* - * Squeezed file format: - * 2 bytes MAGIC - * 2 bytes dummy ??? - * filename ended by \0 - * 2 bytes node count - * node count node values, each 2 bytes - * squeezed data per byte - */ - -#include -#if defined(MSDOS) -# include -#endif - -#define BUFSIZE 128 -#define MAGIC 0xff76 /* Squeezed file magic */ -#define DLE 0x90 /* repeat byte flag */ -#define NOHIST 0 /* no relevant history */ -#define INREP 1 /* sending a repeated value */ -#define SPEOF 256 /* special endfile token */ -#define NUMVALS 257 /* 256 data values plus SPEOF */ - -char * copyright = "@(#) usq.c 2.1 18/06/88 (c) M.J.E. Mol"; - -/* - * Global variable declarations - */ -char *progname; -char *sfn; /* squeezed file name */ -struct nd { /* decoding tree */ - int child[2]; /* left, right */ -} node[NUMVALS]; /* use large buffer */ -int state; /* repeat unpacking state */ -int bpos; /* last bit position read */ -int curin; /* last byte value read */ -int numnodes; /* number of nodes in decode tree */ - - -/* - * Functions declarations - */ -void main (); -int unsqueeze (); -void putc_ncr (); -int get_int (); -int init_usq (); -int getc_usq (); - - - -void main(argc, argv) -int argc; -char ** argv; -{ - - FILE *fp; /* File pointer for squeezed file */ - register int r = 0; /* Exit value */ - - progname = *argv; - - if (argc == 1) { /* no args; unsqueeze standard input */ -#if defined(MSDOS) - setmode(fileno(stdin), O_BINARY); -#endif - unsqueeze(stdin); - } - else /* unsqueeze each file in arglist */ - while (--argc > 0) { - sfn = *++argv; -#if defined(MSDOS) - if ((fp = fopen(sfn, "rb")) == NULL) { -#else - if ((fp = fopen(sfn, "r")) == NULL) { -#endif - perror(sfn); - continue; - } - r |= unsqueeze(fp); - fclose(fp); - } - - exit(r); - -} /* main */ - - - -int unsqueeze(sfp) -FILE *sfp; -{ - register int i; - register int c; /* one char of stream */ - char fname[BUFSIZE]; - int magic; - register FILE *dfp; - - magic = get_int(sfp); -#if defined(DEBUG) - fprintf(stderr, "Magic number: %x\n", magic); -#endif - if (magic != MAGIC) { /* Check magic number */ - fprintf(stderr, "%s: %s not a squeezed file\n", progname, sfn); - fprintf(stderr, "Wrong magic number: %x\n", magic); - return(1); - } - (void) get_int(sfp); /* two dummy bytes ??? */ - i = 0; /* get the original file name */ - while ((fname[i++] = getc(sfp)) != NULL) - ; - -#if defined(MSDOS) /* open destination file */ - if ((dfp = fopen(fname, "wb")) == NULL) { -#else - if ((dfp = fopen(fname, "w")) == NULL) { -#endif - perror(fname); - return(1); - } - - state = NOHIST; /* initial repeat unpacking state */ - - if (init_usq(sfp)) /* init unsqueeze algorithm */ - return 1; - while ((c=getc_usq(sfp)) != EOF) /* and unsqueeze file */ - putc_ncr(c, dfp); - - return 0; /* file is okay */ - -} /* unsqueeze */ - - - - -/* putc-ncr -- decode non-repeat compression. Bytes are passed one - * at a time in coded format, and are written out uncoded. - * The data is stored normally, except that runs of more - * than two characters are represented as: - * - * - * - * With a special case that a count of zero indicates a DLE - * as data, not as a repeat marker. - */ -void putc_ncr(c, t) /* put NCR coded bytes */ -unsigned char c; /* next byte of stream */ -FILE *t; /* file to receive data */ -{ - static int lastc; /* last character seen */ - - switch (state) { /* action depends on our state */ - case NOHIST: /* no previous history */ - if (c==DLE) /* if starting a series */ - state = INREP; /* then remember it next time */ - else putc(lastc=c, t); /* else nothing unusual */ - return; - - case INREP: /* in a repeat */ - if (c) /* if count is nonzero */ - while (--c) /* then repeatedly ... */ - putc(lastc, t); /* ... output the byte */ - else putc(DLE, t); /* else output DLE as data */ - state = NOHIST; /* back to no history */ - return; - - default: - fprintf(stderr, "%s: bad NCR unpacking state (%d)", - progname, state); - } - -} /* putc_ncr */ - - - - -int get_int(f) /* get an integer */ -FILE *f; /* file to get it from */ -{ - - return getc(f) | (getc(f) << 8); - -} /* get_int */ - - - -int init_usq(f) /* initialize Huffman unsqueezing */ -FILE *f; /* file containing squeezed data */ -{ - register int i; /* node index */ - - bpos = 99; /* force initial read */ - - numnodes = get_int(f); /* get number of nodes */ - - if (numnodes<0 || numnodes>=NUMVALS) { - fprintf(stderr, "%s: %s file has an invalid decode tree", - progname, sfn); - return 1; - } - - /* initialize for possible empty tree (SPEOF only) */ - - node[0].child[0] = -(SPEOF + 1); - node[0].child[1] = -(SPEOF + 1); - - for (i=0; i=0); )/* work down(up?) from root */ - { - if (++bpos > 7) { - if ((curin=getc(f)) == EOF) - return(EOF); - bpos = 0; - - /* move a level deeper in tree */ - i = node[i].child[1 & curin]; - } - else i = node[i].child[1 & (curin >>= 1)]; - } - - /* decode fake node index to original data value */ - i = i | 0xffff0000; /* Unix hack: have 32 bits instead of 16 */ - i = -(i + 1); - - - /* decode special endfile token to normal EOF */ - return ((i==SPEOF) ? EOF : i); - -} /* getc_usq */ + END OF ARCHIVE Submitted-by: marcel@duteca.tudelft.nl Posting-number: Volume 1, Source:28 Archive-name: archive/unix/marcel/part2 Architecture: UNIX Version-number: 1.00 This is part 2 of a 2 part posting. =sciibin.c -/* @(#) sciibin.c 3.01 12Feb91 */ -/************************************************************************* - ** ** - ** Name : sciibin ** - ** Author : Marcel J.E. Mol ** - ** Date : 06Mar89 (first release) ** - ** Version : 2.00 ** - ** Files : sciibin.c Main source file ** - ** Purpose : Extract or view BinSCII files ** - ** ** - ** ------------------------- Revision List ------------------------- ** - ** Ver Date Name Remarks ** - ** 1.00 06Mar89 Marcel Mol First release ** - ** 1.10 27Mar89 Marcel Mol Fished things up, error routine, ** - ** linecount, all info fields filled ** - ** in, changed info layout. ** - ** 2.00 03Jun89 Marcel Mol Bug fixes: alphabet to unsigned ** - ** (Dave Whitney) char. Some OS's need types.h. ** - ** Fixed CRE/MOD order. ** - ** Output filenames can be wrong ** - ** when multiple files are ** - ** extracted. Made crc and file- ** - ** type arrays in seperate includes ** - ** 3.00 22Mar90 Marcel Mol Includeed ports of Bruce Kahn ** - ** 1.30 27 Feb 90 Bruce Kahn Ported to AOS/VS C 4.01 and MSC 5.1 ** - ** Added explicit long definitions ** - ** needed. ** - ** Redid layouts for dates to be US. ** - ** Modified the open routines for MSC ** - ** to include binary mode, not text. ** - ** Changed the way 8 bit integers are ** - ** handled (redone MM). ** - ** Added getopt() (see below MM). ** - ** 3.01 22Feb91 Marcel Mol Fixed bug: only close output ** - ** when output is generated. ** - ** ================================================================= ** - ** ** - ** Compile as follows: ** - ** If you don't have getopt, compile and link the given getopt.c ** - ** ** - ** UNIX: cc sciibin.c -Oso sciibin ** - ** ** - ** MSC 5.1: cl /c /Ox sciibin.c ** - ** (add /DMSDOS, if MSC didn't do it) ** - ** link /CO /STACK:10000 sciibin; ** - ** ** - ** AOS/VS: cc sciibin.c ** - ** ccl sciibin ** - ** ** - ** Defining DEBUG gives some debug information. ** - ** Defining DEBUGALL gives input and output of the decode routine. ** - ** ** - ** Usage: sciibin [-hvtc] [-o] ** - ** ** - ** -v show only info on file, do not create output. ** - ** -t test file, do not create output. ** - ** -c do not check checksums. ** - ** -o create given filename instead of the one in ** - ** binscii file. Use this only if the input files ** - ** contain only one output file. ** - ** -h help. ** - ** ** - ** ** - ** This software is freeware. We can not be held responsible to ** - ** any damage this program may coase you or anyone or anything else. ** - ** ** - ** Mail bugs to: marcel@duteca.tudelft.nl ** - ** ** - ************************************************************************/ - - -#include -#include /* keep sun OS happy */ -#include /* mostly includes types.h ... */ -#if defined(MSDOS) -#include /* For the memset function */ -#endif -#include "crc.h" -#include "filetype.h" - -#define BUFLEN 256 -#define FILENAME_LEN 15 -#define BINSCII_HEADER "FiLeStArTfIlEsTaRt\n" -#define MAXSEGLEN 0x3000 - -#if defined(INT8) -typedef long int16; -#else -typedef int int16; -#endif - -/* ==> Expect int variables to be at least 16 bits - * Global variables ==> and longs to be at least 32 bits - * ==> If not, you have some work to do... - */ /* MSDOS has 16 bit ints. */ -char buf[BUFLEN+1]; -unsigned char dec[BUFLEN+1]; -unsigned char alphabet[BUFLEN+1]; /* need $FF in alphabet */ -char outfilename[BUFLEN+1]; - - -unsigned char outflag = 0, /* the -o option */ - crcflag = 0, /* the -c option */ - infoflag = 0, /* the -v option */ - testflag = 0, /* the -t option */ - makeoutput, /* ! (-t | -v) */ - crcok; /* -t | -c */ -FILE *outfp; /* output file */ - -unsigned char filetype, stortype, - file_access; /* access -> file_access for MSDOS */ -unsigned char modyear, modmonth, modday, modhour, modmin, - creyear, cremonth, creday, crehour, cremin; -int namlen, linecount, - numblocks, auxtype; -long filesize, startbyte, segmentlen; -char * infilename; - -char * progname; - - -/* - * function declarations - */ -int main (); -int sciibin (); -int getheader (); -int decode (); -int decodestring (); -char *myfgets (); -void usage (); -void error (); - - -char * copyright = "@(#) sciibin.c 3.01 12Feb91 (c) 1989, 1991 M.J.E. Mol"; - -main(argc, argv) -int argc; -char **argv; -{ - FILE *fp; - int c; - extern int optind; /* For getopt */ - extern char * optarg; /* For getopt */ - int flag; /* Flag for getopt */ - - progname = *argv; - - while ((flag = getopt(argc, argv, "hvcto:")) != EOF) { /* Process options */ - switch (flag) { - case 'v': infoflag = 1; /* Want only info of file */ - break; - case 'h': usage(); /* Give help */ - exit(0); - case 'c': crcflag = 1; - break; - case 't': testflag = 1; - break; - case 'o': -#if defined(MSDOS) - memset(outfilename, NULL, FILENAME_LEN + 1); -#endif - strcpy(outfilename, optarg); - outflag = 1; - break; - default : fprintf(stderr, "%s: skipping unkown flag %c, use -h.\n", - progname, flag); - break; - } - } - - makeoutput = !(testflag | infoflag); - crcok = testflag | crcflag; - -#if defined(DEBUG) - fprintf(stderr, "make output: %d, crcok: %d\n", makeoutput, crcok); -#endif - - if (optind >= argc) { /* No files given, use stdin */ - infilename = "stdin"; - linecount = 0; - sciibin(stdin); - } - else - while (optind < argc) { - infilename = argv[optind]; - optind++; - if ((fp = fopen(infilename, "r")) == NULL) { - perror(infilename); - continue; - } - linecount = 0; - sciibin(fp); - fclose(fp); - } - - exit(0); - -} /* main */ - - - -/* - * Walk over the file processing all segments in it - */ -sciibin(fp) -FILE *fp; -{ - int processed = 0; /* number of processed binscii segments */ - int status = 0; /* return codes of calls to decode */ - - while (myfgets(buf, BUFLEN, fp) != NULL) { - -#if defined(DEBUG) - fprintf(stderr, "(%s) get start:%s", infilename, buf); -#endif - - if (!strncmp(buf, BINSCII_HEADER, strlen(BINSCII_HEADER))) { - if (!getheader(fp) && !infoflag) /* if header ok and not -v flag */ - status |= decode(fp); - processed++; - } - } - - if (processed == 0) { - error("not a BinSCII file"); - return 1; - } - - return status; - -} /* sciibin */ - - - -/* - * Build the alphabet, get the output file info and open output file - * if necessary. - * Still contains lots of debug code to find out the header structure. - * (every bit is known now...) - */ -getheader(fp) -FILE *fp; -{ - register int i, j; - register int16 crc = 0; - struct stat statbuf; /* MUST know if file exists */ - char *iomod; /* write or readwrite a file */ - - /* - * Get the alphabet - */ - if (myfgets(buf, BUFLEN, fp) == NULL) { - error("reading alphabet: unexpected end of file"); - return 1; - } - -#if defined(DEBUG) - fprintf(stderr, "(%s) alphabet:%s", infilename, buf); -#endif - - if (strlen(buf) != 65) { - error("alphabet corrupted"); - return 1; - } - - /* - * Process the alphabet - */ - for (i = 0; i < BUFLEN; i++) - alphabet[i] = 0xff; - - for (i = 0; i < 64; i++) { - j = buf[i]; - if (alphabet[j] != 0xff) - error("Warning: double character in alphabet"); - alphabet[j] = i; - } - -#if defined(DEBUG) - for (i = 0; i < BUFLEN; i+=16) { - fprintf(stderr, "(%s) alphabet[%3d] =", infilename, i); - for (j = 0; j < 16; j++) - fprintf(stderr, " %02X", alphabet[i+j]); - putc('\n', stderr); - } -#endif - - /* - * Get the file header - */ - if (myfgets(buf, BUFLEN, fp) == NULL) { - error("reading fileheader: unexpected end of file"); - return 1; - } - -#if defined(DEBUG) - fprintf(stderr, "(%s) fileheader:%s", infilename, buf); -#endif - - /* - * Extract output filename if needed - */ - if (!outflag) { - namlen = *buf - 'A' + 1; /* IS +1 NEEDED ?? */ -#if defined(MSDOS) - memset(outfilename, NULL, FILENAME_LEN + 1); -#endif - strncpy(outfilename, buf+1, namlen); - outfilename[namlen] = '\0'; - } - -#if defined(DEBUG) - fprintf(stderr, "(%s) filename:**%s**\n", infilename, outfilename); - fprintf(stderr, "(%s) fileinfo:**%s**", infilename, buf+16); -#endif - - /* - * Decode and process the file header information - */ - if ((i = decodestring(buf+FILENAME_LEN+1, dec)) != 27) - error("warning: corrupted file header length"); - - for (i = 0; i < 24; i++) - crc = updcrc(dec[i], crc); - - if (crc != (dec[24] | (dec[25] << 8))) { - if (crcok) - error("warning: CRC error in file header"); - else { - error("error: CRC error in file header"); - return 1; - } - } - - /* Calculate file length */ - filesize = dec[0] + (dec[1]<<8) + ((long) dec[2]<<16); - startbyte = dec[3] + (dec[4]<<8) + ((long) dec[5]<<16); - - /* Calculate file attributes and size */ - file_access= dec[6]; - filetype = dec[7]; - auxtype = dec[8] + (dec[9] << 8); - stortype = dec[10]; - numblocks = dec[11] + (dec[12]<<8); - - /* Calculate creation and modification dates */ -#define MOD 13 -#define CRE 17 /* perhaps creation and modification date are swapped */ - creday = dec[CRE] & 0x1f; - cremonth = ((dec[CRE+1] & 0x01) << 3) | (dec[CRE] >> 5); - creyear = dec[CRE+1] >>1; - cremin = dec[CRE+2] & 0x3f; - crehour = dec[CRE+3] & 0x1f; - modday = dec[MOD] & 0x1f; - modmonth = ((dec[MOD+1] & 0x01) << 3) | (dec[MOD] >> 5); - modyear = dec[MOD+1] >>1; - modmin = dec[MOD+2] & 0x3f; - modhour = dec[MOD+3] & 0x1f; - - segmentlen = dec[21] + (dec[22]<<8) + ((long) dec[23]<<16); - if (segmentlen > MAXSEGLEN) - error("warning: segmentlen probably to long"); - -#define READ 0x01 -#define WRITE 0x02 -#define BACKUP 0x20 -#define RENAME 0x40 -#define DESTROY 0x80 - - if (infoflag) { - - /* Display the files name, type and auxtype */ - printf("%-15s %3s aux: $%04X ", - outfilename, filetypes[filetype], auxtype); - - /* Display the file access type */ - putchar(file_access & READ ? 'r' : '-'); - putchar(file_access & WRITE ? 'w' : '-'); - putchar(file_access & RENAME ? 'n' : '-'); - putchar(file_access & DESTROY ? 'd' : '-'); - putchar(file_access & BACKUP ? 'b' : '-'); - - /* Display the type of file this is - ProDOS Specific */ - switch (stortype) { - case 0x0F : printf(" voldir"); break; - case 0x0D : printf(" dir"); break; - case 0x01 : printf(" seed"); break; - case 0x02 : printf(" sap"); break; - case 0x03 : printf(" tree"); break; - default : printf(" ???"); break; - } - - /* Display modification and creation information */ - printf(" %02d/%02d/%02d(%02d:%02d) -", modmonth, modday, modyear, - modhour, modmin); - printf(" %02d/%02d/%02d(%02d:%02d)\n", cremonth, creday, creyear, - crehour, cremin); - - /* Display segment information */ - printf("Part %4d of %4d,", (int) (startbyte / MAXSEGLEN) + 1, - (int) ((filesize + MAXSEGLEN-1) / MAXSEGLEN)); - printf(" bytes %7ld to %7ld of %7ld bytes, %5d blocks\n", - startbyte, startbyte+segmentlen, filesize, numblocks); - - } /* if (infoflag) */ - - if (makeoutput) { - /* will creating output, not just information so verify the access */ -#if defined(MSDOS) - iomod = (stat(outfilename, &statbuf) == 0) ? "r+b" : "wb"; -#else - iomod = (stat(outfilename, &statbuf) == 0) ? "r+" : "w"; -#endif - if ((outfp = fopen(outfilename, iomod)) == NULL) { - error("unable to open output file"); - perror(outfilename); - return 1; - } - fseek(outfp, startbyte, 0); - } /* if (makeoutput) */ - - return 0; - -} /* getheader */ - - - -/* - * Do the actual decoding of the bin data. - */ -decode(fp) -FILE *fp; -{ - register int i; - register int crc = 0; - int len; - - crc = 0; - while (segmentlen > 0) { - if (myfgets(buf, BUFLEN, fp) == NULL) { - error("reading file: unexpected end of file"); - return 1; - } - -#if defined(DEBUG) - fprintf(stderr, "(%s) data:%s", infilename, buf); -#endif - - if ((len = decodestring(buf, dec)) != 48) - error("warning: corrupted line length"); - for (i = 0; i < 48; i++) - crc = updcrc(dec[i], crc); - if (makeoutput) - for (i = 0; (i < len) && (segmentlen > 0); i++, segmentlen--) - putc(dec[i], outfp); /* COULD CR/NL TXT FILES */ - else - segmentlen -= len; - -#if defined(DEBUG) - fprintf(stderr, "(%s) still need %d bytes\n", infilename, segmentlen); -#endif - - } - - /* - * must be at end of segment now, with one remaining line containing - * the crc check. - */ - if (myfgets(buf, BUFLEN, fp) == NULL) { - error("reading file crc: unexpected end of file"); - return 1; - } - -#if defined(DEBUG) - fprintf(stderr, "(%s) crc:%s", infilename, buf); -#endif - - if ((len = decodestring(buf, dec)) != 3) - error("warning: corrupted crc length"); - if (crc != (dec[0] | (dec[1] << 8))) { - if (crcok) - error("warning: CRC error in file data"); - else { - error("error: CRC error in file data"); - return 1; - } - } - - if (makeoutput) - fclose(outfp); - - return 0; - -} /* decode */ - - -/* - * Decode one string off scii characters to binary data, meanwhile - * calculating crc. - */ -decodestring(in, out) -register char *in; -register unsigned char *out; -{ - register int len = 0; - -#if defined(DEBUGALL) - char *b; - - fprintf(stderr, "(%s) decode in: %s\n", infilename, in); - b = in; - while (*b) - fprintf(stderr, ".%02X", alphabet[*b++]); - putc('\n', stderr); - b = out; -#endif - - while (strlen(in) > 3) { - *out++ = ((alphabet[in[3]] << 2) | (alphabet[in[2]] >> 4)) & 0xFF; - *out++ = ((alphabet[in[2]] << 4) | (alphabet[in[1]] >> 2)) & 0xFF; - *out++ = ((alphabet[in[1]] << 6) | (alphabet[in[0]])) & 0xFF; - len += 3; - in += 4; - } - - *out = '\0'; - if (*in != '\0' && *in != '\n') - error("warning: line not ended by NULL or NEWLINE"); - -#if defined(DEBUGALL) - fprintf(stderr, "(%s) decode out:\n", infilename); - while (b != out) - fprintf(stderr, ".%02X", *b++); - putc('\n', stderr); -#endif - - return len; - -} /* decodestring */ - - - -char *myfgets(buf, len, fp) -char *buf; -int len; -FILE *fp; -{ - - linecount++; - - return fgets(buf, len, fp); - -} /* myfgets */ - - - -void usage() -{ - - fprintf(stderr, "%s\n\n", copyright); - fprintf(stderr, "Usage: sciibin [-vtch] [-o] \n\n"); - fprintf(stderr, " -v show only info on file, do not create output.\n"); - fprintf(stderr, " -t test file, do not create output.\n"); - fprintf(stderr, " -c do not check checksums.\n"); - fprintf(stderr, " -o create given filename instead of the one in\n"); - fprintf(stderr, " binscii file. Use this only if the input files\n"); - fprintf(stderr, " contain only one output file.\n"); - fprintf(stderr, " -h this help message.\n"); - -} /* usage */ - - - -void error(str) -char *str; -{ - - fprintf(stderr, "%s (%s, %d): %s\n", - progname, infilename, linecount, str); - -} /* error */ - =unblu.c -/* @(#) unblu.c 2.2 18/06/89 */ -/************************************************************************* - ** ** - ** Name : unblu ** - ** Author : Marcel J.E. Mol ** - ** Date : 10/05/88 (first release) ** - ** Version : 2.20 ** - ** Files : unblu.c Main source file ** - ** ** - ** ------------------------- Revision List ------------------------- ** - ** Ver Date Name Remarks ** - ** 1.00 10/05/88 Marcel Mol Raw copy of a basic program** - ** 2.00 03/06/88 Marcel Mol Rewrite after blu info ** - ** was send to the net ** - ** 2.10 18/06/88 Marcel Mol Added filetype texts ** - ** 2.20 23/09/88 Marcel Mol Show mod and creation time ** - ** ** - ** ================================================================= ** - ** ** - ** Compile as follows: cc unblu.c -Oso unblu ** - ** ** - ** Usage: unblu [-vh] [] ** - ** ** - ************************************************************************/ - - /************************************************************************ - ** ** - ** NAME ** - ** unblu - Extract files from an apple binary ][ archive. ** - ** ** - ** ** - ** SYNOPSIS ** - ** unblu [-vh] arcfile [files-to-extract] ** - ** ** - ** ** - ** DESCRIPTION ** - ** Unblu list the contents of a binary ][ archive (the -v option) ** - ** or extracts the listed files from the archive (without the ** - ** -v option). If no files are listed, the comlete archive is ** - ** extracted or listed. ** - ** The -h option gives a help message on the usage of unblu. ** - ** ** - ** AUTHOR ** - ** Marcel J.E. Mol ** - ** ** - ** BUGS ** - ** Mail bugs to: marcel@duteca.tudelft.nl ** - ** ** - ************************************************************************/ - -char * copyright = "@(#) unblu.c 2.2 18/06/89 (c) M.J.E. Mol"; -#include -#include -#include "filetype.h" - -#define BUFSIZE 128 /* Blu block length */ -#define DEBUG - -/* Global variables */ -char * progname; -char * blufile; -int verbose = 0; - - -/* Function declarations */ -void main (); -void unblu (); -void process_file (); -void extract_file (); -void print_global_info (); -int want (); -void usage (); -void printhelp (); - - -void main(argc, argv) -int argc; -char ** argv; -{ - int flag; /* Flag for getopt */ - int bfd; /* File descriptor for blu file */ - extern int optind; /* For getopt */ - extern char * optarg; /* For getopt */ - - progname = argv[0]; - while ((flag = getopt(argc, argv, "vh")) != EOF) { /* Process options */ - switch (flag) { - case 'v': verbose = 1; /* Want only listing of archive */ - break; - case 'h': usage(); /* Give help */ - printhelp(); - exit(0); - default : fprintf(stderr, "%s: skipping unkown flag %c.\n", - progname, flag); - break; - } - } - - if (optind >= argc) { /* No archive given */ - usage(); - exit(1); - } - - blufile = argv[optind++]; /* Get archive name */ - if ((bfd = open(blufile, O_RDONLY)) == -1) { - perror(blufile); - exit(2); - } - - unblu(bfd, &argv[optind]); /* Process wanted files */ - - close(bfd); - - exit(0); - -} /* main */ - - -/* - * unblu -- process a binary II file fd, and process the filenames - * listed in wated. If wanted is \0, all files are processed. - */ -void unblu(fd, wanted) -int fd; -char ** wanted; -{ - unsigned char buf[BUFSIZE]; - int firstblock = 1; /* First block needs special processing */ - int tofollow = 1; /* Files to follow in the archive */ - int n; - - while (tofollow && ((n = read(fd, buf, BUFSIZE)) != -1)) { - /* If there is a header block */ - if (n != BUFSIZE) { - fprintf(stderr, "%s: %s file size is broken\n", progname, blufile); - exit(1); - } - if ((buf[0] != 10) || (buf[1] != 71) || - (buf[2] != 76) || (buf[18] != 2)) { - fprintf(stderr, "%s: %s not a binary II file\n", progname, blufile); - exit(1); - } - tofollow = buf[127]; /* How many files to follow */ - if (firstblock && verbose) { - print_global_info(buf); - firstblock = 0; - } - process_file(fd, buf, wanted); /* process the file for it */ - } - return; - -} /* unblu */ - - -/* - * process_file -- retrieve or print file information of file given - * in buf - */ -void process_file(fd, buf, wanted) -int fd; -unsigned char * buf; -char ** wanted; -{ - int tf; - int ftype; - int dflags; - int fnamelen; - int filelen; - char fname[64]; - int nblocks; - int modyear, modmonth, modday; - int creyear, cremonth, creday; - int modhour, modsec; - int crehour, cresec; - - /* - * Get fileinfo - */ - ftype = buf[4]; /* File type */ - fnamelen = buf[23]; /* filename */ - strncpy(fname, &buf[24], fnamelen); - fname[fnamelen] = '\0'; - dflags = buf[125]; /* Data flags */ - tf = buf[127]; /* Number of files to follow */ - filelen = buf[20] + (buf[21]<<8) + (buf[22]<<16);/* Calculate file length */ - nblocks = (filelen + BUFSIZE-1) / BUFSIZE; - modyear = buf[11] >>1; - modday = buf[10] & 0x1f; - modmonth= ((buf[11] & 0x01) << 3) + (buf[10] >> 5); - modhour = buf[13] & 0x1f; - modsec = buf[12] & 0x3f; - creyear = buf[15] >>1; - creday = buf[14] & 0x1f; - cremonth= ((buf[15] & 0x01) << 3) + (buf[14] >> 5); - crehour = buf[17] & 0x1f; - cresec = buf[16] & 0x3f; - - - if (*wanted == NULL || want(fname, wanted)) { - if (verbose) { /* print file information */ - printf("%-15s %3s", fname, filetypes[ftype]); - printf(" %02d/%02d/%02d(%02d:%02d)", modyear, modmonth, modday, - modhour, modsec); - printf(" - %02d/%02d/%02d(%02d:%02d)", creyear, cremonth, creday, - crehour, cresec); - printf(" %5d bytes ", filelen); - if (dflags == 0) - printf("stored"); - else { - if (dflags & 128) { - printf("squeezed"); - } - if (dflags & 64) { - printf("encrypted"); - } - if (dflags & 1) - printf("packed"); - } - putchar('\n'); - - if (ftype != 15) /* If not a directory */ - lseek(fd, BUFSIZE*nblocks, 1); /* Seek to next file */ - } - else if (ftype != 15) - extract_file(fd, fname, filelen); - } - else if (ftype != 15) /* If not a directory */ - lseek(fd, BUFSIZE*nblocks, 1); /* Seek to next file */ - - return; - -} /* process_file */ - - -/* - * extract_file -- extract file fname from the archive fd. Fname - * comtains filelen bytes. - */ -void extract_file(fd, fname, filelen) -int fd; -char * fname; -int filelen; -{ - int ofd; - int n; - unsigned char buf[BUFSIZE]; - - printf("x - %s\n", fname); - if ((ofd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) { - /* Open (PRODOS) file */ - perror(fname); - exit(1); - } - - while (filelen > 0) { - if ((n = read(fd, buf, BUFSIZE)) != BUFSIZE) { /* Read 128 bytes */ - fprintf(stderr, "%s: %s file size is broken\n", progname, blufile); - exit(1); - } - write(ofd, buf, (filelen >= BUFSIZE ? BUFSIZE : filelen)); - filelen -= BUFSIZE; - } - - close(ofd); /* Close (PRODOS) file */ - return; - -} /* extract_file */ - - - -/* - * print_global_info -- print global information of the binary II file - */ -void print_global_info(buf) -unsigned char * buf; -{ - int disk_blocks; - - disk_blocks = buf[117] + (buf[118]<<8) + (buf[119]<<16) + (buf[120]<<24); - printf("%s, by Blu %d, ", blufile, buf[126]); - printf("%d files, using %d blocks\n", buf[127]+1, disk_blocks); - return; - -} /* print_global_info */ - - - -/* - * want -- return 1 if name exists in array wantlist, - * else return 0 - */ -want(name, wantlist) -char * name; -char ** wantlist; -{ - while (*wantlist != NULL) { - if (strcmp(name, *wantlist++) == NULL) - return(1); - } - return(0); - -} /* want */ - - - -void usage() -{ - fprintf(stderr, "usage: %s [-hv] [ ...]\n", - progname); - return; - -} /* usage */ - - - -void printhelp() -{ - fprintf(stderr, "\t-h show this help.\n"); - fprintf(stderr, "\t-v show contents of archive.\n"); -} + END OF ARCHIVE