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"
-
- extern char *mktemp (const char *);
-
- static char *strdup (const char *);
- static int os_cmd (char *);
- static int cmp_cmd (char *, 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;
- }
-
- /* save a string on the heap; return pointer to it */
-
- static char *strdup (const char *str)
- {
- char *p = malloc(strlen(str)+1);
-
- if (p == NULL)
- {
- fprintf(stderr,"Not enough memory to save string\n");
- exit(1);
- }
-
- return (strcpy(p,str));
- }
-
- /* Check whether a command is an OS command (binary search on the table
- * os_commands of valid OS commands).
- */
-
- static char *os_commands[] =
- {
- "access", "adfs", "alphabet", "alphabets",
- "append", "audio", "basic", "breakclr",
- "breaklist", "breakset", "build", "cat",
- "cdir", "channelvoice", "close", "configure",
- "continue", "copy", "count", "countries",
- "country", "create", "debug", "delete",
- "deskfs", "dir", "dump", "echo",
- "enumdir", "error", "eval", "ex",
- "exec", "fileinfo", "fontcat", "fontlist",
- "fx", "go", "gos", "help",
- "iconsprites", "if", "ignore", "info",
- "initstore", "key", "keyboard", "lcat",
- "lex", "lib", "list", "load",
- "memory", "memorya", "memoryi", "modules",
- "obey", "opt", "poduleload", "podules",
- "podulesave", "pointer", "print", "qsound",
- "quit", "ram", "remove", "rename",
- "rmclear", "rmensure", "rmfaster", "rmkill",
- "rmload", "rmreinit", "rmrun", "rmtidy",
- "rommodules", "run", "save", "schoose",
- "scopy", "screenload", "screensave", "sdelete",
- "set", "seteval", "setmacro", "settype",
- "sflipx", "sflipy", "sget", "shadow",
- "shellcli", "show", "showregs", "shut",
- "shutdown", "sinfo", "slist", "sload",
- "smerge", "snew", "sound", "speaker",
- "spool", "spoolon", "srename", "ssave",
- "stamp", "status", "stereo", "tempo",
- "time", "tuning", "tv", "type",
- "unplug", "unset", "up", "voices",
- "volume", "wimppalette", "wimpslot", "wimptask",
- "wipe"
- };
-
- #define NUM_CMDS (sizeof(os_commands) / sizeof(char *))
-
- static int os_cmd (char *cmd)
- {
- int low = 0;
- int high = NUM_CMDS - 1;
-
- while (low <= high)
- {
- int mid = (high + low) / 2;
- int i = cmp_cmd(cmd,os_commands[mid]);
-
- if (i == 0)
- return 1;
- else if (i < 0)
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- return 0;
- }
-
- static int cmp_cmd (char *cmd, char *name)
- {
- while (*name && tolower(*cmd) == *name)
- ++name, ++cmd;
-
- if (*name)
- return (tolower(*cmd) - *name);
-
- return (*cmd != '\0' && !isspace(*cmd));
- }
-
- #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
-