Writing to stdin and reading from stdout (UNIX/LINUX/C Programming)

47,903

Solution 1

Attempting to write on a file marked readonly or vice-versa would cause write and read to return -1, and fail. In this specific case, stdin and stdout are actually the same file. In essence, before your program executes (if you don't do any redirection) the shell goes:

  if(!fork()){
       <close all fd's>
       int fd = open("/dev/tty1", O_RDWR);
       dup(fd);
       dup(fd);
       execvp("name", argv);
  }

So, stdin, out, and err are all duplicates of the same file descriptor, opened for reading and writing.

Solution 2

read(STDIN_FILENO, message, 20); 
write(STDOUT_FILENO, message, 20);

Should work. Note - stdout my be a different place from stdin (even on the command line). You can feed output from another process as stdin into you process, or arrange the stdin/stdout to be files.

fprintf/fgets have a buffer - thus reducing the number of system calls.

Solution 3

If you run a program on UNIX

myapp < input > output

You can open /proc/{pid}/fd/1 and read from it, open /proc/{pid}/fd/0 and write to it and for example, copy output to input. (There is possibly a simpler way to do this, but I know it works)

You can do any manner of things which are plain confusing if you put your mind to it. ;)

Solution 4

Best guess - stdin points to where the input is coming from, your terminal and stdout points to where output should be going, your terminal. Since they both point to the same place they are interchangeable(in this case)?

Solution 5

It's very possible that file descriptors 0, 1, and 2 are all open for both reading and writing (and in fact that they all refer to the same underlying "open file description"), in which case what you're doing will work. But as far as I know, there's no guarantee, so it also might not work. I do believe POSIX somewhere specifies that if stderr is connected to the terminal when a program is invoked by the shell, it's supposed to be readable and writable, but I can't find the reference right off..

Generally, I would recommend against ever reading from stdout or stderr unless you're looking for a terminal to read a password from, and stdin has been redirected (not a tty). And I would recommend never writing to stdin - it's dangerous and you could end up clobbering a file the user did not expect to be written to!

Share:
47,903
Tim
Author by

Tim

Updated on July 09, 2022

Comments

  • Tim
    Tim almost 2 years

    I was working on an assignment where a program took a file descriptor as an argument (generally from the parent in an exec call) and read from a file and wrote to a file descriptor, and in my testing, I realized that the program would work from the command-line and not give an error if I used 0, 1 or 2 as the file descriptor. That made sense to me except that I could write to stdin and have it show on the screen.

    Is there an explanation for this? I always thought there was some protection on stdin/stdout and you certainly can't fprintf to stdin or fgets from stdout.

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    int main()
    {
        char message[20];
        read(STDOUT_FILENO, message, 20);
        write(STDIN_FILENO, message, 20);
    
        return 0;
    }
    
  • Ed Heal
    Ed Heal over 12 years
    But they may not be your terminal.
  • Avery3R
    Avery3R over 12 years
    @Ed then it will read/write from/to whatever stdin/stdout points to. That was a lot of this/that.
  • Vladimir Panteleev
    Vladimir Panteleev over 5 years
    Correction, this is not done by the shell but the terminal (emulator). The shell will inherit its stdin/stdout handles as any other process.