BTOA-22.C
/*
 * btoa: version 2.2 for cpm/msdos on packet radio            *
 *
 * btoa: version 4.0                         *
 * purpose: stream filter to change 8 bit bytes into printable ascii  *
 * computes the number of bytes, and three kinds of simple checksums  *
 * incoming bytes are collected into 32-bit words, then printed in    *
 * base 85  exp(85,5) > exp(2,32). The ASCII characters used are be-  *
 * tween '!' and 'u'. 'z' encodes 32-bit zero; 'x' is used to mark    *
 * the end of encoded data.                     *
 *                              *
 *  Paul Rutter      Joe Orost                  *
 *  philabs!per      petsd!joe                  *
 *                              *
 *  WARNING: this version is not compatible with the original as sent *
 *  out on the net.  The original encoded from ' ' to 't'; which      *
 *  cause problems with some mailers (stripping off trailing blanks). *
 *
 *                                                                    *
 *  86May30 - modified progress displays and removed a debugging dis- *
 *            inadvertently left in |br| ka2bqe               *
 *  86May23 - modified for '-h' or '-H', also added variable line     *
 *            length, and byte counts output to console, and fixed    *
 *            bug in ouput overwrite query |br| ka2bqe                *
 *  86May19 - modified for command line input and '-h' option to pro- *
 *            duce 62 char output lines for HF packet, and place in-  *
 *            put file name in header of output file  |br| ka2bqe     *
 *  86May05 - modified to compile/run for packet radio under cpm-80 & *
 *            msdos by Brian B. Riley ( |br| - ka2bqe) - RATS         *
 *  Hacked to work with non-UNIX machines by Brian Lloyd, 86/04/14    *
 *                                                                    *
 */

#include <stdio.h>

#define reg register

#define MAXPERLINE    78   /* use standard unit record line 78+2*/
#define MAX_HF_PERLINE   60   /* HF packet uses 64 byte packets so */
            /* we'll use 60 */

#define streq(s0, s1)  strcmp(s0, s1) == 0

long int Ceor = 0;
long int Csum = 0;
long int Crot = 0;

long int ccount = 0;
long int bcount = 0;
long unsigned int word;

long int out_count;
int line_length;

FILE * inf;
FILE * outf;

#define EN(c)   (int) ((c) + '!')

/*
 * main
 */
main(argc, argv)
char **argv;
{
   reg      c;
   reg      long int n;
   char      infile[20];
   char      outfile[20];
   char      line_buf[16];

   line_length = MAXPERLINE;   /* default to 78      */
   printf(" btoa: Binary-to-Ascii conversion\n       RATS  v2.2\n");

        if (argc < 2) {
                printf("Usage: btoa [-h || -l xxx] infile outfile \n");
                exit(2);
        }
   if (argv[1][0] == '-') {
       switch (argv[1][1]) {
         case 'h':
         case 'H':
      line_length = MAX_HF_PERLINE;     /* less for HF packet */
      break;
         case 'l':
         case 'L':
      line_length = atoi(argv[2]);
      if (line_length < 4 || line_length > 251) {
          printf("\m LINELENGTH specified out of range - default to 78\n");
          line_length = 78;
      }
           argv++;                   /* advance the arg pointers   */
           argc--;                   /* decrement arg counter   */
      break;
         default:
      printf("\n UNRECOGNIZED option - ignored !\n");
      break;
       }
       argv++;                   /* advance the arg pointers   */
       argc--;                   /* decrement arg counter   */
   } 
        if (argc < 2) {
       printf("Usage: btoa [-h || -l xxx] infile outfile \n");
       exit();
          }
   strcpy(infile,argv[1]);  /* get inputfile name */

        while ((inf = fopen(infile, "r")) == NULL) {
       printf( " Error opening file - %s\n Input file:  ",
         infile);
       if (gets( infile ) == NULL)
      exit();
        }
   strcpy(outfile,argv[2]);

   while ((outf = fopen(outfile,"r")) != NULL) {
       fclose(outf);
       printf("\n Target file name exists! Overwrite (Y/N) ? ");
       gets(line_buf);
       if (toupper(line_buf[0]) == 'Y') {
      break;
       } else {
      printf (" Enter new output filename : ");
      gets(outfile);
       }
   }
   fclose(outf);

        while ((outf = fopen(outfile, "w")) == NULL) {
       printf( " Error opening file - %s\n Output file: ",
         infile);
       fclose (outf);
       if (gets( outfile ) == NULL)
      exit();
        }
   printf(" encoding file: %s ===> %s",infile, outfile);
   fprintf( outf, "xbtoa Begin %s\n", infile);
   n = 0;
   while ((c=getc(inf))!=EOF) {encode(c);n+=1;}
   while (bcount!=0) {encode(0);
   }

   /* n twice as crude cross check*/

   fprintf(outf,"\nxbtoa End N %ld %lx E %lx S %lx R %lx\n",n,n,Ceor,Csum,Crot);
   putc('\n',outf);
   fclose(inf);
   fclose(outf);
   printf("\n ===> *** EOF *** ===> checksum written\n %ld bytes read, %ld bytes en
coded\n"
      ,n, out_count);
   exit();
}

/*
 * charout - output encoded character to the file and count chars to    *
 *           'break the data into manageable lines                      *
 */
charout(c)
{
   putc(c,outf);
   ccount += 1;
   out_count += 1;
   if (ccount == line_length) {
      putc('\r',outf);   /* original function didn't have */
      putc('\n',outf);   /* the /r - packet NEEDS returns */
      out_count += 2;
      ccount = 0;
   }
}

/*
 * encode - stream encoding of the data flow                            *
 */
encode(c)
   reg c;
{
   Ceor ^= c;
   Csum += c;
   Csum += 1;
   if ((Crot & 0x80000000L)) {
      Crot <<= 1;
      Crot += 1;
   } else {
      Crot <<= 1;
   }
   Crot += c;

   word <<= 8;
   word |= c;
   if (bcount==3) {wordout(word);bcount=0;}
    else {bcount+=1;}
}

/*
 * wordout - output the encoded 4 byte stream as 5 'digit' word         *
 */
wordout(word)
   reg unsigned long int word;
{
   if (word==0) {charout('z');}
    else {

      /* 85^4 */
      charout(EN(word / 52200625L ));
      word %= 52200625L;

      /* 85^3 */
      charout(EN(word / 614125L ));
      word %= 614125L;

      /* 85^2 */
      charout(EN(word / 7225L ));
      word %= 7225L;

      /* 85^1 */
      charout(EN(word / 85));
      word %= 85;
      charout(EN(word));
   }
}

