#include #include #include #include #include #include #include "arc.h" #include "sysinc.h" static void runfile PROTO((struct heads *, int, char **)); void clsfil(f, name, date, time) FILE *f; char *name; unsigned date, time; { fflush(f); if (name) _dos_setftime(fileno(f), date, time); fclose(f); } void fatal(fmt, ...) char *fmt; { va_list arg; va_start(arg, fmt); vprintf(fmt, arg); va_end(arg); exit(EXIT_FAILURE); } char *dir(filename) char *filename; { char *result, *p, *q; static int first = 1; static char *path; static int pathlen; static struct find_t ff_area; if (filename) { if (_dos_findfirst(filename, _A_NORMAL, &ff_area) != 0) return NULL; p = filename; if (q = strrchr(p, '/')) p = q + 1; if (q = strrchr(p, '\\')) p = q + 1; if (q = strrchr(p, ':')) p = q + 1; pathlen = p - filename; if (pathlen != 0) { if (!(path = malloc(pathlen))) fatal("Out of memory"); memcpy(path, filename, pathlen); } } else if (first) return NULL; else if (_dos_findnext(&ff_area) != 0) { if (pathlen > 0) free(path); return NULL; } first = 0; result = malloc(pathlen + strlen(ff_area.name) + 1); if (pathlen > 0) memcpy(result, path, pathlen); strcpy(result + pathlen, ff_area.name); return result; } void rempath(nargs, arg) int nargs; char *arg[]; { int n; for (n = 0; n < nargs; n++) arg[n] = basename(arg[n]); } char *makefnam(f, d, r) char *f, *d, *r; { char drive[2][_MAX_DRIVE]; char dire[2][_MAX_DIR]; char name[2][_MAX_FNAME]; char ext[2][_MAX_EXT]; _splitpath(f, drive[0], dire[0], name[0], ext[0]); _splitpath(d, drive[1], dire[1], name[1], ext[1]); if (drive[0][0] == '\0') strcpy(drive[0], drive[1]); if (dire[0][0] == '\0') strcpy(dire[0], dire[1]); if (name[0][0] == '\0') strcpy(name[0], name[1]); if (ext[0][0] == '\0') strcpy(ext[0], ext[1]); _makepath(r, drive[0], dire[0], name[0], ext[0]); strupr(r); return r; } char *basename(p) char *p; { char *q; if (q = strrchr(p, '/')) p = q + 1; if (q = strrchr(p, '\\')) p = q + 1; if (q = strrchr(p, ':')) p = q + 1; if (!(q = malloc(strlen(p) + 1))) fatal("Out of memory"); strcpy(q, p); return q; } FILE *opnfilwr(p) char *p; { FILE *f; char buf[STRLEN]; if (f = fopen(p, "rb")) { fclose(f); printf("WARNING: File %s already exists!", p); do { printf(" Overwrite it (y/n)? "); fgets(buf, STRLEN, stdin); *buf = (char)toupper(*buf); if (*buf == 'N') { printf("%s not extracted.\n", p); return NULL; } } while (*buf != 'Y'); } if (!(f = fopen(p, "wb")) && warn) { perror(p); nerrs++; } return f; } void runarc(num, arg) int num; char *arg[]; { struct heads hdr; char buf[STRLEN]; rempath(num,arg); openarc(0); if (num > 0) { while (readhdr(&hdr, arc)) { if (match(hdr.name, makefnam(arg[0], ".*", buf))) runfile(&hdr, num, &arg[1]); else fseek(arc, hdr.size, 1); } } else { while (readhdr(&hdr, arc)) runfile(&hdr, 0, NULL); } closearc(0); } static void runfile(hdr, num, arg) struct heads *hdr; int num; char *arg[]; { FILE *tmp; char buf[STRLEN], sys[STRLEN], *dir; int n; makefnam("$ARCTEMP", hdr->name, buf); if (strcmp(buf,"$ARCTEMP.BAS") == 0) strcpy(sys, "BASICA $ARCTEMP"); else if(strcmp(buf, "$ARCTEMP.BAT") == 0 || strcmp(buf, "$ARCTEMP.COM") == 0 || strcmp(buf, "$ARCTEMP.EXE") == 0) strcpy(sys, "$ARCTEMP"); else { if (warn) { printf("File %s is not a .BAS, .BAT, .COM, or .EXE\n", hdr->name); nerrs++; } fseek(arc, hdr->size, 1); return; } if (warn && (tmp = fopen(buf, "rb")) != NULL) fatal("Temporary file %s already exists", buf); if ((tmp=opnfilwr(buf)) == NULL) fatal("Unable to create temporary file %s", buf); if (note) printf("Invoking file: %s\n", hdr->name); for (n = 0; n < num; n++) { strcat(sys, " "); strcat(sys, arg[n]); } dir = getcwd(NULL, 0); unpack(arc, tmp, hdr); fclose(tmp); system(sys); chdir(dir); free(dir); if (remove(buf) && warn) { printf("Cannot remove temporary file %s\n", buf); nerrs++; } } int readhdr(hdr, f) struct heads *hdr; FILE *f; { char name[FNLEN]; int try = 0; static int first = 1; if (!f || feof(f)) return 0; if (getc(f) != ARCMARK) { if (warn) { printf("An entry in %s has a bad header.\n", arcname); nerrs++; } while (!feof(f)) { try++; if (getc(f) == ARCMARK) { ungetc(hdrver = getc(f), f); if (hdrver >= 0 && hdrver <= ARCVER) break; } } if (feof(f) && first) fatal("%s is not an archive", arcname); if (changing && warn) fatal("%s is corrupted -- changes disallowed", arcname); if (warn) printf(" %d bytes skipped.\n", try); if (feof(f)) return 0; } hdrver = getc(f); if (hdrver < 0) fatal("Invalid header in archive %s", arcname); if (hdrver == 0) return 0; if (hdrver > ARCVER) { fread(name, 1, FNLEN, f); printf("I don't know how to handle file %s in archive %s\n", name, arcname); printf("I think you need a newer version of ARC.\n"); exit(EXIT_FAILURE); } if (hdrver == 1) { fread(hdr, sizeof (struct heads) - sizeof (long), 1, f); hdrver = 2; hdr->length = hdr->size; } else fread(hdr, sizeof (struct heads), 1, f); if (hdr->date > olddate || (hdr->date == olddate && hdr->time > oldtime)) { olddate = hdr->date; oldtime = hdr->time; } first = 0; return 1; } void writehdr(hdr, f) struct heads *hdr; FILE *f; { putc(ARCMARK, f); putc(hdrver, f); if (hdrver == 0) return; fwrite(hdr, sizeof (struct heads), 1, f); if (hdr->date > arcdate || (hdr->date == arcdate && hdr->time > arctime)) { arcdate = hdr->date; arctime = hdr->time; } } void filecopy(f, t, size) FILE *f, *t; long size; { char *buf; size_t bufl, bytr; bufl = coreleft(); if ((long)bufl > size) bufl = (size_t)size; if (bufl > 60000) bufl = 60000; while (!(buf = malloc(bufl))) if ((bufl >>= 1) == 0) fatal("Out of memory"); while (size > 0) { if ((bytr = fread(buf, (size_t)1, bufl, f)) == 0) fatal("Read fail"); if (fwrite(buf, (size_t)1, bytr, t) != bytr) fatal("Write fail (disk full?)"); size -= bytr; if ((long)bufl > size) bufl = (size_t)size; } free(buf); }