home *** CD-ROM | disk | FTP | other *** search
- /* C.Popen: Simulation of pipes */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "kernel.h"
-
- #include "utils.h"
-
- extern int _os_cmd (char *);
-
- #define MAX_PIPE 20
-
- typedef enum
- {
- unopened = 0,
- reading,
- writing
- }
- pipemode;
-
- static struct pipe
- {
- char *command; /* The command being executed */
- char *name; /* The name of the pipe file */
- FILE *fd; /* The file used as a pipe */
- pipemode pmode; /* The open mode of the pipe */
- int retval; /* The return value of the command */
- }
- pipes[MAX_PIPE];
-
- FILE *popen (char *command, char *mode)
- {
- FILE *current;
- char *name;
- int i;
- pipemode curmode;
- int rval = -1;
- char tmp[11];
-
- /* decide on mode */
- if ( mode[1] != 0 )
- return NULL;
- else if ( *mode == 'r' )
- curmode = reading;
- else if ( *mode == 'w' )
- curmode = writing;
- else
- return NULL;
-
- /* Get a slot in the pipes structure */
- for ( i = 0; i < MAX_PIPE; ++i )
- {
- if ( pipes[i].pmode == unopened )
- break;
- }
-
- if ( i >= MAX_PIPE )
- return NULL;
-
- /* Get a file name to use */
- sprintf(tmp, "Pipe%.2d", i);
- name = mktemp(tmp);
-
- if ( name == NULL )
- return NULL;
-
- /*
- * If we're reading, just call system() to get a file filled
- * with output.
- */
-
- if ( curmode == reading )
- {
- char *tmpname;
- int oscmd = _os_cmd(command);
- char cmd[256];
- int n;
-
- if (*command == '%')
- {
- oscmd = 1;
- ++command;
- }
-
- if (!oscmd)
- {
- char *s;
-
- while (*command && isspace(*command))
- ++command;
-
- s = command;
-
- while (*s && !isspace(*s))
- ++s;
-
- n = sprintf(cmd, "%.*s > %s%s",
- s - command, command, name, s);
- }
- else
- {
- tmpname = mktemp("PipeTmp");
-
- if (tmpname == NULL)
- {
- free(name);
- return NULL;
- }
-
- n = sprintf(cmd, "%s{ > %s }", command, tmpname);
- }
-
- /* Emergency! Overflow in command buffer! */
- if (n > 255)
- {
- if (oscmd)
- {
- remove(tmpname);
- free(tmpname);
- }
- free(name);
- return NULL;
- }
-
- _kernel_setenv("Sys$ReturnCode", "0");
- rval = system(cmd);
-
- if (rval == _kernel_ERROR)
- {
- remove(tmpname);
- free(tmpname);
- free(name);
- return NULL;
- }
-
- if (oscmd)
- {
- int ch;
- FILE *in = fopen(tmpname, "r");
- FILE *out = fopen(name, "w");
-
- if (in == NULL || out == NULL)
- {
- remove(tmpname);
- free(tmpname);
- free(name);
- return NULL;
- }
-
- /* Strip out CRs from the output */
- while ((ch = getc(in)) != EOF && !ferror(out))
- {
- if (ch != '\r')
- putc(ch, out);
- }
-
- /* Did we succeed? */
- ch = (ferror(in) || ferror(out));
-
- /* Tidy up */
- fclose(in);
- fclose(out);
- remove(tmpname);
- free(tmpname);
-
- if (ch)
- {
- free(name);
- return NULL;
- }
- }
-
- if ( (current = fopen(name,"r")) == NULL )
- {
- free(name);
- return NULL;
- }
- }
- else
- {
- if ( (current = fopen(name,"w")) == NULL )
- {
- free(name);
- return NULL;
- }
- }
-
- pipes[i].command = strdup(command);
- pipes[i].name = name;
- pipes[i].fd = current;
- pipes[i].pmode = curmode;
- pipes[i].retval = rval;
- return current;
- }
-
- int pclose (FILE *current)
- {
- int rval;
- int i;
-
- /* Get the appropriate slot in thbe pipes structure */
- for ( i = 0; i < MAX_PIPE; ++i )
- {
- if ( pipes[i].fd == current )
- break;
- }
-
- if ( i >= MAX_PIPE )
- return -1;
-
- if ( pipes[i].pmode == reading )
- {
- /* Input pipes are just files we're done with */
- rval = pipes[i].retval;
- fclose(current);
- remove(pipes[i].name);
- }
- else
- {
- /*
- * Output pipes are temporary files we have
- * to cram down the throats of programs.
- */
- char *command = pipes[i].command;
- int oscmd = _os_cmd(command);
- int n;
- char cmd[256];
-
- if (*command == '%')
- {
- oscmd = 1;
- ++command;
- }
-
- /* Close the pipe file */
- fclose(current);
-
- /* Create the required command string */
- if (oscmd)
- n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
- else
- {
- char *s;
-
- while (*command && isspace(*command))
- ++command;
-
- s = command;
-
- while (*s && !isspace(*s))
- ++s;
-
- n = sprintf(cmd, "%.*s < %s%s",
- s - command, command, pipes[i].name, s);
- }
-
- /* Check for overflow in command buffer */
- if (n > 255)
- rval = -1;
- else
- {
- _kernel_setenv("Sys$ReturnCode", "0");
- rval = system(cmd);
- }
-
- remove(pipes[i].name);
- }
-
- /* clean up current pipe */
- pipes[i].pmode = unopened;
- free(pipes[i].name);
- free(pipes[i].command);
- return rval;
- }
-
- #ifdef test
- int main (int argc, char *argv[])
- {
- FILE *fp;
- char *cmd;
-
- if (argc <= 1)
- {
- printf("Usage Popen [cmd or Popen ]cmd\n");
- return 0;
- }
-
- cmd = argv[1];
-
- if (*cmd++ == ']')
- {
- fp = popen(cmd,"w");
- fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
- pclose(fp);
- }
- else
- {
- char buf[500];
- fp = popen(cmd,"r");
- while (!feof(fp))
- {
- if (!fgets(buf,499,fp))
- {
- printf("Read error!\n");
- return 1;
- }
- buf[strlen(buf)-1] = 0;
- printf(">%s<\n", buf);
- }
- pclose(fp);
- }
-
- return 0;
- }
- #endif
-