I'm trying to execute a process, read from its stdout, send a response based on that to its stdin, and then send the parent process's stdin to the child's stdin and the child's stdout to the parent's stdout.

So, for example, say the process I want to run is /bin/sh - I would want to send a command, read the response, and then connect the shell to stdin/stdout so that it could be used just as if you had run sh instead of my program.

Here's the code I currently have:

Code:
pid_t pid = 0;
int inpipefd[2];
int outpipefd[2];

pipe(inpipefd);
pipe(outpipefd);
pid = fork();
if (pid == 0) {
    dup2(outpipefd[0], STDIN_FILENO);
    dup2(inpipefd[1], STDOUT_FILENO);
    //dup2(inpipefd[1], STDERR_FILENO);

    prctl(PR_SET_PDEATHSIG, SIGTERM);

    // for example
    execl("/bin/sh", "sh", (char*) NULL);

    exit(1);
}

close(outpipefd[0]);
close(inpipefd[1]);

// some working code that reads something from inpipefd[0] and writes something to outpipefd[1]

// todo: pass the parent's stdin to the child's and the child's stdout to the parent


Right now, executing the process, reading from its stdin, and responding to its stdout all work fine, but I haven't been able to figure out how to redirect the parent's stdin/out to the child afterward.

I originally tried a loop that read from stdin and then wrote to outpipefd[1], read from inpipefd[0], and then wrote that to stdout, which obviously didn't work particularly well.

I also tried redirecting outpipefd[1] to stdout using dup2, but that's the read half of the pipe. If I understand correctly, I would have to redirect outpipefd[0] instead, which is now controlled by the sh process.

Google was surprisingly unhelpful for this, so I would appreciate it if anyone could give me any pointers on how to do this, or let me know if I'm approaching this in the wrong way entirely.
Because you want to do bidirectional communication and can't predict which direction the child will be doing I/O at any given time, you need to use multiplexed I/O as exemplified by select(3). This is complex enough that I'll just point you at select_tut(2) rather than try to construct a working example myself.

The trick is that you need to monitor the interfaces of user -> this program -> child as well as child -> this program -> user. Since you're using pipes, you'll monitor two read FDs (user-> and child->) and two write FDs (->child and ->user) rather than the one of each used in the select_tut example program, where bidirectional file descriptors (sockets) are used.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement