0

I want to execve a bash as a child process in a c program. The bash should essentially be controlled by the parent process: the parent process reads from stdin, stores the read input into a buffer and writes the content of the buffer to the bash through a pipe. The output of the bash is supposed to be passed through another pipe back to the parent process's stdout. For instance: the parent process reads "ls" and gives it to the bash through a pipe and receives the output of the bash through another pipe. I know this program doesn't make sense, because there are better ways to execute ls (or some other program) on behalf of the parent process. I'm actually just trying to understand how piping works and this is the first program that came into my mind. And i can't make this program work. That's what i have so far:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>

int main() {
    int pc[2];//"parent to child"-pipe                                                                     
    int cp[2];//"child to parent"-pipe                                                                     
    int status;
    char buffer[256];
    char eof = EOF;

    if (pipe(pc) < 0 || pipe(cp) < 0) {
        printf("ERROR: Pipes could not be created\n");
        return -1;
    }

    pid_t child_pid = fork();

    if (child_pid == 0) { //child has pid 0, child enters here                                             
        close(pc[1]);//close write end of pc                                                                 
        close(cp[0]);//close read end of cp                                                                  

        //redirecting file descriptors to stdin/stdout                                                       
        dup2(cp[1], STDOUT_FILENO);
        dup2(pc[0], STDIN_FILENO);

        execve("/bin/bash",NULL,NULL);

    } else {//parent enters here                                                                           
        close(cp[1]);//close write end of cp                                                                 
        close(pc[0]);//close read end of pc                                                                  

        //redirecting file descriptors to stdin/stdout                                                       
        dup2(cp[0], STDOUT_FILENO);

        while(1) {
            read(STDIN_FILENO, buffer, 3);
            write(pc[1], buffer, 3);
        }

        waitpid(child_pid, &status, 0);

    }

    return 0;
}

On execution: I type in ls, hit enter, nothing happens, hit enter again, output.

$ ./pipe
ls

bash: line 3: s: command not found

Why is only the character 's' delivered to the bash?

  • I get a warning on this line while compiling: "execve("/bin/bash", NULL, NULL);" ... The first "NULL" argument, should be an array of arguments just like main's "argv".... – TonyB May 08 '18 at 00:55
  • @TonyB This is probably due to the different compilers we are are using. I don't get any warnings. But i know that you usually pass an array of arguments to the second parameter of execve. In this case "argv[0]" would be "/bin/sh" and "argv[1]" would be NULL. But i also know that this is not the problem i'm having here. I've tried to execve a bash this way (execve("/bin/bash", NULL, NULL)) and it definitly spawns a shell. And i also tried to give execve the appriate argv array as you suggested. It doesn't change anything. – Narc Eritor May 08 '18 at 08:35
  • @TonyB Other than that, from the output I've posted above you can clearly see that execve("/bin/bash", NULL, NULL) was successful. Btw: I'm using gcc version 7.3.0 on arch linux. – Narc Eritor May 08 '18 at 08:38

0 Answers0