4

The below command makes a copy of the input file descriptor and use the duplicate file descriptor for writing data from the echo command on to the terminal.

sh-4.2$ exec 6<&0
sh-4.2$ echo "hello" >&6
hello

Does that mean we can write to the terminal using the input file descriptor?

JdeBP
  • 66,967
  • 12
  • 159
  • 343
Pankaj Pandey
  • 376
  • 5
  • 12
  • 1
    What operating system, and which terminal emulator, are you using? It's not documented, but the software on most Unix-like systems open their terminal devices with stdin, stdout, and stderr all `dup`ed from the same file descriptor, which was opened for both reading and writing. – Mark Plotnick Dec 17 '16 at 12:24
  • I am using an online bash terminal. – Pankaj Pandey Dec 17 '16 at 12:25
  • Suggested reading: [How do keyboard input and text output work?](http://unix.stackexchange.com/questions/116629/how-do-keyboard-input-and-text-output-work), [what is meant by connecting STDOUT and STDIN?](http://unix.stackexchange.com/questions/31334/what-is-meant-by-connecting-stdout-and-stdin), [How can a command have more than one output?](http://unix.stackexchange.com/questions/96724/how-can-a-command-have-more-than-one-output) – Gilles 'SO- stop being evil' Dec 18 '16 at 22:58

2 Answers2

3

Does that mean we can write to the terminal using the input file descriptor?

Sure. You can write to a terminal (indeed to any file or pipe or device or socket that supports and authorizes writing) using whatever open file descriptor you have for it. A simpler version of your code would be this:

echo hello >&0

which, as you'd expect, sends "hello\n" to whatever file descriptor 0 points to. If that's your terminal, so be it.

Celada
  • 43,173
  • 5
  • 96
  • 105
  • but the file descriptor '0' is associated with stdin which is the keyboard, so how is it possible to write to the terminal using stdin. – Pankaj Pandey Dec 17 '16 at 12:15
  • 1
    "the file descriptor '0' is associated with stdin which is the keyboard": **false**. File descriptor 0 points to your *terminal*, not to your *keyboard*. The terminal is a device that can be both read and written. – Celada Dec 17 '16 at 12:18
  • thnks for the explanation.. @Celeda – Pankaj Pandey Dec 17 '16 at 12:24
  • @Celeda , when you google about file descriptor , it describes file descriptor 0 i.e. stdin connected to the keyboard(default input device), so when we redirect the output to stdin how does it gets printed on the console(monitor) – Pankaj Pandey Dec 17 '16 at 13:39
  • @PankajPandey, the Google search result you found is not correct. The stdio file descriptors 0, 1, and 2, are typically connected (by default) to the *terminal*, not to a keyboard (for input) or video card (for output) or anything else of the sort. A "terminal" is a device which is historically a serial port connected to a (real, physical) terminal (perhaps through a modem), but nowadays is much more commonly an abstraction, connected to, say, a terminal application that displays itself as a window in a GUI system or connected to the server-end of an SSH connection. – Celada Dec 18 '16 at 14:04
1

This is a copy of my answer to a similar question on stackoverflow last year.

You can write to your terminal device's standard input due to historical custom. Here's what's happening:

When a user logs into a terminal on a Unix-like system, or opens a terminal window under X11, file descriptors 0, 1, and 2 are connected to a terminal device, and each of them is opened for both reading and writing. This is the case despite the fact that one normally only reads from fd 0 and writes to fd 1 and 2.

Here is the code from 7th edition init.c:

open(tty, 2);
dup(0);
dup(0);
...
execl(getty, minus, tty, (char *)0);

And here is how ssh does it:

ioctl(*ttyfd, TCSETCTTY, NULL);
fd = open("/dev/tty", O_RDWR);
if (fd < 0)
    error("%.100s: %.100s", tty, strerror(errno));
close(*ttyfd);
*ttyfd = fd;
...
/* Redirect stdin/stdout/stderr from the pseudo tty. */
if (dup2(ttyfd, 0) < 0) 
    error("dup2 stdin: %s", strerror(errno));
if (dup2(ttyfd, 1) < 0) 
    error("dup2 stdout: %s", strerror(errno));
if (dup2(ttyfd, 2) < 0) 
    error("dup2 stderr: %s", strerror(errno));

(The dup2 function dups arg1 into arg2, closing arg2 first if necessary.)

And here is how xterm does it:

if ((ttyfd = open(ttydev, O_RDWR)) >= 0) {
    /* make /dev/tty work */
    ioctl(ttyfd, TCSETCTTY, 0);
...
/* this is the time to go and set up stdin, out, and err
 */
{
/* dup the tty */
for (i = 0; i <= 2; i++)
    if (i != ttyfd) {
    IGNORE_RC(close(i));
    IGNORE_RC(dup(ttyfd));
    }
/* and close the tty */
if (ttyfd > 2)
    close_fd(ttyfd);
Mark Plotnick
  • 24,913
  • 2
  • 59
  • 81