STDIN, STDOUT, STDERR and output detection
In reading about using fstat to detect if there is input from stdin, or a pipe, I explored this in Perl.
fstat takes an fd as an argument instead of a pathname. This is how grep et al detect input is from a file or STDIN (Bach, 1988).
Perl does not have fstat, but the stat command does take references to STDIN, STDERR, and STDOUT - equivalents to fd[0,1,2].
% cat inodes123 #!/usr/bin/perl -w use strict; # assign to vars - perhaps more portable. *in = *STDIN; *out = *STDOUT; *err = *STDERR; my $pid = $$; my $ppid = getppid(); my $gpid = $); my @inodes = ( (stat *in), (stat *in), (stat *out), (stat *out), (stat *err), (stat *err) ); printf "pid/ppid/gpid: %5d/%-5d/%-5d fd0 (STDIN):". " %8x/%-8d\tfd1 (STDOUT): %8x/%-8d\tfd2 (STDERR): %9x/%-9d\n", $pid, $ppid, $gpid, @inodes; printf "%s", $_ while (<>);
Seeing redirections and pipe setups.
Pipes are setup starting at the end, and working backwards to the start. This is seen here with looking at the inodes for the various outputs. The first line of pid/ppid/gpid: output is the last command on the line - it is setup first. The last one setup and executed is the first command, where /etc/hosts is the input.
% ls -i /etc/hosts /dev/null $(tty) 303 /dev/null 751 /dev/ttys006 4590635 /etc/hosts % </etc/hosts ./inodes123 2>/dev/null | ./inodes123 | ./inodes123 | ./inodes123 | ./inodes123 pid/ppid/gpid: 50713/48671/20 fd0 (STDIN): 0/728876461891957955 fd1 (STDOUT): 46c70288/751 fd2 (STDERR): 46c70288/751 pid/ppid/gpid: 50712/48671/20 fd0 (STDIN): 0/728876461973819427 fd1 (STDOUT): 0/728876461973813795 fd2 (STDERR): 46c70288/751 pid/ppid/gpid: 50711/48671/20 fd0 (STDIN): 0/728876461891949683 fd1 (STDOUT): 0/728876461267280611 fd2 (STDERR): 46c70288/751 pid/ppid/gpid: 50710/48671/20 fd0 (STDIN): 0/728876461973818899 fd1 (STDOUT): 0/728876461973813267 fd2 (STDERR): 46c70288/751 pid/ppid/gpid: 50709/48671/20 fd0 (STDIN): 1000002/4590635 fd1 (STDOUT): 0/728876461973818723 fd2 (STDERR): 46c70288/303 ## # Host Database # # localhost is used to configure the loopback interface # when the system is booting. Do not change this entry. ## 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost fe80::1%lo0 localhost