/* atob * stream filter to change printable ascii from "btoa" back into 8 bit bytes * if bad chars, or Csums do not match: exit(1) [and NO output] * * Paul Rutter Joe Orost * * 7/29/90: added input and output file handling so to run on VMS, DOS, etc * add TMPDIR to handle tempory files. * VMS doesn't support unlink, so add a dummy one. * --kang sun (sun@robios.eng.yale.edu) */ #include #define reg register #define streq(s0, s1) strcmp(s0, s1) == 0 #define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x) #if vms #define TMPDIR "SYS$LOGIN:" #define unlink(s) {;} /* a dummy unlink function for VMS */ #endif #if unix #define TMPDIR "/tmp/" #endif #if dos #define TMPDIR "\" #endif FILE *fip, *fop; /* pointer to input and output file */ long int Ceor = 0; long int Csum = 0; long int Crot = 0; long int word = 0; long int bcount = 0; fatal() { fprintf(stderr, "bad format or Csum to atob\n"); exit(1); } #define DE(c) ((c) - '!') decode(c) reg c; { if (c == 'z') { if (bcount != 0) { fatal(); } else { byteout(0); byteout(0); byteout(0); byteout(0); } } else if ((c >= '!') && (c < ('!' + 85))) { if (bcount == 0) { word = DE(c); ++bcount; } else if (bcount < 4) { word = times85(word); word += DE(c); ++bcount; } else { word = times85(word) + DE(c); byteout((int)((word >> 24) & 255)); byteout((int)((word >> 16) & 255)); byteout((int)((word >> 8) & 255)); byteout((int)(word & 255)); word = 0; bcount = 0; } } else { fatal(); } } FILE *tmp_file; byteout(c) reg c; { Ceor ^= c; Csum += c; Csum += 1; if ((Crot & 0x80000000)) { Crot <<= 1; Crot += 1; } else { Crot <<= 1; } Crot += c; putc(c, tmp_file); } main(argc, argv) int argc; char **argv; { reg c; reg long int i; char tmp_name[100]; char buf[100]; long int n1, n2, oeor, osum, orot; fip = stdin; fop = stdout; switch(argc) { case 3: /* both in and out file names are given */ if ((fop=fopen(argv[2],"w"))==NULL) { printf("\tCan't open output file - %s\n",argv[2]); exit (1); } case 2: /* only in file name is given */ if ((fip=fopen(argv[1],"r"))==NULL) { printf("\tCan't open input file - %s\n",argv[1]); exit (1); } case 1: /* neither file name is given */ break; default: printf("\tUsage: atob [file1 [file2]]\n"); break; } sprintf(tmp_name, "%satob.tmp", TMPDIR); tmp_file = fopen(tmp_name, "w+"); if (tmp_file == NULL) { fatal(); } /*search for header line*/ for (;;) { if (fgets(buf, sizeof buf, fip) == NULL) { fatal(); } if (streq(buf, "xbtoa Begin\n")) { break; } } while ((c = getc(fip)) != EOF) { if (c == '\n') { continue; } else if (c == 'x') { break; } else { decode(c); } } if (fscanf(fip,"btoa End N %ld %lx E %lx S %lx R %lx\n", &n1, &n2, &oeor, &osum, &orot) != 5) { fatal(); } if ((n1 != n2) || (oeor != Ceor) || (osum != Csum) || (orot != Crot)) { fatal(); } else { /* Now that we know everything is OK, copy tmp file to fop */ fseek(tmp_file, 0L, 0); for (i = n1; --i >= 0;) { putc(getc(tmp_file),fop); } } switch(argc) { /* close all the open files */ case 3: fclose(fop); case 2: fclose(fip); default: break; } unlink(tmp_name); /* Make file disappear */ exit(0); }