home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckbmkb.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  18KB  |  716 lines

  1. /* File MSBMKB.C
  2.  
  3. Author: Robert Weiner, Programming Plus, rweiner@watsun.cc.columbia.edu
  4.  
  5. Synopsis: Encodes a binary file into printable ASCII "boo" format, preserving
  6. the exact file length, using a 4-for-3 byte encoding.
  7.  
  8. Modification history:
  9.   28-APR-92    Initial pre-Alpha Release
  10.   29-APR-92    Fixes around fwrite, fclose
  11.             Changed writestr -> writeustr
  12.             Added prototypes
  13.         We're now at Beta Release!
  14.             MSDOS 5, MSC 5.1 tests out ok.
  15.             VAX/VMS VAXC032 is ok.
  16.             SUNOS is ok.
  17.             Both work with old or new msbpct.
  18.   30-APR-92    Fix to output()
  19.             Defaults to no prototypes
  20.             Added char counts logic
  21.             Added -v arg
  22.             writexstr takes chgcase now
  23.   01-MAY-92    Added 3rd arg interior-name
  24.             Added -l -u -q
  25.             Added stdin/out support
  26.             Add path stripping
  27.   02-MAY-92    Add '>' to path stripping (vms)
  28.   05-MAY-92    Release after outside testing
  29.             Added VOID usage() proto
  30.             Thanks to Christian Hemsing for OS-9 testing & defs.
  31.             Thanks to Steve Walton for Amiga testing & defs.
  32.   08-MAY-92    Prepare for general release
  33.             Added uchar defs, Modified _CDECL define,
  34.             Fixed up for MSDOS GNU CC
  35.             (GCC warnings noticed by Christian Hemsing)
  36.             Use gcc -DMSDOS to compile.
  37.             This MSDOS GCC defines "unix" which doesn't
  38.                 help us at all!
  39.   17-MAY-92        Add AtariST defs & improved __STDC__ check
  40.                   from Bruce Moore
  41.                         Removed string fns so don't need string.h.
  42.             Next general release now ready... Thanks to those
  43.                 listed in the directory below
  44.   12-JUL-92    Near Final release...??
  45.             Added portability items, cmd line overrides
  46.             ifdef UCHAR, VOID, NOANSI
  47.             Shortened lines to 79 max (got them all?)
  48.             Only thing not done is checking #ifdef NOUCHAR
  49.             and adding any anding off bits which signed
  50.             chars may intruduce in boo().
  51.  
  52.   25-OCT-93    Status VOS support added by David Lane, BSSI.
  53.  
  54. Beta Testing Informaton, Supported Systems Directory:
  55. =====================================================================
  56. ( Testor / Operating System / O.S. Version / Compiler )
  57.  
  58. Rob Weiner, rweiner@watsun.cc.columbia.edu:
  59.     MSDOS        5.0        MSC 5.1
  60.     MSDOS        5.0        GCC (DJGPP DOS 386/G++ 1.05)
  61.     VAX/VMS        5.4-2        VAXC032
  62.     SUNOS        4.1
  63.     UNIXPC        3.51
  64. Christian Hemsing, chris@v750.lfm.rwth-aachen.de:
  65.     OS-9
  66. Stephen Walton, swalton@solaria.csun.edu:
  67.     AMIGA                MANX C (defines MCH_AMIGA)
  68. Bruce J. Moore, moorebj@icd.ab.com:
  69.     AtariST TOS/GEMDOS        MWC 3.7
  70.  
  71. Fun stuff such as my favorite testing shell command is now possible:
  72.     $ for i in *
  73.     do
  74.         echo $i:
  75.         cat $i | msbmkb -q - - | msbpct -q - - | cmp -l - $i
  76.     done
  77.  
  78. This version properly implements the Lasner ~0 fixes.
  79.  
  80. SYNOPSYS: The en-booer writes out printable text from binary text via a 3
  81. input char to 4 output char conversion (called "triple to quad" conversion).
  82. Since the input text can run out before the last triple can be formed, all
  83. en-booers (msbmkb) would add 1 or 2 nulls to the input stream to complete
  84. the triple such that a valid quad can be output.  Thus the problem where
  85. often a de-booer (msbpct) will create an output file from a boo encoded
  86. file, but the output file is larger than the input file by 1 or 2 nulls.
  87. Charles Lasner documented this problem and offered a fix... For each 1 or 2
  88. extra null pad chars added to the input stream, the en-booer should add a
  89. trailing ~0 to the created boo file.  ~X (where X-'0' is a repeat value
  90. which indicates a number of "repeated nulls" does not have a value for the
  91. sequence "~0" which would imply: ``decode into a series of 0 nulls,'' a noop
  92. for "old" debooers.  Hence ~0 can be used as a flag that the input text had
  93. a "padding null" added to it and then the de-booer can know NOT to add these
  94. padding chars to the output stream.  This allows the en-boo/de-boo programs
  95. to finally always guarantee that you get what you started with after passing
  96. through the en-boo then de-boo process.
  97.  
  98. Some bugs/facts with the MSBPCT/MSBMKB programs which popped up
  99. or were discovered recently (January through March 1992):
  100.  -    CURRENT msbpct will NOT make a correct output file from
  101.     the boo file THIS msbmkb creates.  It loses or adds a char.
  102.         Comes from improper implementation of Lasner changes.
  103.         Note: CURRENT enbooer with CURRENT unbooer make the
  104.         same mistakes encoding/uncoding hense files come out
  105.         more or less ok.
  106.  -    OLD msbpct will create a proper output file from a boo
  107.     file created from THIS en-booer.
  108.  -    Current msbpct also screws up output column checking and can
  109.     override the max (usually ~0~0 at eof) and undercut the
  110.     standard value.
  111.  -    Current msbpct doesn't correctly implement lasner fixes.
  112.  -    Current msbpct tells of "using an old booer" at times
  113.     it can determine that that statement is meaningless.
  114.  -    Addtl improper implementation of Lasner change yields
  115.     (quite often) an additional 2 nulls in the output file which
  116.     are removed by an additional 2 ~0 sequence... to break even.
  117.     ie. where old & this enbooer at eof writes "~A", the
  118.     current (bad) booer writes "~C~0~0".
  119. (other items not listed).
  120.  
  121. This program was redone from scratch for portability and implementation
  122. functionality reasons, we also get VMS support here as a bonus.  Also, there
  123. are a few unnecessary things eliminated like adding nulls to the end of
  124. buffers which don't seem to serve any purpose.
  125.  
  126. Character counts for MSDOS ignore the fact that \n is really \r\n, it is
  127. just counting real boo data (in reality the \r can be left out and ignored).
  128. This is done on purpose & is the difference between "data bytes out" and
  129. simply "bytes out".
  130.  
  131. The old enbooer calculated the efficiency of enbooing, well, in reality you
  132. should be calculating the loss as the file grows bigger.  That calc was the
  133. only bit of floating point in the program... so I left it out intentionally.
  134. This program is 100% integer only math now.  Note that sometimes the boo
  135. file is SMALLER than the original, due to lots of null compressions.
  136.  
  137. This new msbmkb replaces the old one (msbmkb's dated before March 1992).
  138. Credit should be given to the maintainers of the old msbmkb:
  139.  
  140.     Original by Bill Catchings, Columbia University, July 1984.
  141.     Modifications by Howie Kaye & Frank da Cruz of Columbia
  142.     University and Christian Hemsing of the Rheinisch-Westphaelish
  143.     Technische Hochschule, Aachen, Germany.
  144. */
  145.  
  146. #include <stdio.h>            /* only header we need */
  147.  
  148. /*
  149.   Version Dependencies... Give each new special case its own defs:
  150. */
  151.  
  152.  
  153. #ifdef VAX11C                /* VAXC032 */
  154. #define SYSTEM        "VAX/VMS"
  155. #define EXIT_GOOD    1
  156. #define EXIT_INFO    3
  157. #define EXIT_BAD    5
  158. #define FOPEN_ROPTS    "rb"
  159. #define FOPEN_WOPTS    "w","rat=cr","rfm=var","mrs=0"
  160. #define CASE_CHANGE    CHANGE_LOWER    /* lowercase boo file name for vms */
  161. #define YES_PROTOS
  162. #endif
  163.  
  164.  
  165. #ifdef MSDOS                /* MSC 5.1 */
  166. #define SYSTEM        "MSDOS"
  167. #define EXIT_GOOD    0
  168. #define EXIT_INFO    1
  169. #define EXIT_BAD    2
  170. #define FOPEN_ROPTS    "rb"
  171. #define FOPEN_WOPTS    "w"
  172. #define CASE_CHANGE    CHANGE_LOWER    /* lowercase boo file name for msdos */
  173. #define YES_PROTOS
  174. #endif
  175.  
  176.  
  177. #ifdef GEMDOS                /* AtariST - TOS - MWC v3.7 */
  178. #define SYSTEM        "AtariST/TOS"
  179. #define EXIT_GOOD    0
  180. #define EXIT_INFO    1
  181. #define EXIT_BAD    2
  182. #define FOPEN_ROPTS    "rb"
  183. #define FOPEN_WOPTS    "w"
  184. #define CASE_CHANGE    CHANGE_LOWER    /* lowercase boo file name */
  185. #define YES_PROTOS
  186. #endif
  187.  
  188.  
  189. #ifdef OSK
  190. #define SYSTEM        "OS-9"
  191. #define EXIT_GOOD    0
  192. #define EXIT_INFO    1
  193. #define EXIT_BAD    1
  194. #define FOPEN_ROPTS    "r"
  195. #define FOPEN_WOPTS    "w"
  196. #define CASE_CHANGE    CHANGE_NONE    /* leave filename case sensitive */
  197. /*
  198. #undef  YES_PROTOS                      * default OS9 to noprotos *
  199. */
  200. #endif
  201.  
  202. #ifdef __VOS__
  203. /* Stratus VOS requires this to not complain about exit()    */
  204. /* being implicitly declared.                    */
  205. #include <stdlib.h>
  206. #define SYSTEM        "Stratus VOS"
  207. #define EXIT_GOOD    0
  208. #define EXIT_INFO    1
  209. #define EXIT_BAD    1
  210.  
  211. /* VOS file system has file organizations.  Assuming that the   */
  212. /* purpose of this is to transport executable programs, I have  */
  213. /* set the file organization to fixed-4096.  Object modules     */
  214. /* would be at fixed-1024, and text files should be either      */
  215. /* stream or sequential.  Ignore org on the boo file.        */
  216. #define FOPEN_ROPTS    "rf 4096"
  217. #define FOPEN_WOPTS    "w"
  218. #define CASE_CHANGE    CHANGE_NONE    /* Leave filename case sensitive */
  219. #define YES_PROTOS
  220. #endif /* __VOS__ */
  221.  
  222. #ifndef FOPEN_ROPTS            /* No system found, default to unix */
  223. #define SYSTEM        "UNIX/Amiga/Generic"
  224. #define EXIT_GOOD    0
  225. #define EXIT_INFO    1
  226. #define EXIT_BAD    2
  227. #define FOPEN_ROPTS    "r"
  228. #define FOPEN_WOPTS    "w"
  229. #define CASE_CHANGE    CHANGE_NONE    /* leave filename case sensitive */
  230. /*
  231. #undef  YES_PROTOS                      * default UNIX/generic to noprotos *
  232. */
  233. #endif
  234.  
  235. #ifndef NOANSI                /* allow cmd line override to STDC */
  236. #ifdef __STDC__                /* Ansi likes prototypes */
  237. #if __STDC__                /* MWC sets this defined but 0 valued */
  238. #define YES_PROTOS
  239. #endif
  240. #endif /* __STDC__ */
  241. #endif /* NOANSI */
  242.  
  243. #ifndef VOID                /* allow cmd line override to VOID */
  244. #define VOID void            /* assume system likes void */
  245. #endif
  246.  
  247. #ifndef _CDECL
  248. #define _CDECL
  249. #endif
  250.  
  251. #ifndef __DATE__
  252. #define __DATE__ "01-MAY-1992"
  253. #endif
  254.  
  255. #ifndef __TIME__
  256. #define __TIME__ "00:00:00"
  257. #endif
  258.  
  259. /*
  260.   BOO Encoder Options
  261. */
  262. #define MAXOUTLEN        72    /* max output chars per line */
  263. #define MAXNULLCOMP        78    /* max null compression via ~ */
  264. #define MINNULLCOMP        2    /* min of 2 nulls to compress */
  265.  
  266. #define tochar(c)    ( (c) + '0' )
  267.  
  268. #define CHANGE_NONE    1
  269. #define CHANGE_UPPER    2
  270. #define CHANGE_LOWER    3
  271.  
  272. /*
  273.   Typedefs
  274. */
  275. #ifndef UCHAR                /* allow cmd line override */
  276. typedef unsigned char uchar;        /* possible portability concern */
  277. #define UCHAR    uchar
  278. #else
  279. #define NOUCHAR        1        /* flag saying cmd line changed uchar */
  280. #endif
  281.  
  282. /*
  283.   Here are the function prototypes...
  284.   If your 'C' don't like prototypes, don't declare YES_PROTOS.
  285. */
  286. #ifdef YES_PROTOS
  287. VOID _CDECL convert    (FILE *, FILE *);
  288. int  _CDECL get3       (FILE *, UCHAR *);
  289. VOID _CDECL output     (FILE *, UCHAR *, int);
  290. VOID _CDECL writechars (FILE *, char *, int);
  291. VOID _CDECL writexstr  (FILE *, char *, int);
  292. VOID _CDECL boo        (UCHAR *, UCHAR *);
  293. VOID _CDECL change_case(char *, int);
  294. VOID _CDECL usage      (VOID);
  295. #else
  296. VOID convert    ();
  297. int  get3       ();
  298. VOID output     ();
  299. VOID writechars ();
  300. VOID writexstr  ();
  301. VOID boo        ();
  302. VOID change_case();
  303. VOID usage();
  304. #endif
  305.  
  306. long count_in=0, count_out=0;        /* character counts */
  307. int quiet=0;
  308.  
  309. main(argc,argv)
  310. int argc;
  311. char **argv;
  312. {
  313.     FILE *fpin, *fpout;
  314.     char *booptr;
  315.     int force_case=0;
  316.     int leave_path=0;
  317.  
  318.     while( argc > 1 && *argv[1]=='-' )
  319.         {
  320.         if( argv[1][1] == '\0' )
  321.             break;
  322.         switch( argv[1][1] )
  323.             {
  324.             case 'v':        /* version */
  325.                 fprintf(stderr,
  326.                 "MSBMKB.C, Date=\"%s, %s\", System=\"%s\"\n",
  327.                     __DATE__,__TIME__,SYSTEM);
  328.                 fprintf(stderr, "\
  329. Email comments to \"rweiner@kermit.columbia.edu\" \
  330. (Rob Weiner/Programming Plus)\
  331. \n");
  332.                 fprintf(stderr,"\n");
  333.                 break;
  334.             case 'l':        /* lowercase internal name */
  335.                 force_case = CHANGE_LOWER ;
  336.                 if( !quiet )
  337.                     fprintf(stderr,
  338.                     "Forcing Lowercased Internal Name\n");
  339.                 break;
  340.             case 'u':        /* uppercase internal name */
  341.                 force_case = CHANGE_UPPER ;
  342.                 if( !quiet )
  343.                     fprintf(stderr,
  344.                     "Forcing Uppercased Internal Name\n");
  345.                 break;
  346.             case 'p':            /* leave paths */
  347.                 leave_path=1;
  348.                 break;
  349.             case 'q':            /* quiet */
  350.                 quiet=1;
  351.                 break;
  352.             default:
  353.                 usage();
  354.             }
  355.         argc--;
  356.         argv++;
  357.         }
  358.  
  359.     if( argc < 3 || argc > 4 )
  360.         usage();
  361.  
  362.     if( argv[1][0]=='-' && argv[1][1]=='\0' )
  363.         {
  364.         fpin = stdin;
  365.         }
  366.     else if( (fpin = fopen( argv[1] , FOPEN_ROPTS )) == NULL )
  367.         {
  368.         fprintf(stderr,"Error, cannot open input file \"%s\"\n",
  369.             argv[1]);
  370.         exit(EXIT_BAD);
  371.         }
  372.  
  373.     if( argv[2][0]=='-' && argv[2][1]=='\0' )
  374.         {
  375.         fpout = stdout;
  376.         }
  377.     else if( (fpout = fopen( argv[2] , FOPEN_WOPTS )) == NULL )
  378.         {
  379.         fprintf(stderr,"Error, cannot open output file \"%s\"\n",
  380.             argv[2]);
  381.         exit(EXIT_BAD);
  382.         }
  383.  
  384.     if( !quiet )
  385.         fprintf(stderr,
  386.                "Creating BOO File \"%s\" from Binary File \"%s\"...\n",
  387.                 argv[2],argv[1]);
  388.  
  389.     booptr = argv[1] ;    /* input file name */
  390.     if( argc > 3 )        /* command line override internal name */
  391.         {
  392.         booptr = argv[3];
  393.         if( !quiet )
  394.             fprintf(stderr,
  395.     "Command Line Argument \"%s\" Overrides Internal BOO File Name\n",
  396.                 booptr);
  397.         }
  398.     else if( !leave_path )
  399.         {    /* strip path regexpr ".*[/\\\]:>]" from booptr */
  400.         char *s, *t;
  401.         for( s = t = booptr ; *s ; s++ )
  402.             {
  403.             if(*s=='/' || *s=='\\' || *s==']' ||
  404.                *s==':' || *s=='>')
  405.                 t = s + 1 ;
  406.             }
  407.         if( *t == '\0' )
  408.             t = "_";
  409.         if( t != booptr )
  410.             {
  411.             if( !quiet )
  412.                 fprintf(stderr,
  413.             "Internal BOO File Name Without Path = \"%s\"\n",t);
  414.             }
  415.         booptr = t ;
  416.         }
  417.  
  418.     if( force_case == 0 )
  419.         force_case = CASE_CHANGE ;
  420.  
  421.     /* first line in output file is filename */
  422.     writexstr( fpout, booptr, force_case );
  423.  
  424.     convert(fpin,fpout);
  425.  
  426.     writechars(fpout,"",0);        /* flush output buffering */
  427.  
  428.     fclose(fpin);
  429.     fclose(fpout);
  430.  
  431.     if( !quiet )
  432.         {
  433.         fprintf(stderr,"Data bytes in: %ld,  ",  count_in);
  434.         fprintf(stderr,"Data bytes out: %ld,  ", count_out);
  435.         fprintf(stderr,"Difference: %ld bytes\n",
  436.                 count_out - count_in);
  437.         }
  438.     exit(EXIT_GOOD);
  439. }
  440.  
  441.  
  442. VOID usage()
  443. {
  444.     fprintf(stderr, "MSBMKB = Encode Binary File into Ascii BOO Format\n");
  445.     fprintf(stderr, "\
  446. Usage: MSBMKB [-v -l -u -p -q] input_file output_boo_file [internal_boo_name]\
  447. \n");
  448.     fprintf(stderr,
  449. "              -v = show version information\n");
  450.     fprintf(stderr,
  451. "              -l = lowercase internal BOO file name\n");
  452.     fprintf(stderr,
  453. "              -u = uppercase internal BOO file name\n");
  454.     fprintf(stderr,
  455. "              -p = leave internal BOO path intact\n");
  456.     fprintf(stderr,
  457. "              -q = quiet mode\n");
  458.     fprintf(stderr,
  459. "              Note: Filenames of '-' are supported for stdin & stdout\n");
  460.     exit(EXIT_INFO);
  461. }
  462.  
  463. VOID convert(fpin,fpout)        /* convert each 3 chars to 4 */
  464. FILE *fpin, *fpout;
  465. {
  466.     int n;
  467.     int fill_nulls = 0;
  468.     UCHAR inbuf[10], outbuf[10];
  469.  
  470.     while( (n = get3(fpin,inbuf)) != 0 )
  471.         {
  472.         if( n < 0 )        /* bunch of nulls */
  473.             {
  474.             outbuf[0] = '~' ;
  475.             outbuf[1] = tochar( -n );
  476.  
  477.             output(fpout,outbuf,2);
  478.             }
  479.         else    {
  480.             while( n < 3 )
  481.                 {
  482.                 inbuf[n++] = '\0' ;
  483.                 fill_nulls++ ;
  484.                 }
  485.  
  486.             boo( inbuf , outbuf );
  487.  
  488.             output(fpout,outbuf,4);
  489.             }
  490.         }
  491.  
  492.     if( fill_nulls > 0 )
  493.         {
  494.         if( !quiet )
  495.             fprintf(stderr,"Fill Nulls = %d\n",fill_nulls);
  496.  
  497. /*        strcpy( outbuf , "~0" );    */
  498.         outbuf[0] = '~' ;        /* redone w/o strcpy... */
  499.         outbuf[1] = '0' ;
  500.         outbuf[2] = '\0' ;
  501.  
  502.         while( fill_nulls-- > 0 )
  503.             {
  504.             output(fpout,outbuf,2);
  505.             }
  506.         }
  507.     output(fpout, (UCHAR *)"", -1);    /* make sure last line is \n termed */
  508. }
  509.  
  510. int get3( fp , buf )    /* return: pos=# read, neg=# nulls found */
  511. FILE *fp;
  512. UCHAR *buf;
  513. {
  514.     int i=0;        /* amt last read */
  515.     int nulls=0;        /* amt nulls found */
  516.     int c;
  517.  
  518.     do    {
  519.         if( (c = getc(fp)) == EOF )        /* hit eof */
  520.             {
  521.             if( ferror(fp) )        /* quick check */
  522.                 {
  523.                 fprintf(stderr,
  524.                     "get3(): fread error on input file\n");
  525.                 exit(EXIT_BAD);
  526.                 }
  527.             break;                /* stop */
  528.             }
  529.         count_in++;
  530.  
  531.         if( (nulls > 0) && (c != '\0') )    /* stop collecting */
  532.             {
  533.             if( nulls < MINNULLCOMP )
  534.                 {        /* correct for too few nulls */
  535.                 i = nulls + 1 ;        /* nulls + new char */
  536.                 while( nulls-- > 0 )    /* restore null data */
  537.                     *buf++ = '\0' ;
  538.                 *buf++ = c ;        /* store curr char */
  539.                 }
  540.             else    {
  541.                 ungetc(c,fp);        /* save non-null */
  542.                 count_in--;
  543.                 break;
  544.                 }
  545.             }
  546.         else if( (i == 0) && (c == '\0') )    /* collect */
  547.             {
  548.             nulls++ ;            /* keep collecting */
  549.             }
  550.         else    {
  551.             i++;                /* count till 3 */
  552.             *buf++ = c ;            /* save chars */
  553.             }
  554.  
  555.         } while( (i <= 2) && (nulls <= MAXNULLCOMP) );
  556.  
  557.     if( nulls > MAXNULLCOMP )
  558.         {
  559.         ungetc(c,fp);        /* save the 79th null for next time */
  560.         nulls--;
  561.         count_in--;
  562.         }
  563.  
  564.     if( nulls > 0 )
  565.         return( -nulls );
  566.  
  567.     return(i);
  568. }
  569.  
  570.  
  571. VOID output(fp,buf,n)    /* output chars taking care of line wraps */
  572. FILE *fp;        /* we are keeping output quads on the same line */
  573. UCHAR *buf;
  574. int n;        /* -1 is flag to end last line with \n if its not already */
  575. {
  576.     static outlen=0;
  577.  
  578.     if( ((n < 0) && (outlen != 0)) || ((outlen+n) > MAXOUTLEN) )
  579.         {
  580.         writechars(fp,"\n",1);
  581.         outlen=0;
  582.         }
  583.  
  584.     if( n > 0 )
  585.         {
  586.         outlen += n;
  587.         writechars(fp,(char *)buf,n);
  588.         }
  589. }
  590.  
  591. VOID writechars( fp, s, n )            /* n==0 = flush */
  592. char *s;
  593. int n;
  594. FILE *fp;
  595. {
  596.     static char buf[BUFSIZ];
  597.     static char *p=buf;
  598.     int flush = (n==0) ;
  599.     unsigned count;
  600.  
  601.     if( (p+n) >= (buf+sizeof(buf)) )
  602.         {
  603.         fprintf(stderr,
  604.             "writechars: error would exceed output buffer\n");
  605.         exit(EXIT_BAD);
  606.         }
  607.  
  608.     while( n-- > 0 )
  609.         *p++ = *s++ ;
  610.  
  611.     /* we know there is a \n at the end of the ~73 char lines! */
  612.  
  613.     if( flush || (p[-1] == '\n') )        /* time to dump buffer */
  614.         {
  615.         if( (count = p-buf) != 0 )
  616.             {
  617.             /* this must be "p-buf,1" ordered here for VMS
  618.                varying recs to come out right */
  619.             count_out += count ;
  620. #if 0                        /* Ignore the nl's for now */
  621. #if MSDOS
  622.             if( !flush )        /* MSDOS does \r\n not \n */
  623.                 count_out++ ;
  624. #endif
  625. #endif
  626.             if( fwrite( buf , count , 1 , fp ) != 1 )
  627.                 {
  628.                 fprintf(stderr,
  629.                 "writechars(): fwrite error on output file\n");
  630.                 exit(EXIT_BAD);
  631.                 }
  632.             p = buf ;
  633.             }
  634.         if( flush )
  635.             fflush(fp);
  636.         }
  637. }
  638.  
  639. VOID writexstr(fp,s,t)            /* write uppercased string */
  640. FILE *fp;
  641. char *s;
  642. int t;                    /* type of case change */
  643. {
  644.     int i;
  645.     char buf[BUFSIZ], *p;
  646.  
  647. /*
  648.     i=strlen(s);
  649.     if( i > BUFSIZ )        * make sure name is sane length *
  650.         i = BUFSIZ ;
  651.     s[i] = '\0' ;
  652.     strcpy(buf,s);
  653. */
  654.                     /* redone w/o strlen & strcpy... */
  655.     i = BUFSIZ - 1;            /* watch buffer overrun */
  656.     p = buf;
  657.     while( (i-- > 0) && ((*p = *s++) != '\0') )
  658.         p++ ;
  659.     *p = '\0' ;            /* make sure there's a null */
  660.     i = p-buf;            /* strlen */
  661.  
  662.     change_case(buf,t);        /* change case as appropriate */
  663.     writechars(fp,buf,i);
  664.     writechars(fp,"\n",1);
  665. }
  666.  
  667.  
  668. VOID boo( inbuf , outbuf )    /* here is where we boo 3 into 4 chars */
  669. UCHAR *inbuf, *outbuf;
  670. {
  671.     UCHAR x,y,z,a,b,c,d;
  672.  
  673.     /* get x,y,z the 3 input bytes */
  674.  
  675.     x = *inbuf++;
  676.     y = *inbuf++;
  677.     z = *inbuf;
  678.  
  679.     /* generate a,b,c,d the 4 output bytes */
  680.  
  681.     a = x >> 2 ;
  682.     b = ( (x << 4) | (y >> 4) ) & 077 ;
  683.     c = ( (y << 2) | (z >> 6) ) & 077 ;
  684.     d = z & 077 ;
  685.  
  686.     *outbuf++ = tochar(a);
  687.     *outbuf++ = tochar(b);
  688.     *outbuf++ = tochar(c);
  689.     *outbuf   = tochar(d);
  690. }
  691.  
  692.  
  693. VOID change_case(s,t)
  694. char *s;
  695. int t;
  696. {
  697.     if( t != CHANGE_UPPER && t != CHANGE_LOWER && t != CHANGE_NONE )
  698.         {
  699.         fprintf(stderr,"Error, bad case change type\n");
  700.         exit(EXIT_BAD);
  701.         }
  702.  
  703.     while( *s )
  704.         {
  705.         if( ((t==CHANGE_UPPER) && ( (*s >= 'a') && (*s <= 'z') )) ||
  706.             ((t==CHANGE_LOWER) && ( (*s >= 'A') && (*s <= 'Z') )) )
  707.             *s ^= 040;
  708.         s++;
  709.         }
  710. }
  711.  
  712. /*
  713.   [EOF]
  714. */
  715.  
  716.