Home > Net >  How is &> redirection implemented in UNIX shells?
How is &> redirection implemented in UNIX shells?

Time:04-18

We know that &> outfile redirects both stdout and stderr to outfile in a UNIX shell. But how does the shell implement this? I write a naïve test:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
    int fd = open("tmpf", O_CREAT | O_TRUNC | O_WRONLY, 0644);
    // redirect stdout to file
    dup2(fd, 1);
    close(fd);
    // redirect stderr to stdout
    dup2(2, 1);
    close(2);
    // print stuff to file
    fprintf(stdout, "stdout string\n");
    fprintf(stderr, "stderr string\n");
}

It simply redirects stdout to the file and then redirects stderr to stdout. But this doesn't work. The above code produces

$ ./a.out
stdout string
$ cat tmpf
$

If we exchange the order of stdout->file and stderr->stdout, it gives the following result

$ ./a.out
$ cat tmpf
stdout string
$

CodePudding user response:

Don't close your destination FDs. The only FD you should close is the handle on tmpf; both stdout and stderr need to be open to be able to write to them.

Also, it should be dup2(1,2) to copy stdout to stderr -- coping stderr to stdout (as the original code does) discards your handle on tmpf.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
    int fd = open("tmpf", O_CREAT | O_TRUNC | O_WRONLY, 0644);
    // copy FD to stdout ("redirect stdout to fd")
    dup2(fd, 1);
    // fd was copied to stdout so we don't need the original
    close(fd);
    // copy stdout fd to stderr ("redirect stdout to stderr")
    dup2(1, 2);
    // print stuff to file
    fprintf(stdout, "stdout string\n");
    fprintf(stderr, "stderr string\n");
}

Also see this running in an online sandbox at https://replit.com/@CharlesDuffy2/KnowingWobblyFibonacci#main.c (you can use "Show files" to see the resulting tmpf file in output).

  • Related