home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 446.lha / Popen / popen.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  5KB  |  206 lines

  1. /*
  2. ** popen.c
  3. ** Written by Rick Schaeffer (ricks@isc-br.isc-br.com)
  4. NAME
  5.      popen, pclose - initiate I/O to/from a process
  6.  
  7. SYNOPSIS
  8.      #include <stdio.h>
  9.  
  10.      FILE *popen(command, type)
  11.      char *command, *type;
  12.  
  13.      pclose(stream)
  14.      FILE *stream;
  15.  
  16. DESCRIPTION
  17.      The arguments to popen are pointers to null-terminated
  18.      strings containing respectively a command line and an
  19.      I/O mode, either "r" for reading or "w" for writing.  It
  20.      creates a pipe between the calling process and the command
  21.      to be executed.  The value returned is a stream pointer that
  22.      can be used (as appropriate) to write to the standard input
  23.      of the command or read from its standard output.
  24.  
  25.      A stream opened by popen **MUST** be closed by pclose, which
  26.      waits for the associated process to terminate and returns
  27.      the exit status of the command.
  28.  
  29.      Because stdio files are shared, a type "r" command may be
  30.      used as an input filter, and a type "w" as an output filter.
  31.  
  32. DIAGNOSTICS
  33.      Popen returns a null pointer if files or processes cannot be
  34.      created.
  35.  
  36.      Pclose returns -1 if stream is not associated with a
  37.      `popened' command.
  38.  
  39. */
  40.  
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <exec/types.h>
  44. #include <libraries/dos.h>
  45. #include <libraries/dosextens.h>
  46. #include <proto/dos.h>
  47. #include <proto/exec.h>
  48. #include <arp/arpbase.h>
  49. #include <ios1.h>
  50.  
  51. struct ArpBase                        *ArpBase;
  52. static struct Process                *thistask;
  53. static struct ProcessControlBlock    pcb;
  54.  
  55. struct pstruct {
  56.     FILE    *fptr;
  57.     struct ZombieMsg    exitmsg;
  58.     };
  59.  
  60. struct pstruct poarray[6];
  61.  
  62. FILE *popen(cmd,mode)
  63. char    *cmd;
  64. char    *mode;
  65. {
  66.     char         *parms;
  67.     static char tempname[] = "pipe:pXXX.XXX";
  68.     char         *pname,redir[20],*mktemp();
  69.     short        i;
  70.     int            pmode;
  71.     struct pstruct    *poptr;
  72.     BPTR        pfd;
  73.  
  74.     if (thistask == NULL)
  75.         thistask = (struct Process *) FindTask(NULL);
  76.     if (ArpBase == NULL)
  77.         ArpBase = (struct ArpBase *) OpenLibrary(ArpName,ArpVersion);
  78.     if (ArpBase == NULL) {
  79.         fprintf(stderr,"Arp Open Failed\n");
  80.         return(NULL);
  81.         }
  82.     poptr = NULL;
  83.     for (i=0; i<6; i++) {
  84.         if (poarray[i].fptr == NULL) {
  85.             poptr = &poarray[i];
  86.             break;
  87.             }
  88.         }
  89.     if (poptr == NULL) {
  90.         fprintf(stderr,"popen: Unable to find an open pipe\n");
  91.         return(NULL);
  92.         }
  93.     if (strcmp(mode,"r") == 0)
  94.         pmode = MODE_NEWFILE;
  95.     else if (strcmp(mode,"w") == 0)
  96.         pmode = MODE_OLDFILE;
  97.     else {
  98.         fprintf(stderr,"popen: Mode must be 'r' or 'w'\n");
  99.         return(NULL);
  100.         }
  101.     tempname[5] = 'a' + i;
  102.     strcpy(redir,tempname);
  103.     pname = mktemp(redir);                /* set up a pipe: file name */
  104.  
  105.     setmem(&pcb, sizeof(struct ProcessControlBlock), 0);
  106.     /* Now get the child's stack and priority set up */
  107.     if (thistask->pr_CLI) {
  108.         struct CommandLineInterface        *cli;
  109.         cli = (struct CommandLineInterface *) BADDR(thistask->pr_CLI);
  110.         pcb.pcb_StackSize = cli->cli_DefaultStack << 2;
  111.         }
  112.     else
  113.         pcb.pcb_StackSize = thistask->pr_StackSize;
  114.     pcb.pcb_Pri = thistask->pr_Task.tc_Node.ln_Pri;
  115.     /* Open the side of the pipe for the child */
  116.     pfd = Open(pname,pmode);
  117.     if (pfd == 0) {
  118.         fprintf(stderr,"popen: Unable to open pipe file\n");
  119.         return(NULL);
  120.         }
  121.     if (pmode == MODE_NEWFILE)
  122.         pcb.pcb_Output = pfd;
  123.     else
  124.         pcb.pcb_Input = pfd;
  125.  
  126.     /* Locate the break between command and parameters */
  127.     parms = strpbrk(cmd," \t");
  128.     if (parms) {
  129.         *parms++ = 0;
  130.         parms = stpblk(parms);
  131.         if (parms && *parms == 0)
  132.             parms = NULL;
  133.         }
  134.     /* Create a port for the child's exit message */
  135.     poptr->exitmsg.zm_ExecMessage.mn_ReplyPort = CreatePort(NULL,0);
  136.     if (poptr->exitmsg.zm_ExecMessage.mn_ReplyPort == 0) {
  137.         fprintf(stderr,"popen: Couldn't create message port\n");
  138.         return(NULL);
  139.         }
  140.     pcb.pcb_LastGasp = &poptr->exitmsg;
  141.  
  142.     if (ASyncRun(cmd,parms,&pcb) < 0) {
  143.         fprintf(stderr,"popen: AsyncRun failed\n");
  144.         DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
  145.         return(NULL);
  146.         }
  147.     /* Now open our side of the pipe */
  148.     poptr->fptr = fopen(pname,mode);
  149.     if (poptr->fptr == NULL) {
  150.         fprintf(stderr,"popen: Unable to open pipe file %s\n",pname);
  151.         DeletePort(poptr->exitmsg.zm_ExecMessage.mn_ReplyPort);
  152.         return(NULL);
  153.         }
  154.     return(poptr->fptr);
  155. }
  156.  
  157. pclose(fptr)
  158. FILE    *fptr;
  159. {
  160.     short        i;
  161.  
  162.     for (i=0; i<6; i++)
  163.         if (poarray[i].fptr == fptr)
  164.             break;
  165.     if (i > 5) {
  166.         fprintf(stderr,"popen: DISASTER...couldn't find file pointer in pclose\n");
  167.         exit(1);
  168.         }
  169.     fclose(fptr);
  170.     WaitPort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
  171.     poarray[i].fptr = NULL;
  172.     DeletePort(poarray[i].exitmsg.zm_ExecMessage.mn_ReplyPort);
  173.     return(poarray[i].exitmsg.zm_ReturnCode);
  174. }
  175.  
  176. char *mktemp(template)
  177. char *template;
  178. {
  179.     register char *cp;
  180.     register unsigned long val;
  181.  
  182.     cp = template;
  183.     cp += strlen(cp);
  184.     for (val = (unsigned long) FindTask(0L) ; ; )
  185.         if (*--cp == 'X') {
  186.             *cp = val%10 + '0';
  187.             val /= 10;
  188.         } else if (*cp != '.')
  189.             break;
  190.  
  191.     if (*++cp != 0) {
  192.         *cp = 'A';
  193.         while (access(template, 0) == 0) {
  194.             if (*cp == 'Z') {
  195.                 *template = 0;
  196.                 break;
  197.             }
  198.             ++*cp;
  199.         }
  200.     } else {
  201.         if (access(template, 0) == 0)
  202.             *template = 0;
  203.     }
  204.     return template;
  205. }
  206.