Reputation: 3
Can someone please explain the reasoning of using dup2
after checking if fd[0] != STDIN_FILENO
, because from what I understand fd[0] != STDIN_FILENO
would fail and dup2
would still return something other than STDIN_FILENO
, just trying to understand some example code thank you, also if some one could explain the use of execlp for me to that would be awesome.
int fd[2];
pid_t pid;
if(argc != 2) {
fprintf(stderr, "Must be specify exactly 1 file\n");
exit(0);
}
if(pipe(fd) < 0)
exit(1);./
pid = fork();
switch (pid) {
case -1:
exit(1);
case 0:
close(fd[1]);
//here
if(fd[0] != STDIN_FILENO) {
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
exit(3);
close(fd[0]);
}
if(execlp("tr", "tr", "[a-z]", "[A-Z]", (char *) 0) < 0)
exit(4);
break;
default:
close(fd[0]);
// and here
if(fd[1] != STDIN_FILENO) {
if(dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)
exit(5);
close(fd[1]);
}
if(execlp("cat", "cat", argv[1], (char *) 0) < 0)
exit(4);
break;
}
return 0;
Upvotes: 0
Views: 4808
Reputation: 16406
The intent is to make stdin (STDIN_FILENO, which is 0) point to the file that fd[0] points to (the read side of the pipe). First check that they aren't already the same ... if they are, the code would dup 0 to 0 and then close 0 -- not good. If they aren't the same, use dup2 to make STDIN_FILENO point where fd[0] points. If dup2 succeeds, it returns its second argument, so the check is against that with a call to exit if dup2 failed.
You write
From what I understand fd[0] != STDIN_FILENO would fail
It's not at all clear why you "understand" this. It only fails if fd[0] contains STDIN_FILENO (i.e., 0), but it isn't likely to since it contains a file descriptor allocated by the pipe
call.
dup2 would still return something other than STDIN_FILENO
dup2 returns its second argument if it succeeds. It won't return something other than STDIN_FILENO unless it fails -- and why would it? -- and in that case it returns -1.
Upvotes: 3
Reputation: 980
The checking on fd[0] != STDIN_FILENO
is a defensive programming practice, since normally the standard input and standard output have been previously open, although if they had both been closed before you do the pipe()
call, pipe()
would have allocated the two descriptors to the pipe (Note when a pipe is created, the file descriptors used for the two ends of the pipe are the next lowest-numbered descriptors), so the checking will come into making sense.
Upvotes: 1
Reputation: 45568
execlp
basically executes a program. That program will read its input from STDIN_FILENO
(in other words, fd 0). The dup2
and close
syscalls are used to move the fd[0]
or fd[1]
file descriptor to that number.
Upvotes: 1
Reputation: 9889
This program is going to run cat in parent process, and run tr in child process, and it want cat's output to be read by tr.
At beginning, it opens a pipe, parent will write to fd[1], and child will read from fd[0], so that parent can write data to child.
In parent, it dup fd[1] to stdin; and in child it dup fd[0] to stdin.
In child, execlp to run tr, tr will read from stdin, and since stdin has been dup as fd[0], so it actually read what cat's output from the pipe.
execlp()
run a new executable in current process. You may man execlp
for its argument detail.
Upvotes: 0