home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / bin / msvv90sea.exe / MSBOOFLS.EXE / MSBPCT.C < prev    next >
C/C++ Source or Header  |  1992-07-30  |  8KB  |  262 lines

  1. /*
  2.  * MSBPCT.C
  3.  *
  4.  * Howie Kaye -- Columbia University 3/11/86
  5.  *
  6.  * Sibling program to MSBMKB.C.  It is used to unpack BOO files, used for
  7.  * encoding binary files into text, and back.  This program does the decoding.
  8.  * It is meant to replace the program "MSBPCT.BAS", and runs approximately
  9.  * 200 times faster.
  10.  *
  11.  * For documentation on BOO file format, see MSBMKB.C.
  12.  * This program runs, as is, under Microsoft C on MSDOS and under UNIX.
  13.  *
  14.  * Modification history:
  15.  *
  16.  * 10-AUG-90, Robert Weiner (robert%progplus.uucp@uunet.uu.net)
  17.  *   Look for [rw] comments
  18.  *   Moved strlen() out of loop, makes MSBPCT quicker (I've seen 20% quicker)
  19.  *   Added ferror() check for outputfile, else things like out-of-disk-space
  20.  *   and write errors go unnoticed.  I think ferror() should be a reasonably
  21.  *   machine independent call.
  22.  *   There was a "final ^Z" outputted for MSDOS, removed it since we are
  23.  *   extracting executables here and what we extract should be exactly what
  24.  *   we put in.  If there was a final ^Z in the inputfile (ie. possibly a text
  25.  *   file) it should have been encoded in the boo file to begin with and
  26.  *   therefore would be automatically extracted.
  27.  *   Added proper exit status to go along with the ferror() test.
  28.  *   exit(0)=good, exit(1)=bad.  Added exit status variable 'ret'.
  29.  *   Tested under MSC 5.1, MSDOS 3.10
  30.  *
  31.  * 1/26/92, Christian Hemsing. Added OS-9 support. Omit trailing nulls.
  32.  *            after an idea from Charles Lasner.
  33.  * 1/21/92, Frank da Cruz.  Fix #ifdef's, remove empty #else clause.
  34.  * 6/29/90, Frank da Cruz.  Lowercase output filename for Unix.
  35.  *
  36.  * 1/27/89, Frank da Cruz.  Comment out #define MSDOS, since this is already
  37.  *   predefined for Microsoft C and probably other MS-DOS C compilers.
  38.  *   put it back if you have trouble.
  39.  *   Also comment out #define CI86.  Uncomment if you're really using CI-86,
  40.  *   or define CI86 on the compiler command line.
  41.  *
  42.  * 1/1/88, Frank da Cruz.  Remove default input file names -- too
  43.  *   confusing.  Add exit(0) for good return code upon success. 
  44.  *
  45.  * 3/23/86 - Davide P. Cervone -- University of Rochester
  46.  *   added AMIGA and VAX11C support
  47.  *
  48.  * 3/24/86 - Martin Knoblauch -- TH-Darmstadt              (MK001)
  49.  *   test if 1. line of inputfile is delimited by "\r\n" instead of "\n"
  50.  *
  51.  * 5/5/86 - John Matthews, U of Delaware.
  52.  *   Explicitly close the files.
  53.  *
  54.  * 5/8/86 - L. John Junod, DTNSRDC.
  55.  *   Adapt for Computer Innovations MS-DOS CI-86 Compiler
  56.  *   Improve too many args error message
  57.  *
  58.  */
  59. #include <stdio.h>
  60.  
  61. #ifdef AMIGA
  62. #include <fcntl.h>
  63. #endif /* AMIGA */
  64.  
  65. #ifdef MSDOS 
  66. #ifndef CI86
  67. #include <fcntl.h>
  68. #endif /* CI86 */
  69. #else
  70. #ifdef vax11c
  71. #include <file.h>
  72. #else
  73. #ifndef OSK
  74. #include <sys/file.h>
  75. #endif /* not OSK */
  76. #endif /* vax11c */
  77. #endif /* MSDOS */
  78.  
  79. #define fixchr(x) ((x) -'0')
  80. #define MYRPTQ        '~'     /* Repeat count prefix */
  81.  
  82. yes_or_no_p(arg) char *arg; {
  83.     int c,x;
  84.     while (1) {
  85.     printf("%s",arg);
  86.     c = getchar();
  87.     if (c == '\n') continue;
  88.     while ((x = getchar()) != '\n')
  89.       if (x == EOF) return(0);
  90.     if ((c == 'Y') || (c == 'y')) return(1);
  91.     if ((c == 'N') || (c == 'n') || (c == EOF)) return(0);
  92.     printf("Please answer 'Y' or 'N'\n");
  93.     }
  94. }
  95.  
  96. main(argc,argv) char **argv; {
  97.     char *infile = "";            /* input file name, with default */
  98.     char outfile[100];            /* output file name */
  99.     FILE *ifp, *ofp;            /* i/o files */
  100.     char inline[100];
  101.     int f, i, n;
  102.     int ret=0;                /* [rw] exit status assumed ok */
  103.     char last,before_last;  /* two byte buffer to omit trailing nulls */
  104.     char first=1;
  105.     char null_cnt=0;        /* #of trailing nulls */
  106.  
  107.     if (argc > 2) {            /* check for too many args */
  108.     printf("Too many args. Usage: msbpct input-boo-file-name\n");
  109.     exit(1);
  110.     }
  111.     if (argc > 1) {            /* check for input file */
  112.     infile = argv[1];
  113.     } else if (argc < 2) {
  114.     printf("Usage: msbpct input-boo-file-name\n");
  115.     exit(1);
  116.     }
  117.     if ((ifp = fopen(infile,"r")) == NULL) { /* open input file */
  118.     printf("%s not found.\n",infile); /* failure? */
  119.     exit(1);
  120.     }
  121.  
  122.     fgets(outfile,100,ifp);        /* get output file name */
  123.     n = strlen(outfile);
  124.     if ((outfile[n-2] == '\r')|        /* MK001 */
  125.     (outfile[n-2] == '\n')) {
  126.     outfile[n-2] = '\0';
  127.     } else {
  128.     outfile[n-1] = '\0';
  129.     }
  130.  
  131. #ifndef MSDOS
  132. #ifndef vms
  133.     /* For UNIX and OSK, convert name to lowercase. */
  134.     for (i = 0; i < n; i++) {
  135.     if (outfile[i] >= 'A' && outfile[i] <= 'Z') outfile[i] += 32;
  136.     }
  137. #endif /* vms */
  138. #endif /* MSDOS */
  139.  
  140.     if ((ofp = fopen(outfile,"r")) != NULL) {
  141.     char msg[100];
  142.     sprintf(msg,
  143.         "output file '%s' already exists.  continue (y/n)? ",outfile);
  144.     if (!yes_or_no_p(msg)) {
  145.         printf("ok.     bye\n");
  146.         exit(0);
  147.     } else {
  148.         fclose(ofp);
  149.     }
  150.     }
  151.  
  152. #ifndef MSDOS
  153. #ifndef O_BINARY
  154. #define O_BINARY 0
  155. #endif /* O_BINARY */
  156. #endif /* MSDOS */
  157.  
  158. #ifdef AMIGA
  159.     if ((ofp = fopen(outfile,"w")) == NULL) {
  160.     printf("could not open %s\n",outfile); /* failure */
  161.     exit(0);
  162.     }
  163. #else
  164. #ifdef CI86
  165.     if((ofp = fopen(outfile,"wb")) == NULL){
  166.     printf("could not open %s\n",outfile); /* failure */
  167.     exit(0);
  168.     }
  169. #else
  170. #ifdef OSK
  171.     if ((ofp = fopen(outfile,"w")) == NULL) { /* open it */
  172. #else
  173.     f = open(outfile,O_CREAT|O_WRONLY|O_TRUNC|O_BINARY,0x1ff);
  174.     if ((ofp = fdopen(f,"w")) == NULL) { /* open it */
  175. #endif
  176.     printf("failure to open %s\n",outfile); /* failure? */
  177.     exit(1);
  178.   }
  179. #endif /* CI86 */
  180. #endif /* AMIGA */
  181.  
  182.     printf("%s ==> %s\n",infile,outfile); /* announce our intentions */
  183.  
  184.     while(fgets(inline,100,ifp) != NULL) { /* till EOF */
  185.     int index=0,outindex=0,len;    /* [rw] added len */
  186.     len=strlen(inline);        /* [rw] moved out of loop below */
  187.     while (index < len && inline[index] != '\n' &&
  188.            inline[index] != '\r') {    /* end of line? */
  189.         if (inline[index] == MYRPTQ) { /* null compress char... */
  190.         int rptcnt;
  191.         int i;
  192.  
  193.         index++;
  194.         rptcnt = fixchr(inline[index]); /* get repeat count */
  195.         index++;
  196.         if (rptcnt == 0) {    /* additional nulls to be omitted */
  197.             null_cnt = null_cnt +1;
  198.             continue;
  199.         }
  200.         if (!first) {
  201.             putc(before_last,ofp);
  202.             putc(last,ofp);
  203.             before_last = '\0';
  204.             last = '\0';
  205.         } else {
  206.             first = 0;
  207.             before_last = '\0';
  208.             last = '\0';
  209.         }
  210.         rptcnt = rptcnt - 2;
  211.         for (i=0; i<rptcnt; i++) /* output rest of the nulls */
  212.           putc('\0',ofp);
  213.         } else {            /* a quad to decode... */
  214.         int a, b, c ,d;
  215.  
  216.         a = fixchr(inline[index]);
  217.         index++;
  218.         b = fixchr(inline[index]);
  219.         index++;
  220.         c = fixchr(inline[index]);
  221.         index++;
  222.         d = fixchr(inline[index]);
  223.         index++;
  224.  
  225.         if (!first) {
  226.             putc(before_last,ofp);
  227.             putc(last,ofp);
  228.             putc(((a*4)+(b/16)) & 255,ofp); /* output the bytes */
  229.             before_last = ((b*16)+(c/4)) & 255;
  230.             last = ((c*64)+d) & 255;
  231.         } else {
  232.             first = 0;
  233.             putc(((a*4)+(b/16)) & 255,ofp); /* output the bytes */
  234.             before_last = ((b*16)+(c/4)) & 255;
  235.             last = ((c*64)+d) & 255;
  236.         }
  237.         }
  238.     }
  239.     if ( ferror(ofp) )        /* [rw] must check for errors here! */
  240.       break;
  241.     }
  242.  
  243.     if (null_cnt == 0) {
  244.     printf("There might be one additional null at eof, because\n");
  245.     printf("the BOO file had been encoded with an old encoder.\n");
  246.     putc(before_last,ofp);
  247.     } else if (null_cnt == 1) {
  248.     putc(before_last,ofp);
  249.     } else {} /* nothing to do here; just don't output the last two nulls */
  250. #ifdef AMIGA
  251.     putc('\032',ofp);            /* final ^Z for the Amiga */
  252. #endif /* AMIGA */
  253.  
  254.     if ( ferror(ofp) ) {        /* [rw] must check for errors */
  255.     printf("error writing output file %s\n",outfile); /* failure */
  256.     ret = 1 ;            /* [rw] exit status is now bad */
  257.     }
  258.     fclose(ofp);            /* Close the files */
  259.     fclose(ifp);
  260.     exit(ret);                /* [rw] exit with success/failed */
  261. }                    /* End of program */
  262.