home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
- #include <ios1.h>
- #include <fcntl.h>
- #include <libraries/dosextens.h>
- #include <exec/lists.h>
- #include <exec/nodes.h>
- #include <rsbx/ChildTasking.h>
-
-
- struct pstruct {
- struct MinNode node;
- FILE *fptr1;
- struct ChildNode *child;
- };
-
- static struct MinList PList = { 0 };
-
-
- FILE *popenl(char *args, ...);
- FILE *popenv(char **args, char *mode);
- int pclose(FILE *fptr);
- static char *mktemp(char *template);
-
-
-
- /****** rsbx.lib/popenl() ****************************************************
- *
- * NAME
- * popenl -- Initiate I/O to or from a command.
- *
- * SYNOPSIS
- * pipe = popenl(arg0, ..., argn, NULL, mode)
- *
- * FILE *popenl(char *, char *, ...);
- *
- * FUNCTION
- * Creates a stream between the calling process and the stdin or stdout
- * streams of the command it executes. Mode should be "r" to read
- * the stdout stream of the command, or "w" to write to the stdin
- * stream of the command.
- *
- * INPUTS
- * arg0 - Name of file to execute.
- * ... - Other command line arguments needed by the file to be
- * executed.
- * NULL - Zero.
- * mode _ I/O mode string.
- *
- * RESULT
- * pipe - File pointer to use to read or write to the command
- * with.
- *
- * NOTES
- * A stream opened by popenl() should be closed by pclose().
- *
- * SEE ALSO
- * popenv(), pclose().
- *
- * BUGS
- * This function does not create a complete CLI enviroment for the child
- * process. Use of this function with a command that expects a BCPL
- * environment will crash the system. The Unix function 'popen' takes
- * as arguments a command string which it passes to the shell, and a
- * mode string.
- *
- ******************************************************************************
- *
- */
-
- FILE *popenl(char *args, ...)
- {
- char **nullarg;
-
- for(nullarg = (char **)(&args); *nullarg != 0; nullarg++);
-
- return(popenv(&args, *(nullarg+1)));
- }
-
-
- /****** rsbx.lib/popenv() ****************************************************
- *
- * NAME
- * popenv -- Initiate I/O to or from a command.
- *
- * SYNOPSIS
- * pipe = popenv(argv, mode)
- *
- * FILE *popenv(char **, char *);
- *
- * FUNCTION
- * Creates a stream between the calling process and the stdin or stdout
- * streams of the command it executes. Mode should be "r" to read
- * the stdout stream of the command, or "w" to write to the stdin
- * stream of the command.
- *
- * INPUTS
- * argv - An array of pointer to the argument strings for the
- * command. The last pointer must be followed by a 0
- * pointer. The first pointer, argv[0], is the name of
- * file to execute.
- * mode _ I/O mode string.
- *
- * RESULT
- * pipe - File pointer to use to read or write to the command
- * with.
- *
- * NOTES
- * A stream opened by popenv() should be closed by pclose().
- *
- * SEE ALSO
- * popenl(), pclose().
- *
- * BUGS
- * This function does not create a complete CLI enviroment for the child
- * process. Use of this function with a command that expects a BCPL
- * environment will crash the system. The Unix function 'popen' takes
- * as arguments a command string which it passes to the shell, and a
- * mode string.
- *
- ******************************************************************************
- *
- */
-
- FILE *popenv(char **args, char *mode)
- {
- struct LAUNCHENV env = { 0,0,0,0,0,0,0 };
- static char tempname[] = "pipe:popen.XXXX.XXXXXXXX";
- char *pname;
- char redir[64];
- struct pstruct *poptr;
- char *mode1;
- int mode2;
- int f2;
-
- if (!PList.mlh_Head)
- {
- NewList(&PList);
- }
-
- if ((strcmp(mode,"r") != 0) && (strcmp(mode,"w") != 0))
- {
- fprintf(stderr,"popen: bad mode!\n");
- return(NULL);
- }
-
- if (*mode == 'r')
- {
- mode1 = "r";
- mode2 = MODE_NEWFILE;
- }
- else
- {
- mode1 = "w";
- mode2 = MODE_OLDFILE;
- }
-
- strcpy(redir,tempname);
-
- if (!(poptr = (struct pstruct *)malloc(sizeof(struct pstruct))))
- {
- fprintf(stderr,"popen: Out of memory!\n");
- return(NULL);
- }
-
- if (!(pname = mktemp(redir)))
- {
- fprintf(stderr,"popen: Unable to find an available pipe.\n");
- free(poptr);
- return(NULL);
- }
-
- if (!(poptr->fptr1 = fopen(pname, mode1)))
- {
- fprintf(stderr,"popen: Unable to open pipe end 1 file %s mode %s\n", pname, m
- de);
- free(poptr);
- return(NULL);
- }
-
- if (!(f2 = Open(pname, mode2)))
- {
- fprintf(stderr,"popen: Unable to open pipe end 2 file %s mode %s\n", pname, m
- de);
- fclose(poptr->fptr1);
- free(poptr);
- return(NULL);
- }
-
- env.priority = ((struct Task *)FindTask(NULL))->tc_Node.ln_Pri;
- if (*mode == 'r')
- {
- env.std_out = f2;
- }
- else
- {
- env.std_in = f2;
- }
- env.le_fh1 = f2;
-
- if (!(poptr->child = LaunchChildv(&env, *args, args)))
- {
- fprintf(stderr,"popen: Fork failed\n");
- Close(f2);
- fclose(poptr->fptr1);
- free(poptr);
- return(NULL);
- }
-
- AddTail(&PList, poptr);
-
- return(poptr->fptr1);
- }
-
-
- /****** rsbx.lib/pclose() ****************************************************
- *
- * NAME
- * pclose -- Closes pipe opened by popenl() or by popenv().
- *
- * SYNOPSIS
- * status = pclose(pipe)
- *
- * int pclose(FILE *);
- *
- * FUNCTION
- * Waits for the command associated with the pipe to exit, closes the
- * stream, and returns the return code from the command.
- *
- * INPUTS
- * pipe - Stream pointer returned by a call to popenl() or to
- * popenv().
- *
- * RESULT
- * status - The return code from the command executed, or -1 if
- * pipe wasn't opened by popenl() or by popenv().
- *
- * NOTES
- *
- * SEE ALSO
- * popenl(), popenv().
- *
- * BUGS
- * None known.
- *
- ******************************************************************************
- *
- */
-
- int pclose(FILE *fptr)
- {
- long status;
- struct pstruct *poptr;
-
- for (poptr = (struct pstruct *)PList.mlh_Head;
- poptr->node.mln_Succ;
- poptr = (struct pstruct *)poptr->node.mln_Succ)
- {
- if (poptr->fptr1 == fptr)
- {
- Remove(poptr);
- fclose(poptr->fptr1);
- if (!WaitChild(poptr->child, &status))
- {
- status = -1;
- }
- free(poptr);
- return(status);
- }
- }
-
- return -1;
- }
-
- static unsigned short Generation = 0;
-
- static char *hex = "0123456789abcdef";
-
- static char *mktemp(char *template)
- {
- char *cp;
- unsigned long val;
-
- cp = template;
- cp += strlen(template);
-
- val = (unsigned long) FindTask(0L);
- while (*--cp == 'X')
- {
- *cp = hex[val%16];
- val /= 16;
- }
-
- val = Generation++;
- while (*--cp == 'X')
- {
- *cp = hex[val%16];
- val /= 16;
- }
-
- return template;
- }
-