TheInnerParty TheInnerParty - 18 days ago 5
Bash Question

Why are stdin and stdout seemingly interchangeable?

I understand that stdin and stdout (at least in UNIX parlance) are stream buffers, and that stdout is used to output from a program to the console (or to then be piped by a shell, etc), and that stdin is for standard input to a program..

So why is it, at least on macOS, that they can be used interchangeably (stdout as stdin, and vice versa?

Examples:


  1. If you run
    cat /dev/stdin
    then type something in, and it echoes it back. Running the command as
    cat /dev/stdout
    does the same thing.

  2. Similarly,
    echo "Hey There" > /dev/stdout
    and
    echo "Hey There" > /dev/stdin
    both output 'Hey There' back to the terminal.

  3. It also works in C++:



example:

#include <iostream>
#include <string>
#include <fstream>

int main(int argc, const char * argv[]) {
std::string echoString;
std::fstream stdoutFile;
stdoutFile.open("/dev/stdout");
stdoutFile << "Hey look! I'm using stdout properly!\nNow You trying using it wrongly: " << std::endl;
stdoutFile >> echoString;
stdoutFile << "You Typed: " << echoString << std::endl;
}


When prompted, typing a single word, followed by EOF (Ctrl+D) works as expected.

Answer

Because, typically, when a program is invoked from an interactive terminal, with no redirection, both standard input and standard output are connected to the same terminal device, such as /dev/tty (the actual device name varies based on the operating system).

The terminal device is a read/write device. Reading from the terminal device reads terminal input. Writing to the terminal device generates output on the terminal.

You still have discrete file descriptors, 0 and 1, but they're connected to the same device.

Think of it as single, bi-directional pipe, that's duped to both file descriptors 0 and 1.

Linux behaves the same way (you can echo Foo >/dev/stdin and see the output):

$ ls -al /proc/self/fd/[01]
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/0 -> /dev/pts/1
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/1 -> /dev/pts/1

So, for this process, file descriptors 0 and 1 is connected to the /dev/pts/1, the same pseudo-terminal device. Whether you are reading from file descriptor 0 or file descriptor 1, you end up reading from the same underlying /dev device, so it makes no difference which actual file descriptor you use.

This is, of course, operating system-dependent. Other POSIX-based operating systems may implement their standard input and output in other ways, where you can't actually write to standard input and read from standard output.