2

This is my c program read from stderr i write

#include <uninstd.h>
#include <stdio.h>

int main(void) {
 char buff[3];
 read(2, buff, sizeof(buff));
 printf("%s", buff");
 return 0;
}

My question how can i send a stderr to it. Most of search show like, in bash redirection

command 2> file

But this send the stderr to a file.

How can i pass to my program. Like pip,

command 2 "somthing here" ./myprogram

Thanks for answers.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • STDERR_FILENO is an output file descriptor. You can't read from it. If you check what read returns (which you should always do!) you should probably be getting either an error (-1) or end-of-file (0). What is the real problem you're having? Why do you want to read from standard error? – Paulo Tomé Mar 21 '20 at 15:18
  • @PauloTomé, sure you can, if it's open for writing. At least on the Linux systems I've used, that's the default. e.g. cat /dev/stderr works (as does cat /dev/stdout), and so does that program, well, at least after all the syntax errors and buffer overflows are fixed. – ilkkachu Mar 21 '20 at 15:47
  • 1
    stderr is open for reading and writing and reading from stderr was usual before /dev/tty has been introduced. – schily Mar 21 '20 at 15:51

4 Answers4

3

It comes as a surprise to many people, given that most reference books and documentation always refer to standard error as an output, that it is in fact usually already open for read+write. Your program very much can read from file descriptor 2.

(Note: In this answer I am using the actual file descriptor numbers. The C streams such as stderr need not actually correspond with these file descriptors, as a program can change them, and it adds a layer of confusion to talk about what the C streams do. Your program is using read().)

File descriptor 2 is open for reading and writing

For programs in login sessions where no redirection has been used in a parent process, file descriptor 2 (standard error) is typically a duplicate of file descriptor 0 (standard input). They both reference the same underlying file description, which is typically the terminal of the login session (opened and duplicated by ttymon or, on older systems, getty at the very start of the session).

If you read from file descriptor 2, you get the same input as if you had read from file descriptor 0.

BTW: Reading from file descriptor 2 was frequently done for things like password input; before the /dev/tty device was introduced, around 1977. The reason for reading from file descriptor 2 was to obtain input from the original terminal when file descriptor 0 had been redirected elsewhere (as is the case in the middle of a pipeline, for example).

Even though /dev/tty has been available for a long time now, over 40 years, POSIX still requires file descriptor 2 to be open for reading as well.

What your program is not doing

Reading from the file descriptor 2 output of another program is a different thing. You canot easily do that by itself, without merging standard output with standard error. It usually involves a series of 3>&1 1>&2 2>&3 or suchlike swaps. A few shells permit pipes on the output file descriptor 2 by calling

prog1 2| prog2

But such shells are rare, and that's not what your program needs in any case.

Sending input to your program

If you want your program, reading from file descriptor 2, to read from something other than from the terminal, you of course redirect that file descriptor. You could use the normal input redirection syntax (the < operator in the shell), but libraries in your program, or even other code that you have written elsewhere, will have assumptions that they can write to this file descriptor.

The shell allows you to use the <> redirect operator that explicitly opens a file for both reading and writing. This is what you use when redirecting your program's file descriptor 2.

./myprogram 2<>filename

Outwith shell redirection, there are plenty of tools that allow manipulation of file descriptors. For example: With Laurent Bercot's chain-loading redirfd tool, that comes with execline, this redirection looks more like your hypothesis:

redirfd -u 2 filename ./myprogram

There is also shell syntax in the likes of the Bourne Again and Z shells (but not the Almquist shells) to provide "here documents" and "here strings" to file descriptor 2. Note that file descriptor 2 is opened read only by these shells in this case.

./myprogram 2<<< "here string"
schily
  • 19,173
1

stderr is meant for writing, not reading. Sometimes it is a duplicate of stdin (e.g. when all 3 in/out/err are connected to terminal). To read stderr of another program, you redirect the stderr of that program, to the stdin of another.

e.g. to directs stdout to a file, and stderr to ./myprograms's stdin.

command 2>&1 >a_file | ./myprogram
  • 3
    You are mistaken, stderr is open for reading and writing. – schily Mar 21 '20 at 15:49
  • @schily But you can not always read from it. You should expect it to be an output. – ctrl-alt-delor Mar 21 '20 at 16:46
  • 1
    There are a few exceptions, when you cannot read from stderr. These exceptions are usually hit when you did redirect stderr. The shell however allows to use the <> redirect operator that explicitly opens a file for reading and writing. – schily Mar 21 '20 at 18:56
1

With shells like bash and zsh (But not plain POSIX sh), you can redirect one program's standard error to another program's standard input via firstprogram 2> >(second program).

Example:

$ perl -E 'say "perl stdout"; warn "perl stderr\n"' 2> >(awk '{print "awk", $0}')
perl stdout
awk perl stderr
Shawn
  • 1,173
  • 6
  • 8
0

To have the shell set up an input redirection for stderr, you'd use <, << or <<< and prefix the file descriptor number:

./myprog 2< somefile.txt

or

./myprog 2<<< "some text"

Though if you redirect stderr like that, the program can't output to it, which will mean you won't see any error messages the program (or any libraries it uses) might try to print, and in addition the program will get errors for trying to write those messages.

You may want to reconsider if there would be some other way of doing what ever it is you're doing. In the least, consider using e.g. fd 3 if the idea is to provide some input to the program.

ilkkachu
  • 138,973