Hello. I need to create a process and get its I / O. In libc there is a popen and you can get either input or output. I need to get this and that.
Please share your ideas :)
To get both input and output of the child process, you can redirect them using dup2 () (executable pseudo-code):
#!/usr/bin/env python from os import * STDIN_FILENO, STDOUT_FILENO = 0, 1 r_stdin, w_stdin = pipe() r_stdout, w_stdout = pipe() if not fork(): # child process close(w_stdin) # unused close(r_stdout) # unused dup2(r_stdin, STDIN_FILENO) # redirect stdin close(r_stdin) dup2(w_stdout, STDOUT_FILENO) # redirect stdout close(w_stdout) execlp('cat', 'cat') else: # parent close(r_stdin) # unused close(w_stdout) # unused write(w_stdin, b'hello') # send some input to the child close(w_stdin) output = read(r_stdout, 512) # read it back write(STDOUT_FILENO, b'got [' + output + b']\n') close(r_stdout) wait() # wait for the child to exit In essence, this is the implementation of the steps from the @Pink Tux response .
It is worth mentioning that in practice, many programs change their behavior if their standard I / O is redirected to a pipe. In particular, due to internal buffering, I / O can be delayed, for example, without the - --line-buffered option of the grep option, lines that are not immediately found can print if its output is redirected. Perhaps you should use pseudo-tty (pty) instead of pipe. See Q: Why not just use a pipe (popen ())?
For comparison, here is the full C code corresponding to the above pseudo-code:
/** Redirect both stdin/stdout of a child process. Test it. * * $ gcc *.c && ./a.out */ #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> #define Close(FD) do { \ int Close_fd = (FD); \ if (close(Close_fd) == -1) { \ perror("close"); \ fprintf(stderr, "%s:%d: close(" #FD ") %d\n", \ __FILE__, __LINE__, Close_fd); \ } \ }while(0) static int child = 0; /* whether it is a child process relative to main() */ static void report_error_and_exit(const char* msg) { perror(msg); (child ? _exit : exit)(EXIT_FAILURE); } /** move oldfd to newfd */ static void redirect(int oldfd, int newfd) { if (oldfd != newfd) { if (dup2(oldfd, newfd) != -1) Close(oldfd); /* successfully redirected */ else report_error_and_exit("dup2"); } } int main(void) { int fd_stdin[2], fd_stdout[2]; /* stdin/stdout pipes */ if (pipe(fd_stdin) == -1) report_error_and_exit("stdin pipe"); if (pipe(fd_stdout) == -1) report_error_and_exit("stdout pipe"); switch(fork()) { case -1: /* error */ report_error_and_exit("fork"); case 0: /* child: redirect stdin/stdout and exec */ child = 1; Close(fd_stdin[1]); /* close unused end of the pipe */ Close(fd_stdout[0]); /* unused */ redirect(fd_stdin[0], STDIN_FILENO); /* redirect stdin */ redirect(fd_stdout[1], STDOUT_FILENO); /* redirect stdout */ execlp("cat", "cat", NULL); report_error_and_exit("execlp"); default: /* parent: write some input to the child and read it back */ Close(fd_stdin[0]); /* close unused end of the pipe */ Close(fd_stdout[1]); /* unused */ { /* send some input to the child */ char buf[] = "hello"; if (write(fd_stdin[1], buf, sizeof buf) == -1) report_error_and_exit("write"); Close(fd_stdin[1]); } { /* read it back */ char readbuf[512] = {0}; ssize_t n = read(fd_stdout[0], readbuf, sizeof readbuf); if (n == -1) report_error_and_exit("read"); Close(fd_stdout[0]); printf("got [%.*s]\n", (int)n, readbuf); } { /* wait for the child to exit */ int status = 0; if (wait(&status) == -1) report_error_and_exit("wait"); } } return 0; } Something like this:
Source: https://ru.stackoverflow.com/questions/530413/
All Articles
FILE*stdio, usefileno, on the contrary -fdopen. - sercxjo