#ifdef TYPES_H #include #endif /* TYPES_H */ #include #include "globals.h" #include "crc.h" #include "readline.h" #include "../util/masks.h" #include "../util/util.h" #include "../util/patchlevel.h" #include "../fileio/wrfile.h" #include "../fileio/wrfileopt.h" #include "../fileio/machdr.h" #include "../fileio/kind.h" #include "../util/curtime.h" #include "hexbin.h" #define LOCALOPT "ilvcn:qVH" extern void exit(); extern void backtrans(); #ifdef DL extern void dl(); #endif /* DL */ #ifdef HECX extern void hecx(); #endif /* HECX */ #ifdef HQX extern void hqx(); #endif /* HQX */ #ifdef MU extern void mu(); #endif /* MU */ static void usage(); static void do_files(); static int find_header(); static char options[128]; int main(argc, argv) int argc; char **argv; { char *filename; char macname[32]; extern int optind; extern char *optarg; int errflg; int c; set_wrfileopt(0); (void)strcat(options, get_wrfileopt()); (void)strcat(options, LOCALOPT); errflg = 0; filename = ""; macname[0] = 0; while((c = getopt(argc, argv, options)) != EOF) { if(!wrfileopt((char)c)) { switch(c) { case 'l': listmode++; break; case 'v': verbose++; break; case 'i': info_only++; break; case 'c': uneven_lines++; break; case 'n': backtrans(macname, optarg); break; case '?': errflg++; break; case 'H': give_wrfileopt(); (void)fprintf(stderr, "Hexbin specific options:\n"); (void)fprintf(stderr, "-i:\tgive information only, do not convert\n"); (void)fprintf(stderr, "-l:\tgive listing\n"); (void)fprintf(stderr, "-v:\tgive verbose listing, including lines skipped\n"); (void)fprintf(stderr, "-c:\tdo not check for equal line lengths\n"); (void)fprintf(stderr, "-n nm:\tname to be generated\n"); (void)fprintf(stderr, "-V:\tgive information about this version\n"); (void)fprintf(stderr, "-H:\tthis message\n"); (void)fprintf(stderr, "Default is silent conversion\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, "Hexified files recognized:\n"); #ifdef DL (void)fprintf(stderr, "\tDownload (.dl)\n"); #endif /* DL */ #ifdef HECX (void)fprintf(stderr, "\tBinHex 2.0 (.hex)\n"); (void)fprintf(stderr, "\tBinHex 3.0 (.hcx)\n"); #endif /* HECX */ #ifdef HQX (void)fprintf(stderr, "\tBinHex 4.0 (.hqx)\n"); #endif /* HQX */ #ifdef MU (void)fprintf(stderr, "\tUUTool (.mu)\n"); #endif /* MU */ exit(0); } } } if(errflg) { usage(); exit(1); } if(info_only || verbose) { listmode++; } do { if(optind == argc) { filename = "-"; } else { filename = argv[optind]; optind++; #ifdef SCAN do_idf(filename, UNIX_NAME); #endif /* SCAN */ } do_files(filename, macname); } while(optind < argc); exit(0); /* NOTREACHED */ } static char *extensions[] = { #ifdef DL ".dl", #endif /* DL */ #ifdef HECX ".hex", ".Hex", ".hcx", ".Hcx", #endif /* HECX */ #ifdef HQX ".hqx", ".Hqx", #endif /* HQX */ #ifdef MU ".mu", #endif /* MU */ "", NULL }; static void do_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; int qformat; int again; if(filename[0] == '-') { ifp = stdin; filename = "stdin"; } else { /* find input file and open it */ for(ep = extensions; *ep != NULL; ep++) { (void)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); } } again = 0; nexttry: if(ifp == stdin) { curtime = (long)time((time_t *)0) + TIMEDIFF; mh.m_createtime = curtime; mh.m_modifytime = curtime; } else { mh.m_createtime = stbuf.st_mtime + TIMEDIFF; mh.m_modifytime = stbuf.st_mtime + TIMEDIFF; } qformat = find_header(again); /* eat mailer header &cetera, intuit format */ switch (qformat) { #ifdef DL case form_dl: dl(macname, filename); break; #endif /* DL */ #ifdef HECX case form_hecx: hecx(macname, filename); break; #endif /* HECX */ #ifdef HQX case form_hqx: hqx(macname); again = 1; goto nexttry; #endif /* HQX */ #ifdef MU case form_mu: mu(macname); again = 1; goto nexttry; #endif /* MU */ default: break; } (void)fclose(ifp); } /* eat characters until header detected, return which format */ static int find_header(again) int again; { int c, dl_start, llen; char *cp; char header[INFOBYTES]; int ds, rs; if(again && was_macbin) { while(to_read-- > 0) { c = fgetc(ifp); } } was_macbin = 0; c = fgetc(ifp); (void)ungetc(c, ifp); if(c == 0) { was_macbin = 1; if(fread(header, 1, INFOBYTES, ifp) != INFOBYTES) { (void)fprintf(stderr, "Premature EOF\n"); #ifdef SCAN do_error("hexbin: Premature EOF"); #endif /* SCAN */ exit(1); } ds = get4(header + I_DLENOFF); rs = get4(header + I_RLENOFF); ds = (((ds + 127) >> 7) << 7); rs = (((rs + 127) >> 7) << 7); to_read = ds + rs; if(strncmp(header + I_TYPEOFF, "TEXT", 4)) { (void)fprintf(stderr, "This file is not a proper BinHexed file.\n"); #ifdef SCAN do_error("hexbin: not a proper BinHexed file"); #endif /* SCAN */ exit(1); } if(listmode) { (void)fprintf(stderr, "This file is probably packed by "); if(!strncmp(header + I_AUTHOFF, "BNHQ", 4)) { (void)fprintf(stderr, "\"BinHex\""); } else if(!strncmp(header + I_AUTHOFF, "BthX", 4)) { (void)fprintf(stderr, "\"BinHqx\""); } else if(!strncmp(header + I_AUTHOFF, "BnHq", 4)) { (void)fprintf(stderr, "\"StuffIt\""); } else if(!strncmp(header + I_AUTHOFF, "ttxt", 4)) { (void)fprintf(stderr, "\"Compactor\""); } else if(!strncmp(header + I_AUTHOFF, "BSWU", 4)) { (void)fprintf(stderr, "\"UUTool\""); } else { (void)fprintf(stderr, "an unknown program"); } (void)fprintf(stderr, ".\n"); } } /* look for "(This file ...)" or "(Convert with...)" line. */ /* or for "begin " */ /* dl format starts with a line containing only the symbols '@' to 'O', or '|'. */ while(readline()) { llen = strlen(line); #ifdef HQX if((strncmp(line, "(This file", 10) == 0) || (strncmp(line, "(Convert with", 13) == 0)) { if(verbose) { (void)fprintf(stderr, "Skip:%s\n", line); } break; } #endif /* HQX */ #ifdef MU if(strncmp(line, "begin ", 6) == 0) { return form_mu; } #endif /* MU */ #ifdef DL /* Do not allow bogus false starts */ if(llen > 40 && (llen & 1) == 0) { dl_start = 1; for(cp = &line[0]; *cp != 0; cp++) { if((*cp < '@' || *cp > 'O') && *cp != '|') { dl_start = 0; break; } } if(dl_start && cp > &line[1]) { return form_dl; } } #endif /* DL */ if(llen != 0 && verbose) { (void)fprintf(stderr, "Skip:%s\n", line); } } while(readline()) { switch (line[0]) { #ifdef HQX case ':': return form_hqx; #endif /* HQX */ #ifdef HECX case '#': return form_hecx; #endif /* HECX */ default: break; } } if(!again) { (void)fprintf(stderr, "unexpected EOF\n"); #ifdef SCAN do_error("hexbin: unexpected EOF"); #endif /* SCAN */ exit(1); } return form_none; } static void usage() { (void)fprintf(stderr, "Usage: hexbin [-%s] [filenames]\n", options); (void)fprintf(stderr, "Use \"hexbin -H\" for help.\n"); }