Exemplo n.º 1
0
void
pm_system(void stdinFeeder(int, void *),
          void *          const feederParm,
          void stdoutAccepter(int, void *),
          void *          const accepterParm,
          const char *    const shellCommand) {
/*----------------------------------------------------------------------------
   Run a shell and have it run command 'shellCommand'.  Feed its
   Standard Input with a pipe, which is fed by the routine
   'stdinFeeder' with parameter 'feederParm'.  Process its Standard
   Output with the routine 'stdoutAccepter' with parameter 'accepterParm'.

   But if 'stdinFeeder' is NULL, just feed the shell our own Standard
   Input.  And if 'stdoutFeeder' is NULL, just send its Standard Output
   to our own Standard Output.

   Run the program 'progName' with arguments argArray[] (terminated by NULL
   element).  That includes arg0.
-----------------------------------------------------------------------------*/
    /* If 'stdinFeeder' is non-NULL, we create a child process to run
       'stdinFeeder' and create a pipe between from that process as the
       shell's Standard Input.

       If 'stdoutFeeder' is non-NULL, we create a child process to run
       the shell and create a pipe between the shell's Standard Output
       and this process, and then this process runs 'stdoutAccepter'
       to read the data from that pipe.
       
       But if 'stdoutFeeder' is NULL, we just run the shell in this
       process.

       So there can be 1, 2, or 3 processes involved depending on 
       parameters.
    */
    
    int shellStdinFd;
    pid_t feederPid;

    if (stdinFeeder) 
        createPipeFeeder(stdinFeeder, feederParm, &shellStdinFd, &feederPid);
    else {
        shellStdinFd = STDIN;
        feederPid = 0;
    }

    if (stdoutAccepter) {
        int shellStdoutFd;
        pid_t processorPid;

        /* Make a child process to run the shell and pipe back to us its
           Standard Output 
        */
        spawnProcessor(shellCommand, shellStdinFd, 
                       &shellStdoutFd, &processorPid);

        /* The shell process has cloned our 'shellStdinFd'; we have no
           more use for our copy.
        */
        close(shellStdinFd);
        /* Dispose of the stdout from that shell */
        (*stdoutAccepter)(shellStdoutFd, accepterParm);
        close(shellStdoutFd);

        cleanupProcessorProcess(processorPid);
    } else {
        /* Run a child process for the shell that sends its Standard Output
           to our Standard Output
        */
        int const stdinSaveFd = dup(STDIN);
        int rc;

        dup2(shellStdinFd, STDIN);
        
        rc = system(shellCommand);

        close(STDIN);
        dup2(stdinSaveFd, STDIN);
        
        if (rc < 0)
            pm_error("Unable to invoke the shell.  Errno=%d (%s)",
                     errno, strerror(errno));
        else if (rc != 0)
            pm_message("WARNING: Shell process completion code = %d", rc);
    }

    if (feederPid) 
        cleanupFeederProcess(feederPid);
}
Exemplo n.º 2
0
void
pm_system_vp(const char *    const progName,
             const char **   const argArray,
             void stdinFeeder(int, void *),
             void *          const feederParm,
             void stdoutAccepter(int, void *),
             void *          const accepterParm) {
/*----------------------------------------------------------------------------
   Run a program in a child process.  Feed its Standard Input with a
   pipe, which is fed by the routine 'stdinFeeder' with parameter
   'feederParm'.  Process its Standard Output with the routine
   'stdoutAccepter' with parameter 'accepterParm'.

   But if 'stdinFeeder' is NULL, just feed the program our own Standard
   Input.  And if 'stdoutFeeder' is NULL, just send its Standard Output
   to our own Standard Output.

   Run the program 'progName' with arguments argArray[] (terminated by NULL
   element).  That includes arg0.
-----------------------------------------------------------------------------*/
    /* If 'stdinFeeder' is non-NULL, we create a child process to run
       'stdinFeeder' and create a pipe from that process as the
       program's Standard Input.

       We create another child process to run the program.

       If 'stdoutFeeder' is non-NULL, we create a pipe between the
       program process and the current process and have the program
       write its Standard Output to that pipe.  The current process
       runs 'stdoutAccepter' to read the data from that pipe.
       
       But if 'stdoutFeeder' is NULL, we just tell the program process
       to write to the current process' Standard Output.

       So there are two processes when stdinFeeder is NULL and three when
       stdinFeeder is non-null.
    */
    
    int progStdinFd;
    pid_t feederPid;
    pid_t processorPid;

    if (stdinFeeder) 
        createPipeFeeder(stdinFeeder, feederParm, &progStdinFd, &feederPid);
    else {
        progStdinFd = STDIN;
        feederPid = 0;
    }

    if (stdoutAccepter) {
        int progStdoutFd;

        /* Make a child process to run the program and pipe back to us its
           Standard Output 
        */
        spawnProcessor(progName, argArray, progStdinFd, 
                       &progStdoutFd, &processorPid);

        /* The child process has cloned our 'progStdinFd'; we have no
           more use for our copy.
        */
        close(progStdinFd);
        /* Dispose of the stdout from that child */
        (*stdoutAccepter)(progStdoutFd, accepterParm);
        close(progStdoutFd);
    } else {
        /* Run a child process for the program that sends its Standard Output
           to our Standard Output
        */
        spawnProcessor(progName, argArray, progStdinFd, NULL, &processorPid);
    }

    cleanupProcessorProcess(processorPid);

    if (feederPid) 
        cleanupFeederProcess(feederPid);
}