I'm trying to run a program with a specific standard input. I succeed by using a file descriptor of a file where there is what I want to put in the stdin, but I fail to write directly on the 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);
}
That works :
$./a.out
Hello
$
But if I try to write directly on the STDIN using pipe the program displays nothing and keeps running :
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 your help
Cordially, Bastien.
EDIT Problem solved:
Thanks for your answers, here the code which 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;
}
You need to dup the read side of the pipe to stdin
, not the write side. (And write to the write side, 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 you check the return values of all those functions though, you'll never manage to debug your code if you don't.
execv
and friends replace the current running program with the specified one; they do not return - execution continues at the start of new program instead.
So what you normally do is fork
and, in one of the forks, call execv
. You then read and write through the pipe from your program continuing in the other fork. There are usually popen
functions to do this in most languages; sadly in POSIX the popen() is strictly read or write and not bidirectional.
Luckily, I've made, tested and published a popen3
function. This gives you back three file descriptors - one for stdin to the process, and two for stdout and stderr. You can then use write() on the stdin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With