home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / devtools / rpcgen / amiga / popen.c next >
Encoding:
C/C++ Source or Header  |  1994-03-06  |  8.8 KB  |  395 lines

  1. /*------------------------------------------------------------------------*/
  2. /*                                      *
  3.  *  $Id: popen.c,v 1.3 1993/10/05 21:40:06 alph Exp $
  4.  *
  5.  *  $Log: popen.c,v $
  6.  * Revision 1.3  1993/10/05  21:40:06  alph
  7.  * *** empty log message ***
  8.  *
  9.  * Revision 1.2  1993/10/05  21:38:19  alph
  10.  * *** empty log message ***
  11.  *
  12.  * Revision 1.1  1993/01/19  14:07:12  heinz
  13.  * Initial revision
  14.  *
  15.  * Revision 1.3  93/01/03  11:57:50  heinz
  16.  * All new popen.c, Cleans up, works nice, it's just fine :-)
  17.  *
  18.  * Revision 1.2  93/01/02  22:27:55  heinz
  19.  * Major cleanup for SAS/C 6.1, childprocess() is now clean!!
  20.  * There is still the DOSBase passing, though.
  21.  *
  22.  * Revision 1.1  92/12/26  16:55:24  heinz
  23.  * Initial revision
  24.  *
  25.  *                                      */
  26. /*------------------------------------------------------------------------*/
  27.  
  28. /*------------------------------------------------------------------------*/
  29. /*
  30. ** popen.c
  31. ** Written by Rick Schaeffer (ricks@isc-br.isc-br.com)
  32. NAME
  33.      popen, pclose - initiate I/O to/from a process
  34.  
  35. SYNOPSIS
  36.      #include <stdio.h>
  37.  
  38.      FILE *popen(command, type)
  39.      char *command, *type;
  40.  
  41.      pclose(stream)
  42.      FILE *stream;
  43.  
  44. DESCRIPTION
  45.      The arguments to popen are pointers to null-terminated
  46.      strings containing respectively a command line and an
  47.      I/O mode, either "r" for reading or "w" for writing.  It
  48.      creates a pipe between the calling process and the command
  49.      to be executed.  The value returned is a stream pointer that
  50.      can be used (as appropriate) to write to the standard input
  51.      of the command or read from its standard output.
  52.  
  53.      A stream opened by popen **MUST** be closed by pclose, which
  54.      waits for the associated process to terminate and returns
  55.      the exit status of the command.
  56.  
  57.      Because stdio files are shared, a type "r" command may be
  58.      used as an input filter, and a type "w" as an output filter.
  59.  
  60. DIAGNOSTICS
  61.      Popen returns a null pointer if files or processes cannot be
  62.      created.
  63.  
  64.      Pclose returns -1 if stream is not associated with a
  65.      `popened' command.
  66.  
  67. */
  68.  
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include <string.h>
  72. #include <stdarg.h>
  73.  
  74. #include <exec/types.h>
  75. #include <exec/memory.h>
  76. #include <dos/dos.h>
  77. #include <dos/dosextens.h>
  78. #include <dos/record.h>
  79. #include <dos/dostags.h>
  80.  
  81. #define __USE_SYSBASE
  82. #include <proto/exec.h>
  83. #include <proto/dos.h>
  84. #include <clib/alib_protos.h>
  85.  
  86.  
  87. #define NOTDEF
  88.  
  89. extern char *mktemp(char *);
  90.  
  91. struct POmsg {
  92.     struct Message    POm;
  93.     int        rc;
  94.     char        *cmd;
  95.     struct Library    *DOSBase;
  96.     };
  97.  
  98.  
  99. struct pstruct {
  100.     FILE    *fptr;
  101.     struct POmsg    childmsg;
  102.     };
  103.  
  104. #define MAXPIPES    6
  105. struct pstruct poarray[MAXPIPES];
  106.  
  107. FILE *popen(char    *cmd, char    *mode)
  108. {
  109.     static char tempname[] = "pipe:pXXX.XXX";
  110.     char        *pname,redir[20];
  111.     short        i;
  112.     int            pmode;
  113.     int            childprocess();
  114.     struct pstruct    *poptr;
  115.     BPTR            pfd;
  116.     struct Process    *child;
  117.     struct CommandLineInterface *cli;
  118.     BPTR Binfh, Boutfh;
  119.     ULONG closeinp, closeoutp;
  120.     ULONG stacksize;
  121.     struct Process *thistask;
  122.  
  123.     /* First, get pointers to our process and cli structs */
  124.     thistask = (struct Process *) FindTask(NULL);
  125.     cli = Cli();
  126.     poptr = NULL;
  127.  
  128.     /* now find an open pipe (we currently only allow 6 simultaneously
  129.        open pipes) */
  130.     for (i=0; i<MAXPIPES; i++) {
  131.         if (poarray[i].fptr == NULL) {
  132.             poptr = &poarray[i];
  133.             break;
  134.             }
  135.         }
  136.     if (poptr == NULL) {
  137.         fprintf(stderr,"popen: Unable to find an open pipe\n");
  138.         return(NULL);
  139.         }
  140.     if (strcmp(mode,"r") == 0)
  141.         pmode = MODE_NEWFILE;
  142.     else if (strcmp(mode,"w") == 0)
  143.         pmode = MODE_OLDFILE;
  144.     else {
  145.         fprintf(stderr,"popen: Mode must be 'r' or 'w'\n");
  146.         return(NULL);
  147.         }
  148.  
  149.     /* Try to make a guaranteed unique file name for the pipe */
  150.     strcpy(redir,tempname);
  151.     redir[5] = 'a' + i;
  152.  
  153.     pname = mktemp(redir);                          /* set up a pipe: file name */
  154.  
  155.     /* Now get the child's stack and priority set up */
  156.     if (cli)
  157.         stacksize = cli->cli_DefaultStack << 2;
  158.     else
  159.         stacksize = thistask->pr_StackSize;
  160.  
  161.     /* Open the side of the pipe for the child */
  162.     pfd = Open(pname,pmode);
  163.     if (pfd == 0) {
  164.         fprintf(stderr,"popen: Unable to open pipe file\n");
  165.         return(NULL);
  166.         }
  167.  
  168.     /* set up the tags for the new process */
  169.     if (pmode == MODE_NEWFILE) {
  170.         Binfh      = (Tag) Input();
  171.         Boutfh      = (Tag) pfd;
  172.         closeinp  = FALSE;
  173.         closeoutp = TRUE;
  174.         }
  175.     else {
  176.         Binfh      = (Tag) pfd;
  177.         Boutfh      = (Tag) Output();
  178.         closeinp  = TRUE;
  179.         closeoutp = FALSE;
  180.         }
  181.  
  182.     /* create the command.    since the "System" function runs through
  183.        the default shell, we need to tell it not to fail so that we
  184.        ALWAYS get back the exit status.  This wouldn't be necessary
  185.        if the CLI created by the System function inherited the parent's
  186.        FAILAT level
  187.     */
  188.     poptr->childmsg.cmd = malloc(strlen(cmd) + 15);
  189.     strcpy(poptr->childmsg.cmd,"failat 9999\n");
  190.     strcat(poptr->childmsg.cmd,cmd);
  191.  
  192.     /* Create a port that we can get the child's exit status through */
  193.     poptr->childmsg.POm.mn_ReplyPort = CreateMsgPort();
  194.     poptr->childmsg.POm.mn_Node.ln_Type = NT_MESSAGE;
  195.     poptr->childmsg.POm.mn_Node.ln_Pri = 0;
  196.     if (poptr->childmsg.POm.mn_ReplyPort == 0) {
  197.         fprintf(stderr,"popen: Couldn't create message port\n");
  198.         return(NULL);
  199.         }
  200.  
  201.     /* Now we can start the new process.  NOTE: this is actually going
  202.        to create a process consisting ONLY of the function "childprocess"
  203.        which can be seen below.  childprocess() then runs the command
  204.        passed in the startup message.
  205.     */
  206.     child = CreateNewProcTags(
  207.         NP_Entry,    (Tag) childprocess,
  208.         NP_Input,    Binfh,
  209.         NP_Output,    Boutfh,
  210.         NP_CloseInput,    closeinp,
  211.         NP_CloseOutput, closeoutp,
  212.         NP_StackSize,    stacksize,
  213.         NP_Cli,     TRUE,
  214.         TAG_DONE
  215.         );
  216.  
  217.     poptr->childmsg.DOSBase = (struct Library *)DOSBase;
  218.  
  219.     /* now pass the child the startup message */
  220.     PutMsg(&child->pr_MsgPort,(struct Message *) &poptr->childmsg);
  221.  
  222.     /* Now open our side of the pipe */
  223.     poptr->fptr = fopen(pname,mode);
  224.     if (poptr->fptr == NULL) {
  225.         fprintf(stderr,"popen: Unable to open pipe file %s\n",pname);
  226.         DeleteMsgPort(poptr->childmsg.POm.mn_ReplyPort);
  227.         return(NULL);
  228.         }
  229.     return(poptr->fptr);
  230. }
  231.  
  232. FILE *popenl(char *arg0, ...)
  233. {
  234.     va_list ap;
  235.     char argbuf[512], *mode;
  236.  
  237.     strcpy(argbuf, arg0);
  238.     va_start(ap, arg0);
  239.     while(1)
  240.     {
  241.         char *s = va_arg(ap, char *);
  242.  
  243.         if(s == NULL)
  244.         {
  245.         strcat(argbuf, "\n");
  246.         break;
  247.         } /* if */
  248.  
  249.         strcat(argbuf, " ");
  250.  
  251.         if(strchr(s, ' '))
  252.         {
  253.         strcat(argbuf, "\"");
  254.         strcat(argbuf, s);
  255.         strcat(argbuf, "\"");
  256.         }
  257.         else
  258.         {
  259.         strcat(argbuf, s);
  260.         } /* if */
  261.     }
  262.     mode = va_arg(ap, char *);
  263.     va_end(ap);
  264.  
  265.     return(popen(argbuf, mode));
  266.  
  267. } /* popenl */
  268.  
  269. int pclose(FILE    *fptr)
  270. {
  271. #if 0
  272.     int        rc;
  273. #endif
  274.     short        i;
  275.  
  276.     /* Figure out which pipe we used for this file */
  277.     for (i=0; i<MAXPIPES; i++)
  278.         if (poarray[i].fptr == fptr)
  279.             break;
  280.     if (i >= MAXPIPES) {
  281.         fprintf(stderr,"popen: DISASTER...couldn't find file pointer in pclose\n");
  282.         exit(1);
  283.         }
  284.  
  285.     /* close the file */
  286.     fclose(fptr);
  287.  
  288.     /* now wait for the exit status */
  289.     WaitPort(poarray[i].childmsg.POm.mn_ReplyPort);
  290.     poarray[i].fptr = NULL;
  291.  
  292.     /* clean things up */
  293.     DeletePort(poarray[i].childmsg.POm.mn_ReplyPort);
  294.     free(poarray[i].childmsg.cmd);
  295.     return(poarray[i].childmsg.rc);
  296. }
  297.  
  298. /* SAS/C autoinitialization for cleanup! */
  299. void __stdargs _STDpopen(void)
  300. {
  301.     short i;
  302.  
  303.     /* Close all the open pipes! */
  304.     for(i=0; i<MAXPIPES; i++)
  305.     {
  306.     if(poarray[i].fptr)
  307.     {
  308.         pclose(poarray[i].fptr);
  309.     } /* if */
  310.     } /* for */
  311.  
  312. } /* _STDpopen */
  313.  
  314. #ifdef NOTDEF
  315.  
  316. char *mktemp(template)
  317. char *template;
  318. {
  319.     register char *cp;
  320.     register unsigned long val;
  321.  
  322.     cp = template;
  323.     cp += strlen(cp);
  324.     for (val = (unsigned long) FindTask(0L) ; ; )
  325.         if (*--cp == 'X') {
  326.             *cp = val%10 + '0';
  327.             val /= 10;
  328.         } else if (*cp != '.')
  329.             break;
  330.  
  331.     if (*++cp != 0) {
  332.         *cp = 'A';
  333.         while (access(template, 0) == 0) {
  334.             if (*cp == 'Z') {
  335.                 *template = 0;
  336.                 break;
  337.             }
  338.             ++*cp;
  339.         }
  340.     } else {
  341.         if (access(template, 0) == 0)
  342.             *template = 0;
  343.     }
  344.     return template;
  345. }
  346.  
  347. #endif
  348.  
  349. /* WATCH OUT! This only works without __saveds because of the special
  350.    SAS/C 6.1 tricks I use! Check the output with omd! */
  351. int __interrupt childprocess(void)
  352. {
  353.     struct ExecBase *SysBase = *((struct ExecBase **)4);
  354.     struct Library *DOSBase;
  355.     struct Process    *me;
  356.     struct POmsg    *startupmsg;
  357.     int                i=20;
  358.  
  359.     /* find our process structure */
  360.     me = (struct Process *) FindTask(NULL);
  361.  
  362.     /* Wait for the parent to kick us off */
  363.     WaitPort(&me->pr_MsgPort);
  364.  
  365.     /* Get the command to execute */
  366.     startupmsg = (struct POmsg *) GetMsg(&me->pr_MsgPort);
  367.  
  368.     DOSBase = startupmsg->DOSBase;
  369.  
  370.     if(DOSBase)
  371.     {
  372.         /* Now run the command.  stdin and stdout are already set up */
  373.         i = SystemTags(startupmsg->cmd,
  374.                SYS_UserShell, 1,
  375.                TAG_DONE);
  376.     } /* if */
  377.  
  378.     if(i > 0)
  379.     {
  380.         /* UNIX compatibility ... */
  381.         i <<= 8;
  382.     } /* if */
  383.  
  384.     startupmsg->rc = i;
  385.     /* pass the exit code back to the parent */
  386.     ReplyMsg((struct Message *) startupmsg);
  387.     return(0);
  388. }
  389.  
  390.  
  391. /*------------------------------------------------------------------------*/
  392.  
  393. /* Ende des Quelltextes */
  394.  
  395.