home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 103_01 / ndio.c < prev    next >
Text File  |  1985-03-10  |  8KB  |  320 lines

  1. /* 6 MAY 81 */
  2.  
  3. /*
  4.     Directed I/O package for use with BDS C v1.4x.
  5.  
  6.     The following functions make up the directed I/O library:
  7.  
  8.     1. dioinit(&argc,argv)        Make this the first thing you do in
  9.                     your "main" function, to process
  10.                     redirection commands on the CP/M
  11.                     command line.
  12.  
  13.     2. getchar()            Gets a character from the keyboard,
  14.                     or from a directed input file if one
  15.                     was specified on the command line.
  16.  
  17.     3. putchar(c)            Puts a character out to the console,
  18.                     or to a directed output file if one
  19.                     was specified on the command line.
  20.  
  21.     4. dioflush()            Flushes directed output file, if open,
  22.                     and closes all directed I/O files (if
  23.                     any.) This must be called before your
  24.                     program exits or returns to CP/M.
  25.  
  26.     To activate redirection: Four special arguments may be given
  27.     on the command line to the generated COM file...
  28.  
  29.         >foo    causes "putchar" to place characters into the file
  30.             named "foo" instead of to the console.
  31.  
  32.         +foo    like >foo except that the characters are ALSO sent
  33.             to the console.
  34.  
  35.         <foo    causes "getchar" to return characters from the file
  36.             named "foo" instead of from the keyboard.
  37.  
  38.      command |prog    causes the standard output of the command specified in
  39.             "command" to be fed into the standard input of another
  40.             program, "prog". (BOTH "command" and "prog" must be
  41.             compiled with DIO)
  42.  
  43.         )    send to CPM list device
  44.  
  45.         }    send to printer
  46.  
  47.         ]    send to robot-typewriter
  48.  
  49.      (Note that there must never be any spaces between >,+,< or | and the
  50.       corresponding filename.)
  51.  
  52.     You can send the output to more than one thing at once, like so:
  53.         A>prog <infile +)}]>outfile
  54.  
  55.     Thus, a C program using redirection has the following form:
  56.  
  57.         #include "bdscio.h"        /* standard header file    */
  58.         #include "dio.h"        /* directed I/O header    */
  59.  
  60.         ...                /* other externals, if any */
  61.  
  62.         main(argc,argv)
  63.         char **argv;
  64.         {
  65.             ...            /* declarations        */
  66.             dioinit(&argc,argv)    /* initialize redirection */
  67.             ...            /* body of program    */
  68.             dioflush();
  69.         }
  70.             
  71.     NOTES:
  72.  
  73.     0. Redirection and pipes work only for TEXT. This mechanism should
  74.        not be used for binary data.
  75.  
  76.     1. The "getchar" and "putchar" functions should each be used EXPLICITLY
  77.        at least once in your main source file, so that the correct versions
  78.        are picked off from DIO.CRL instead of the incorrect ones from
  79.        DEFF2.CRL (because of the way the linker works.)
  80.  
  81.     2. The "putc" library function should be modified so that an iobuf
  82.        value of 4 sends a character to the CP/M console via a "bdos"
  83.        call (as opposed to using "putchar"), and that a '\n' character
  84.        thus sent should be expanded into a CR-LF combination. This
  85.            is easily accomplished by adding the following clause to the "putc"
  86.        function, recompiling STDLIB1.C, and updating DEFF.CRL by
  87.        transferring in the new "putc" with CLIB.COM:
  88.  
  89.         if (_iobuf == 4) {
  90.             if (c == '\n') bdos(2,'\r');
  91.             bdos(2,c);
  92.         }            
  93.        (This may already have been done in the version you have.)
  94.  
  95.     3. The "execv" function, used by this package, is available in the
  96.        file EXECV.ASM; it should be assembled, renamed EXECV.CRL, and
  97.        then transferred into DEFF2.CRL using CLIB.COM.
  98.        (This may already have been done in the version you have.)
  99.  
  100. */
  101.  
  102. #include "bdscio.h"
  103. #include "dio.h"
  104.  
  105. #define CON_INPUT 1            /* BDOS call to read console       */
  106. #define CON_OUTPUT 2            /* BDOS call to write to console   */
  107. #define CON_STATUS 11            /* BDOS call to interrogate status */
  108.  
  109. #define CONTROL_C 3            /* Quit character           */
  110. #define STDERR 4            /* Standard Error descriptor (sorry,
  111.                        Unix fans, 2 was already used.) */
  112. #define INPIPE 2            /* bit setting to indicate directed
  113.                        input from a temp. pipe fil     */
  114. #define VERBOSE 2            /* bit setting to indicate output is to
  115.                        go to console AND directed output */
  116. #define DIRECTED_OUT 1
  117. #define CONS_TOO 2
  118. #define CPM_LIST_OUT 4
  119. #define PRINTER_OUT 8
  120. #define ROBOTYPE_OUT 16
  121. #define CONSOLE_ONLY 0
  122.  
  123. /* 
  124.     The "dioinit" function must be called at the beginning of the
  125.     "main" function:
  126. */
  127.  
  128. #define argc *argcp
  129.  
  130. dioinit(argcp,argv)
  131. int *argcp;
  132. char **argv;
  133. {
  134.     int i,j, argcount;
  135.     int n;    /* this keeps track of location in argument */
  136.  
  137.     _diflag = _doflag = _pipef = FALSE;  /* No directed I/O by default   */
  138.     _nullpos = &argv[argc];
  139.     argcount = 1;
  140.  
  141.     for (i = 1; i < argc; i++)    /* Scan the command line for > and < */
  142.     {
  143.         if (_pipef) break;
  144.         n=0;    /* start with first character */
  145. getmore:    switch(argv[i][n++]) {
  146.  
  147.            case '<':        /* Check for directed input: */
  148.             if (!argv[i][n]) goto barf;
  149.             if (fopen(&argv[i][n], _dibuf) == ERROR)
  150.             {
  151.                 fprintf(STDERR,"Can't open %s\n",&argv[i][n]);
  152.                 exit();
  153.             }
  154.             _diflag = TRUE;
  155.             if (strcmp(argv[i],"<TEMPIN.$$$") == 0)
  156.                  _diflag |= INPIPE;
  157.             goto movargv;
  158.  
  159.            case '|':    /* Check for pipe: */
  160.             _pipef++;
  161.             _pipedest = &argv[i][n]; /* save prog name for execl */
  162.             if (argv[i][n]) 
  163.             {
  164.                 argv[i] = ".TEMPOUT.$$$";  /* temp. output */
  165.                 _savei = &argv[i];
  166.             }
  167.             goto foo;
  168.  
  169.            case '+': 
  170.             _doflag |= VERBOSE;
  171.             goto getmore;
  172.            case ')':
  173.             _doflag |= CPM_LIST_OUT;
  174.             goto getmore;
  175.            case '}':
  176.             _doflag |= PRINTER_OUT;
  177.             goto getmore;
  178.            case ']':
  179.             _doflag |= ROBOTYPE_OUT;
  180.             goto getmore;
  181.             
  182.          foo:   case '>':    /* Check for directed output    */
  183.         
  184.             if (!argv[i][n]) 
  185.             {
  186.             barf:   fprintf(STDERR,"Bad redirection/pipe specifier");
  187.                 exit();
  188.             }
  189.             strcpy (sav_out_file, &argv[i][n] );
  190.             if (fcreat("TEMPOUT.$$$", _dobuf) == ERROR)
  191.             {
  192.                 fprintf(STDERR,"\nCan't create <%s>\n",
  193.                                                      "TEMPOUT.$$$");
  194.                    exit();
  195.             }
  196.             _doflag++;
  197.  
  198.          movargv:    if (!_pipef) {
  199.                 for (j = i; j < argc; j++) argv[j] = argv[j+1];
  200.                 (argc)--;
  201.                 i--;
  202.                 _nullpos--;
  203.              } else {
  204.                 argc = argcount;
  205.                 argv[argc] = 0;
  206.              }
  207.             break;
  208.  
  209.             default:    /* handle normal arguments: */
  210.                 if (n!=1) goto movargv;
  211.             argcount++;
  212.         }
  213.     }
  214. }
  215.  
  216.  
  217. #undef argc
  218.  
  219. /*
  220.     The "dioflush" function must be called before exiting the program:
  221. */
  222.  
  223. dioflush()
  224. {
  225.     if (_diflag)
  226.     {
  227.         fclose(_dibuf);
  228.         if (_diflag & INPIPE) unlink("tempin.$$$");
  229.     }
  230.  
  231.     if (_doflag)
  232.     {
  233.         putc(CPMEOF,_dobuf);
  234.         fflush(_dobuf);
  235.         fclose(_dobuf);
  236.         if (OK != strcmp ("TEMPOUT.$$$", sav_out_file))
  237.               { unlink (sav_out_file);
  238.             rename ("TEMPOUT.$$$", sav_out_file);
  239.               }
  240.         rename("tempout.$$$","tempin.$$$");
  241.         if (_pipef) 
  242.         {
  243.             *_savei = "<TEMPIN.$$$";
  244.             *_nullpos = NULL;
  245.             execv(_pipedest,_savei);
  246.         }
  247.     }
  248. }
  249.  
  250.  
  251. /*
  252.     This version of "getchar" replaces the regular version when using
  253.     directed I/O:
  254. */
  255.  
  256. getchar()
  257. {
  258.     char c;
  259.  
  260.     if (_diflag) {
  261.         if ((c = getc(_dibuf)) == '\r') c = getc(_dibuf);
  262.     } else
  263.         if ((c = bdos(CON_INPUT)) == CONTROL_C) exit();
  264.  
  265.     if (c == CPMEOF) return EOF;         /* Control-Z is EOF key     */
  266.     if (c == '\r') 
  267.     {
  268.         c = '\n';
  269.         if (!_diflag) bdos(2,'\n');  /* echo LF after CR to console */
  270.     }
  271.     return c;
  272. }
  273.  
  274.  
  275. /*
  276.     This version of "putchar" replaces the regular version when using
  277.     directed I/O:
  278. */
  279.  
  280. putchar(c)
  281. char c;
  282. {
  283.     if (_doflag & DIRECTED_OUT)
  284.     {
  285.         if (c == '\n') putc('\r',_dobuf);
  286.         if(putc(c,_dobuf) == ERROR)
  287.         {
  288.             fprintf(STDERR,"File output error; disk full?\n");
  289.             exit();
  290.         }
  291.     }
  292.  
  293.     if (_doflag==0 || _doflag & CONS_TOO)
  294.     {
  295.     if (bdos(CON_STATUS) && bdos(CON_INPUT) == CONTROL_C) exit();
  296.     if (c == '\n') bdos(CON_OUTPUT,'\r');
  297.     bdos(CON_OUTPUT,c);
  298.     }
  299.  
  300.     if (_doflag & CPM_LIST_OUT)
  301.     {
  302.         bdos(5,c);
  303.         if (c=='\n') bdos(5,'\r');
  304.     }
  305.     if (_doflag & PRINTER_OUT)
  306.     {
  307.         bdos(5,c);
  308.     }
  309.     if (_doflag & ROBOTYPE_OUT)
  310.     {
  311.         fprintf(STDERR,"sending ROBO <%c>    ",c);
  312.     }
  313. }
  314. flag & PRINTER_OUT)
  315.     {
  316.         bdos(5,c);
  317.     }
  318.     if (_doflag & ROBOTYPE_OUT)
  319.     {
  320.         fprintf(STDERR,"sending ROB