cincybengal
cincybengal

Reputation: 3

dup2 after Fd[0]!= STDIN_FILENO

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

Answers (4)

Jim Balter
Jim Balter

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

poiu2000
poiu2000

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

thejh
thejh

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

TieDad
TieDad

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

Related Questions