Home >Backend Development >C++ >How can I properly pipe standard input and output to a child process in Linux?

How can I properly pipe standard input and output to a child process in Linux?

Linda Hamilton
Linda HamiltonOriginal
2024-11-08 19:39:02276browse

How can I properly pipe standard input and output to a child process in Linux?

Executing Child Processes with Piped Standard Input and Output in Linux

Consider the following function:

string f(string s) {
    string r = system("foo < s");
    return r;
}

This function attempts to execute the "foo" program with the string s as its standard input, capturing the program's standard output in the string r. However, this approach is not viable.

To implement this functionality correctly, a combination of Linux system calls or POSIX functions is required:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int createChild(const char *szCommand, char *const aArguments[], char *const aEnvironment[],
               const char *szMessage) {
  int aStdinPipe[2];
  int aStdoutPipe[2];
  int nChild;
  char nChar;

  if (pipe(aStdinPipe) < 0) {
    perror("allocating pipe for child input redirect");
    return -1;
  }
  if (pipe(aStdoutPipe) < 0) {
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    perror("allocating pipe for child output redirect");
    return -1;
  }

  nChild = fork();
  if (0 == nChild) {
    // child continues here

    // redirect stdin
    if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
      exit(errno);
    }

    // redirect stdout
    if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
      exit(errno);
    }

    // redirect stderr
    if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) {
      exit(errno);
    }

    // run child process image
    // (replace this with any `exec*` function you find easier to use)
    execve(szCommand, aArguments, aEnvironment);

    // if we get here at all, an error occurred, but we are in the child
    // process, so just exit
    exit(errno);
  } else if (nChild > 0) {
    // parent continues here

    // close unused file descriptors
    close(aStdinPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);

    // send message to child (if provided)
    if (NULL != szMessage) {
      write(aStdinPipe[PIPE_WRITE], szMessage, strlen(szMessage));
    }

    // read child's output
    while (read(aStdoutPipe[PIPE_READ], &nChar, 1) == 1) {
      write(STDOUT_FILENO, &nChar, 1);
    }

    // close pipes
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
  } else {
    // failed to create child
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);
  }
  return nChild;
}

This function createChild sets up a pipe between the parent and child processes, redirecting the child's standard input and output to and from the pipe. The parent process can then send input to the child via the pipe and read the child's output from the same pipe.

The above is the detailed content of How can I properly pipe standard input and output to a child process in Linux?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn