home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / utilslib / utils_old / c / Popen < prev    next >
Encoding:
Text File  |  1994-02-22  |  6.7 KB  |  393 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. static int os_cmd (char *);
  12. static int cmp_cmd (char *, char *);
  13.  
  14. #define MAX_PIPE 20
  15.  
  16. typedef enum
  17. {
  18.     unopened = 0,
  19.     reading,
  20.     writing
  21. }
  22. pipemode;
  23.  
  24. static struct pipe
  25. {
  26.     char *command;    /* The command being executed        */
  27.     char *name;    /* The name of the pipe file        */
  28.     FILE *fd;    /* The file used as a pipe        */
  29.     pipemode pmode;    /* The open mode of the pipe        */
  30.     int retval;    /* The return value of the command    */
  31. }
  32. pipes[MAX_PIPE];
  33.  
  34. FILE *popen (char *command, char *mode)
  35. {
  36.     FILE *current;
  37.     char *name;
  38.     int i;
  39.     pipemode curmode;
  40.     int rval = -1;
  41.     char tmp[11];
  42.  
  43.     /* decide on mode */
  44.     if ( mode[1] != 0 )
  45.         return NULL;
  46.     else if ( *mode == 'r' )
  47.         curmode = reading;
  48.     else if ( *mode == 'w' )
  49.         curmode = writing;
  50.     else
  51.         return NULL;
  52.  
  53.     /* Get a slot in the pipes structure */
  54.     for ( i = 0; i < MAX_PIPE; ++i )
  55.     {
  56.         if ( pipes[i].pmode == unopened )
  57.             break;
  58.     }
  59.  
  60.     if ( i >= MAX_PIPE )
  61.         return NULL;
  62.  
  63.     /* Get a file name to use */
  64.     sprintf(tmp, "Pipe%.2d", i);
  65.     name = mktemp(tmp);
  66.  
  67.     if ( name == NULL )
  68.         return NULL;
  69.  
  70.     /*
  71.      * If we're reading, just call system() to get a file filled
  72.      * with output.
  73.      */
  74.  
  75.     if ( curmode == reading )
  76.     {
  77.         char *tmpname;
  78.         int oscmd = os_cmd(command);
  79.         char cmd[256];
  80.         int n;
  81.  
  82.         if (*command == '%')
  83.         {
  84.             oscmd = 1;
  85.             ++command;
  86.         }
  87.  
  88.         if (!oscmd)
  89.         {
  90.             char *s;
  91.  
  92.             while (*command && isspace(*command))
  93.                 ++command;
  94.  
  95.             s = command;
  96.  
  97.             while (*s && !isspace(*s))
  98.                 ++s;
  99.             
  100.             n = sprintf(cmd, "%.*s > %s%s",
  101.                 s - command, command, name, s);
  102.         }
  103.         else
  104.         {
  105.             tmpname = mktemp("PipeTmp");
  106.  
  107.             if (tmpname == NULL)
  108.             {
  109.                 free(name);
  110.                 return NULL;
  111.             }
  112.  
  113.             n = sprintf(cmd, "%s{ > %s }", command, tmpname);
  114.         }
  115.  
  116.         /* Emergency! Overflow in command buffer! */
  117.         if (n > 255)
  118.         {
  119.             if (oscmd)
  120.             {
  121.                 remove(tmpname);
  122.                 free(tmpname);
  123.             }
  124.             free(name);
  125.             return NULL;
  126.         }
  127.  
  128.         _kernel_setenv("Sys$ReturnCode", "0");
  129.         rval = system(cmd);
  130.  
  131.         if (rval == _kernel_ERROR)
  132.         {
  133.             remove(tmpname);
  134.             free(tmpname);
  135.             free(name);
  136.             return NULL;
  137.         }
  138.  
  139.         if (oscmd)
  140.         {
  141.             int ch;
  142.             FILE *in = fopen(tmpname, "r");
  143.             FILE *out = fopen(name, "w");
  144.  
  145.             if (in == NULL || out == NULL)
  146.             {
  147.                 remove(tmpname);
  148.                 free(tmpname);
  149.                 free(name);
  150.                 return NULL;
  151.             }
  152.  
  153.             /* Strip out CRs from the output */
  154.             while ((ch = getc(in)) != EOF && !ferror(out))
  155.             {
  156.                 if (ch != '\r')
  157.                     putc(ch, out);
  158.             }
  159.  
  160.             /* Did we succeed? */
  161.             ch = (ferror(in) || ferror(out));
  162.  
  163.             /* Tidy up */
  164.             fclose(in);
  165.             fclose(out);
  166.             remove(tmpname);
  167.             free(tmpname);
  168.  
  169.             if (ch)
  170.             {
  171.                 free(name);
  172.                 return NULL;
  173.             }
  174.         }
  175.  
  176.         if ( (current = fopen(name,"r")) == NULL )
  177.         {
  178.             free(name);
  179.             return NULL;
  180.         }
  181.     }
  182.     else
  183.     {
  184.         if ( (current = fopen(name,"w")) == NULL )
  185.         {
  186.             free(name);
  187.             return NULL;
  188.         }
  189.     }
  190.  
  191.     pipes[i].command = strdup(command);
  192.     pipes[i].name = name;
  193.     pipes[i].fd = current;
  194.     pipes[i].pmode = curmode;
  195.     pipes[i].retval = rval;
  196.     return current;
  197. }
  198.  
  199. int pclose (FILE *current)
  200. {
  201.     int rval;
  202.     int i;
  203.  
  204.     /* Get the appropriate slot in thbe pipes structure */
  205.     for ( i = 0; i < MAX_PIPE; ++i )
  206.     {
  207.         if ( pipes[i].fd == current )
  208.             break;
  209.     }
  210.  
  211.     if ( i >= MAX_PIPE )
  212.         return -1;
  213.  
  214.     if ( pipes[i].pmode == reading )
  215.     {
  216.         /* Input pipes are just files we're done with */
  217.         rval = pipes[i].retval;
  218.         fclose(current);
  219.         remove(pipes[i].name);
  220.     }
  221.     else
  222.     {
  223.         /*
  224.          * Output pipes are temporary files we have
  225.          * to cram down the throats of programs.
  226.          */
  227.         char *command = pipes[i].command;
  228.         int oscmd = os_cmd(command);
  229.         int n;
  230.         char cmd[256];
  231.  
  232.         if (*command == '%')
  233.         {
  234.             oscmd = 1;
  235.             ++command;
  236.         }
  237.  
  238.         /* Close the pipe file */
  239.         fclose(current);
  240.  
  241.         /* Create the required command string */
  242.         if (oscmd)
  243.             n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
  244.         else
  245.         {
  246.             char *s;
  247.  
  248.             while (*command && isspace(*command))
  249.                 ++command;
  250.  
  251.             s = command;
  252.  
  253.             while (*s && !isspace(*s))
  254.                 ++s;
  255.             
  256.             n = sprintf(cmd, "%.*s < %s%s",
  257.                 s - command, command, pipes[i].name, s);
  258.         }
  259.  
  260.         /* Check for overflow in command buffer */
  261.         if (n > 255)
  262.             rval = -1;
  263.         else
  264.         {
  265.             _kernel_setenv("Sys$ReturnCode", "0");
  266.             rval = system(cmd);
  267.         }
  268.  
  269.         remove(pipes[i].name);
  270.     }
  271.  
  272.     /* clean up current pipe */
  273.     pipes[i].pmode = unopened;
  274.     free(pipes[i].name);
  275.     free(pipes[i].command);
  276.     return rval;
  277. }
  278.  
  279. /* Check whether a command is an OS command (binary search on the table
  280.  * os_commands of valid OS commands).
  281.  */
  282.  
  283. static char *os_commands[] =
  284. {
  285.     "access",    "adfs",        "alphabet",    "alphabets",
  286.     "append",    "audio",    "basic",    "breakclr",
  287.     "breaklist",    "breakset",    "build",    "cat",
  288.     "cdir",        "channelvoice",    "close",    "configure",
  289.     "continue",    "copy",        "count",    "countries",
  290.     "country",    "create",    "debug",    "delete",
  291.     "deskfs",    "dir",        "dump",        "echo",
  292.     "enumdir",    "error",    "eval",        "ex",
  293.     "exec",        "fileinfo",    "fontcat",    "fontlist",
  294.     "fx",        "go",        "gos",        "help",
  295.     "iconsprites",    "if",        "ignore",    "info",
  296.     "initstore",    "key",        "keyboard",    "lcat",
  297.     "lex",        "lib",        "list",        "load",
  298.     "memory",    "memorya",    "memoryi",    "modules",
  299.     "obey",        "opt",        "poduleload",    "podules",
  300.     "podulesave",    "pointer",    "print",    "qsound",
  301.     "quit",        "ram",        "remove",    "rename",
  302.     "rmclear",    "rmensure",    "rmfaster",    "rmkill",
  303.     "rmload",    "rmreinit",    "rmrun",    "rmtidy",
  304.     "rommodules",    "run",        "save",        "schoose",
  305.     "scopy",    "screenload",    "screensave",    "sdelete",
  306.     "set",        "seteval",    "setmacro",    "settype",
  307.     "sflipx",    "sflipy",    "sget",        "shadow",
  308.     "shellcli",    "show",        "showregs",    "shut",
  309.     "shutdown",    "sinfo",    "slist",    "sload",
  310.     "smerge",    "snew",        "sound",    "speaker",
  311.     "spool",    "spoolon",    "srename",    "ssave",
  312.     "stamp",    "status",    "stereo",    "tempo",
  313.     "time",        "tuning",    "tv",        "type",
  314.     "unplug",    "unset",    "up",        "voices",
  315.     "volume",    "wimppalette",    "wimpslot",    "wimptask",
  316.     "wipe"
  317. };
  318.  
  319. #define NUM_CMDS (sizeof(os_commands) / sizeof(char *))
  320.  
  321. static int os_cmd (char *cmd)
  322. {
  323.     int low = 0;
  324.     int high = NUM_CMDS - 1;
  325.  
  326.     while (low <= high)
  327.     {
  328.         int mid = (high + low) / 2;
  329.         int i = cmp_cmd(cmd,os_commands[mid]);
  330.  
  331.         if (i == 0)
  332.             return 1;
  333.         else if (i < 0)
  334.             high = mid - 1;
  335.         else
  336.             low = mid + 1;
  337.     }
  338.  
  339.     return 0;
  340. }
  341.  
  342. static int cmp_cmd (char *cmd, char *name)
  343. {
  344.     while (*name && tolower(*cmd) == *name)
  345.         ++name, ++cmd;
  346.  
  347.     if (*name)
  348.         return (tolower(*cmd) - *name);
  349.  
  350.     return (*cmd != '\0' && !isspace(*cmd));
  351. }
  352.  
  353. #ifdef test
  354. int main (int argc, char *argv[])
  355. {
  356.     FILE *fp;
  357.     char *cmd;
  358.  
  359.     if (argc <= 1)
  360.     {
  361.         printf("Usage Popen [cmd or Popen ]cmd\n");
  362.         return 0;
  363.     }
  364.  
  365.     cmd = argv[1];
  366.  
  367.     if (*cmd++ == ']')
  368.     {
  369.         fp = popen(cmd,"w");
  370.         fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
  371.         pclose(fp);
  372.     }
  373.     else
  374.     {
  375.         char buf[500];
  376.         fp = popen(cmd,"r");
  377.         while (!feof(fp))
  378.         {
  379.             if (!fgets(buf,499,fp))
  380.             {
  381.                 printf("Read error!\n");
  382.                 return 1;
  383.             }
  384.             buf[strlen(buf)-1] = 0;
  385.             printf(">%s<\n", buf);
  386.         }
  387.         pclose(fp);
  388.     }
  389.  
  390.     return 0;
  391. }
  392. #endif
  393.