home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / utilslib / c / Popen < prev    next >
Encoding:
Text File  |  1991-05-12  |  4.8 KB  |  318 lines

  1. /* C.Popen: Simulation of pipes */
  2.  
  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "kernel.h"
  8.  
  9. #include "utils.h"
  10.  
  11. extern int _os_cmd (char *);
  12.  
  13. #define MAX_PIPE 20
  14.  
  15. typedef enum
  16. {
  17.     unopened = 0,
  18.     reading,
  19.     writing
  20. }
  21. pipemode;
  22.  
  23. static struct pipe
  24. {
  25.     char *command;    /* The command being executed        */
  26.     char *name;    /* The name of the pipe file        */
  27.     FILE *fd;    /* The file used as a pipe        */
  28.     pipemode pmode;    /* The open mode of the pipe        */
  29.     int retval;    /* The return value of the command    */
  30. }
  31. pipes[MAX_PIPE];
  32.  
  33. FILE *popen (char *command, char *mode)
  34. {
  35.     FILE *current;
  36.     char *name;
  37.     int i;
  38.     pipemode curmode;
  39.     int rval = -1;
  40.     char tmp[11];
  41.  
  42.     /* decide on mode */
  43.     if ( mode[1] != 0 )
  44.         return NULL;
  45.     else if ( *mode == 'r' )
  46.         curmode = reading;
  47.     else if ( *mode == 'w' )
  48.         curmode = writing;
  49.     else
  50.         return NULL;
  51.  
  52.     /* Get a slot in the pipes structure */
  53.     for ( i = 0; i < MAX_PIPE; ++i )
  54.     {
  55.         if ( pipes[i].pmode == unopened )
  56.             break;
  57.     }
  58.  
  59.     if ( i >= MAX_PIPE )
  60.         return NULL;
  61.  
  62.     /* Get a file name to use */
  63.     sprintf(tmp, "Pipe%.2d", i);
  64.     name = mktemp(tmp);
  65.  
  66.     if ( name == NULL )
  67.         return NULL;
  68.  
  69.     /*
  70.      * If we're reading, just call system() to get a file filled
  71.      * with output.
  72.      */
  73.  
  74.     if ( curmode == reading )
  75.     {
  76.         char *tmpname;
  77.         int oscmd = _os_cmd(command);
  78.         char cmd[256];
  79.         int n;
  80.  
  81.         if (*command == '%')
  82.         {
  83.             oscmd = 1;
  84.             ++command;
  85.         }
  86.  
  87.         if (!oscmd)
  88.         {
  89.             char *s;
  90.  
  91.             while (*command && isspace(*command))
  92.                 ++command;
  93.  
  94.             s = command;
  95.  
  96.             while (*s && !isspace(*s))
  97.                 ++s;
  98.             
  99.             n = sprintf(cmd, "%.*s > %s%s",
  100.                 s - command, command, name, s);
  101.         }
  102.         else
  103.         {
  104.             tmpname = mktemp("PipeTmp");
  105.  
  106.             if (tmpname == NULL)
  107.             {
  108.                 free(name);
  109.                 return NULL;
  110.             }
  111.  
  112.             n = sprintf(cmd, "%s{ > %s }", command, tmpname);
  113.         }
  114.  
  115.         /* Emergency! Overflow in command buffer! */
  116.         if (n > 255)
  117.         {
  118.             if (oscmd)
  119.             {
  120.                 remove(tmpname);
  121.                 free(tmpname);
  122.             }
  123.             free(name);
  124.             return NULL;
  125.         }
  126.  
  127.         _kernel_setenv("Sys$ReturnCode", "0");
  128.         rval = system(cmd);
  129.  
  130.         if (rval == _kernel_ERROR)
  131.         {
  132.             remove(tmpname);
  133.             free(tmpname);
  134.             free(name);
  135.             return NULL;
  136.         }
  137.  
  138.         if (oscmd)
  139.         {
  140.             int ch;
  141.             FILE *in = fopen(tmpname, "r");
  142.             FILE *out = fopen(name, "w");
  143.  
  144.             if (in == NULL || out == NULL)
  145.             {
  146.                 remove(tmpname);
  147.                 free(tmpname);
  148.                 free(name);
  149.                 return NULL;
  150.             }
  151.  
  152.             /* Strip out CRs from the output */
  153.             while ((ch = getc(in)) != EOF && !ferror(out))
  154.             {
  155.                 if (ch != '\r')
  156.                     putc(ch, out);
  157.             }
  158.  
  159.             /* Did we succeed? */
  160.             ch = (ferror(in) || ferror(out));
  161.  
  162.             /* Tidy up */
  163.             fclose(in);
  164.             fclose(out);
  165.             remove(tmpname);
  166.             free(tmpname);
  167.  
  168.             if (ch)
  169.             {
  170.                 free(name);
  171.                 return NULL;
  172.             }
  173.         }
  174.  
  175.         if ( (current = fopen(name,"r")) == NULL )
  176.         {
  177.             free(name);
  178.             return NULL;
  179.         }
  180.     }
  181.     else
  182.     {
  183.         if ( (current = fopen(name,"w")) == NULL )
  184.         {
  185.             free(name);
  186.             return NULL;
  187.         }
  188.     }
  189.  
  190.     pipes[i].command = strdup(command);
  191.     pipes[i].name = name;
  192.     pipes[i].fd = current;
  193.     pipes[i].pmode = curmode;
  194.     pipes[i].retval = rval;
  195.     return current;
  196. }
  197.  
  198. int pclose (FILE *current)
  199. {
  200.     int rval;
  201.     int i;
  202.  
  203.     /* Get the appropriate slot in thbe pipes structure */
  204.     for ( i = 0; i < MAX_PIPE; ++i )
  205.     {
  206.         if ( pipes[i].fd == current )
  207.             break;
  208.     }
  209.  
  210.     if ( i >= MAX_PIPE )
  211.         return -1;
  212.  
  213.     if ( pipes[i].pmode == reading )
  214.     {
  215.         /* Input pipes are just files we're done with */
  216.         rval = pipes[i].retval;
  217.         fclose(current);
  218.         remove(pipes[i].name);
  219.     }
  220.     else
  221.     {
  222.         /*
  223.          * Output pipes are temporary files we have
  224.          * to cram down the throats of programs.
  225.          */
  226.         char *command = pipes[i].command;
  227.         int oscmd = _os_cmd(command);
  228.         int n;
  229.         char cmd[256];
  230.  
  231.         if (*command == '%')
  232.         {
  233.             oscmd = 1;
  234.             ++command;
  235.         }
  236.  
  237.         /* Close the pipe file */
  238.         fclose(current);
  239.  
  240.         /* Create the required command string */
  241.         if (oscmd)
  242.             n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
  243.         else
  244.         {
  245.             char *s;
  246.  
  247.             while (*command && isspace(*command))
  248.                 ++command;
  249.  
  250.             s = command;
  251.  
  252.             while (*s && !isspace(*s))
  253.                 ++s;
  254.             
  255.             n = sprintf(cmd, "%.*s < %s%s",
  256.                 s - command, command, pipes[i].name, s);
  257.         }
  258.  
  259.         /* Check for overflow in command buffer */
  260.         if (n > 255)
  261.             rval = -1;
  262.         else
  263.         {
  264.             _kernel_setenv("Sys$ReturnCode", "0");
  265.             rval = system(cmd);
  266.         }
  267.  
  268.         remove(pipes[i].name);
  269.     }
  270.  
  271.     /* clean up current pipe */
  272.     pipes[i].pmode = unopened;
  273.     free(pipes[i].name);
  274.     free(pipes[i].command);
  275.     return rval;
  276. }
  277.  
  278. #ifdef test
  279. int main (int argc, char *argv[])
  280. {
  281.     FILE *fp;
  282.     char *cmd;
  283.  
  284.     if (argc <= 1)
  285.     {
  286.         printf("Usage Popen [cmd or Popen ]cmd\n");
  287.         return 0;
  288.     }
  289.  
  290.     cmd = argv[1];
  291.  
  292.     if (*cmd++ == ']')
  293.     {
  294.         fp = popen(cmd,"w");
  295.         fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
  296.         pclose(fp);
  297.     }
  298.     else
  299.     {
  300.         char buf[500];
  301.         fp = popen(cmd,"r");
  302.         while (!feof(fp))
  303.         {
  304.             if (!fgets(buf,499,fp))
  305.             {
  306.                 printf("Read error!\n");
  307.                 return 1;
  308.             }
  309.             buf[strlen(buf)-1] = 0;
  310.             printf(">%s<\n", buf);
  311.         }
  312.         pclose(fp);
  313.     }
  314.  
  315.     return 0;
  316. }
  317. #endif
  318.