0

Why piping doesn't work for the following code?

int p_fds[2];
pipe(p_fds);

int pid_left = fork();
if (pid_left == 0){
    dup2(p_fds[1],STDOUT_FILENO);
    close(p_fds[0]);
    close(p_fds[1]);
    execv("cat", (char*[]){ "cat", "afile" });//execlp("cat", "cat", "afile", NULL);         
    exit(1);
}

int pid_right = fork();
if (pid_right == 0){
    dup2(p_fds[0], STDIN_FILENO);
    close(p_fds[1]);
    close(p_fds[0]);
    execv("grep", (char*[]){ "grep", "something" });//execlp("grep", "grep", "something", NULL);
    exit(1);
}

close(p_fds[0]);
close(p_fds[1]);
waitpid(pid_left, NULL, 0);
waitpid(pid_right, NULL, 0);

but it works with execlp or any other exec* except execv. What should be updated to make it work with execv? It is expected that this code print something in main stdout like cat afile | grep sth.

Yun
  • 3,056
  • 6
  • 9
  • 28
  • 3
    Your argument arrays **must** be NULL terminated. This code would benefit from some error checking (`if (fork/execv(...) == -1) { /* uh oh */ }`). – Oka Sep 14 '21 at 04:34
  • 1
    What is `left` in `execv(left->items[0], left->items);`? And why is this line here if the previous line is expected to replace the process' execution context completely? Please post a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Oka Sep 14 '21 at 04:37
  • @Oka `left`and `xecv(left->items[0], left->items)` is not needed. I removed them. I would add error checking later. Thanks. – Ilya Zlatkin Sep 14 '21 at 04:46
  • 1
    But error checking would help you *now*, as it would quickly reveal why `execv` is failing. One `if (-1 == execv(...)) { perror("..."); /* ... */ }` is an easy way to be pointed towards an answer (hint: `man execv`, and read the difference between `execv` and `execvp`). – Oka Sep 14 '21 at 04:49
  • @Oka Thanks. It is really not expected errors for 1st and 2d execv. ...: No such file or directory ...: Permission denied Because the file exist (in the same dir) and it’s not clear what is wrong with permission – Ilya Zlatkin Sep 14 '21 at 05:02
  • this statement: `execv("grep", (char*[]){ "grep", "something" });` should be: `execv("grep", (char*[]){ "grep", "something" , NULL});` Notice the trailing NULL – user3629249 Sep 15 '21 at 16:39
  • regaarding: `execv("cat", (char*[]){ "cat", "afile" });//execlp("cat", "cat", "afile", NULL); exit(1);` should be: `execv("/bin/cat", (char*[]){ "cat", "afile", NULL }); perror( "execv failed" ); exit(1); – user3629249 Sep 15 '21 at 16:42

1 Answers1

1

It is needed to provide full path for execv(full_path, char *const argv[]); execv("/bin/cat") Other functions (exec*) perforce search in $PATH