Execv * and write in stdin

I am trying to run a program with special standard input. I can use the file descriptor of the file, where there is something that I want to put in stdin, but I can not write directly to stdin:

$cat input.test echo Hello $ 

Code C:

 int main(int argc, char **argv) { int fd = 0; fd = open("input.test", O_CREAT); close(STDIN_FILENO); dup2(fd, STDIN_FILENO); char *const args[] = { "bash", NULL }; execvp("bash", args); } 

It works:

 $./a.out Hello $ 

But if I try to write directly to STDIN using the program, the program does not display anything and continues to work:

 int main(int argc, char **argv) { int fds[2]; pipe(fds); close(STDIN_FILENO); dup2(fds[1], STDIN_FILENO); write(fds[1], "echo Hello;", 11); // Rรฉsults are identics with fds[0] char *const args[] = { "bash", NULL }; execvp("bash", args); } 

thanks for the help

Heartily, Bastien.

EDIT Problem Solved:

Thanks for your answers, here is the code that works:

 int main(void) { int fd[2]; pid_t pid; if (pipe(fd) < 0) return EXIT_FAILURE; if ((pid = fork()) < 0) return EXIT_FAILURE; else if (pid != 0) { /* father */ close(fd[1]); dup2(fd[0], STDIN_FILENO); execlp("bash", "bash", (char *)0); } else { /* son */ close(fd[0]); write(fd[1], "echo hello\n", 11); } return EXIT_SUCCESS; } 
+6
source share
4 answers

You need to duplicate the read side on stdin , not the write side. (And write to the side of the record, obviously.)

 #include <unistd.h> #include <string.h> #include <stdio.h> int main(int argc, char **argv) { int fds[2]; char cmd[] = "echo hello\nexit\n"; pipe(fds); close(STDIN_FILENO); dup2(fds[0], STDIN_FILENO); write(fds[1], cmd, strlen(cmd)); char *const args[] = { "bash", NULL }; execvp("bash", args); return 0; } 

Make sure that you check the return values โ€‹โ€‹of all these functions, but never delete your code if you do not.

+4
source

execv and friends will replace the currently running program with the specified one; they do not return - execution is performed at the beginning of a new program.

So what you usually do is fork , and call execv in one of the forks. Then you read and write the pipe from your program, continuing in another fork. Commonly used popen functions for most languages; sadly in POSIX popen () is strictly read or written, not bi-directional.

Fortunately, I did, tested and published the popen3 function . This gives you three file descriptors - one for stdin for the process and two for stdout and stderr. Then you can use write () for stdin.

+3
source

When you call pipe, fd [0] is open for reading, and fd [1] is open for writing. You must duplicate stdin on the read side (fd [0]) and write on the write side (fd [1]). Check the return value of the entry: possibly -1.

But there is a big problem. You never close any side of the pipe. bash can block while reading and never do anything until the write side is closed. You must close both sides of the pipe after duplexing and recording. (Or set FD_CLOEXEC).

+2
source

Also note that when doing this the way you do, you depend on the size of the buffer. If you write too much, the recording will be blocked, as there is no reader. Do it reliably, you have to fork (), execute exec on the child and write to the parent pipe. Thus, the pipe will have a reader, and you can write as much data as you want.

0
source

Source: https://habr.com/ru/post/901293/


All Articles