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].

The code

% 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)[0],
                (stat *in)[1],
                (stat *out)[0],
                (stat *out)[1],
                (stat *err)[0],
                (stat *err)[1]
);

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

Published on in