home *** CD-ROM | disk | FTP | other *** search
- /*
- ** popen.c
- ** Written by Rick Schaeffer (ricks@isc-br.isc-br.com)
- NAME
- popen, pclose - initiate I/O to/from a process
-
- SYNOPSIS
- #include <stdio.h>
-
- FILE *popen(command, type)
- char *command, *type;
-
- pclose(stream)
- FILE *stream;
-
- DESCRIPTION
- The arguments to popen are pointers to null-terminated
- strings containing respectively a command line and an
- I/O mode, either "r" for reading or "w" for writing. It
- creates a pipe between the calling process and the command
- to be executed. The value returned is a stream pointer that
- can be used (as appropriate) to write to the standard input
- of the command or read from its standard output.
-
- A stream opened by popen **MUST** be closed by pclose, which
- waits for the associated process to terminate and returns
- the exit status of the command.
-
- Because stdio files are shared, a type "r" command may be
- used as an input filter, and a type "w" as an output filter.
-
- DIAGNOSTICS
- Popen returns a null pointer if files or processes cannot be
- created.
-
- Pclose returns -1 if stream is not associated with a
- `popened' command.
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <arp/arpbase.h>
- #include <ios1.h>
-
- struct ArpBase *ArpBase;
- static struct Process *thistask;
- static struct ProcessControlBlock pcb;
-
- struct pstruct {
- FILE *fptr;
- struct ZombieMsg exitmsg;
- };
-
- struct pstruct poarray[6];
-
- FILE *popen(cmd,mode)
- char *cmd;
- char *mode;
- {
- char *parms;
- static char tempname[] = "pipe:pXXX.XXX";
- char *pname,redir[20],*mktemp();
- short i;
- int pmode;
- struct pstruct *poptr;
- BPTR pfd;
-
- if (thistask == NULL)
- thistask = (struct Process *) FindTask(NULL);
- if (ArpBase == NULL)
- ArpBase = (struct ArpBase *) OpenLibrary(ArpName,ArpVersion);
- if (ArpBase == NULL) {
- fprintf(stderr,"Arp Open Failed\n");
- return(NULL);
- }
- poptr = NULL;
- for (i=0; i<6; i++) {
- if (poarray[i].fptr == NULL) {
- poptr = &poarray[i];
- break;
- }
- }
- if (poptr == NULL) {
- fprintf(stderr,"popen: Unable to find an open pipe\n");
- return(NULL);
- }
- if (strcmp(mode,"r") == 0)
- pmode = MODE_NEWFILE;
- else if (strcmp(mode,"w") == 0)
- pmode = MODE_OLDFILE;
- else {
- fprintf(stderr,"popen: Mode must be 'r' or 'w'\n");
- return(NULL);
- }
- tempname[5] = 'a' + i;
- strcpy(redir,tempname);
- pname = mktemp(redir); /* set up a pipe: file name */
-
- setmem(&pcb, sizeof(struct ProcessControlBlock), 0);
- /* Now get the child's stack and priority set up */
- if (thistask->pr_CLI) {
- struct CommandLineInterface *cli;
- cli = (struct CommandLineInterface *) BADDR(thistask->pr_CLI);
- pcb.pcb_StackSize = cli->cli_DefaultStack << 2;
- }
- else
- pcb.pcb_StackSize = thistask->pr_StackSize;
- pcb.pcb_Pri = thistask->pr_Task.tc_Node.ln_Pri;
- /* Open the side of the pipe for the child */
- pfd = Open(pname,pmode);
- if (pfd == 0) {
- fprintf(stderr,"popen: Unable to open pipe file\n");
- return(NULL);
- }
- if (pmode == MODE_NEWFILE)
- pcb.pcb_Output = pfd;
- else
- pcb.pcb_Input = pfd;
-
- /* Locate the break between command and parameters */
- parms = strpbrk(cmd," \t");
- if (parms) {
- *parms++ = 0;
- parms = stpblk(parms);
- if (parms && *parms == 0)
- parms = NULL;
- }
- /* Create a port for the child's exit message */
- poptr->exitmsg.zm_ExecMessage.mn_ReplyPort = CreatePort(NULL,0);
- if (poptr->exitmsg.zm_ExecMessage.mn_ReplyPort == 0) {
- fprintf(stderr,"popen: Couldn't create message port\n");
- return(NULL);
- }
- pcb.pcb_LastGasp = &poptr->exitmsg;
-
- if (ASyncRun(cmd,parms,&pcb) < 0) {
- fprintf(stderr,"popen: AsyncRun failed\n");
- DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
- return(NULL);
- }
- /* Now open our side of the pipe */
- poptr->fptr = fopen(pname,mode);
- if (poptr->fptr == NULL) {
- fprintf(stderr,"popen: Unable to open pipe file %s\n",pname);
- DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
- return(NULL);
- }
- return(poptr->fptr);
- }
-
- pclose(fptr)
- FILE *fptr;
- {
- short i;
-
- for (i=0; i<6; i++)
- if (poarray[i].fptr == fptr)
- break;
- if (i > 5) {
- fprintf(stderr,"popen: DISASTER...couldn't find file pointer in pclose\n");
- exit(1);
- }
- fclose(fptr);
- WaitPort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
- poarray[i].fptr = NULL;
- DeletePort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
- return(poarray[i].exitmsg.zm_ReturnCode);
- }
-
- char *mktemp(template)
- char *template;
- {
- register char *cp;
- register unsigned long val;
-
- cp = template;
- cp += strlen(cp);
- for (val = (unsigned long) FindTask(0L) ; ; )
- if (*--cp == 'X') {
- *cp = val%10 + '0';
- val /= 10;
- } else if (*cp != '.')
- break;
-
- if (*++cp != 0) {
- *cp = 'A';
- while (access(template, 0) == 0) {
- if (*cp == 'Z') {
- *template = 0;
- break;
- }
- ++*cp;
- }
- } else {
- if (access(template, 0) == 0)
- *template = 0;
- }
- return template;
- }
-