Chris Zhu
Chris Zhu

Reputation: 21

using dup2 and pipe to redirect stdin

I have a program A that takes two arguments from stdin and exits with a unique code depending on the arguments. I am writing a program B that calls program A using fork and exec and let program B print out the code program A exits with. For some reason, program A doesn't seem to be getting the data I piped through to it in the child process of fork. I'm not sure if I'm piping the correct data to the child process.

Could someone help me please? Thanks!

Here is my code:

int program_B(void) {
char var_a[256];
char var_b[256];
int fd[2];

 // Read from stdin 
char *sendarray[2];
sendarray[0] = var_a;
sendarray[1] = var_b;


if(fgets(var_a, MAXLINE, stdin) == NULL) {
    perror("fgets");
    exit(1);
}

if(fgets(var_b, MAXLINE, stdin) == NULL) {
    perror("fgets");
    exit(1);
}

if (pipe(fd) == -1) {
  perror("pipe");
  exit(1);
}

int pid = fork();

// Child process -- error seems to be here. 
if (pid == 0) {

    close(fd[1]);

    dup2(fd[0], fileno(stdin));

    close(fd[0]);

    execl("program_A", NULL);

    perror("exec"); 
    exit(1);

} else {

    close(fd[0]);
    write(fd[1], sendarray, 2*sizeof(char*));
    close (fd[1]);

    int status; 

      if (wait(&status) != -1) {

        if (WIFEXITED(status)) {


            printf("%d\n", WEXITSTATUS(status));


        } else {
          perror("wait");
          exit(1);
        }
      }


}







return 0;
}

Upvotes: 1

Views: 2476

Answers (1)

Fränki
Fränki

Reputation: 71

You are piping the wrong data to the child process.

I am assuming var_a and var_b are the strings you want to send to program A. They are both of type array of chars, which in C is the same thing as pointer to char (Actually there is a small difference between pointers and arrays but this is irrelevant for this problem). So they are actually just pointers to the first byte of each argument. sendarray, however is an array of char-pointers which is the same thing as a pointer to char-pointer. Keep this in mind for a second.

When calling write() the 2nd parameter tells it where the data is in memory. By passing sendarray, write thinks this sendarray points the data you want to write although it actually points to yet another pointer. So what happens is that the pointer values of var_a and var_b (which is what sendarray points to), are written to the pipe.

So you have to pass var_a and var_b to write(), since those are pointers to the actual data you want to send. Also you have to know how long (how many bytes) this data is. If var_a and var_b point to null-terminated strings, you can use strlen() to determine their length.

One last thing: I don't know how exactly your program A obtains 2 arguments from a continuous byte stream like stdin, but assuming it reads it line by line, you obviously have to send a new-line character from program B, as well.

So putting it all together your write statements should look something like this:

write(fd[1], var_a, strlen(var_a));
write(fd[1], "\n", 1);
write(fd[1], var_b, strlen(var_b));

Of course, if any of the assumptions I made is wrong, you have to adopt this code appropriately.

Upvotes: 1

Related Questions