5

I would like to be able to redirect stderr to a C string because I need to use the string in the program I'm writing. I would like to avoid writing to a file (on the hard drive) first then readings the file to get the string. What is the best way to get this done?

user1660675
  • 149
  • 3
  • 10

3 Answers3

15

You could just use setbuf() to change stderr's buffer:

#include <stdio.h>

int main(void)
{
    char buf[BUFSIZ];
    setbuf(stderr, buf);
    fprintf(stderr, "Hello, world!\n");
    printf("%s", buf);
    return 0;
}

prints:

Hello, world! 
Hello, world!

Note: you should change the buffer before any operation on the stream.

iabdalkader
  • 17,009
  • 4
  • 47
  • 74
  • Oh nice! Didn't know you could even do that! Is `BUFSIZ` defined in stdio? – mmtauqir Feb 05 '13 at 20:02
  • @mtahmed yes, there's more info in the man page, you could also set the buffering mode if you use `setvbuf()` – iabdalkader Feb 05 '13 at 20:03
  • Is there a way to get a callback when 'buf' is written to? – user1660675 Feb 05 '13 at 22:14
  • @user1660675 not that I know of, maybe if you use select on the fd not sure. – iabdalkader Feb 05 '13 at 22:16
  • -1 because this is a hack. The buffer used by `setbuf` is for use by the framework only. This works only if (a) you call `setbuf` immediately the `fprintf`, and your string fits entirely in `BUFSIZ` (or maybe even limited to `BUFSIZ/2` if the buffer is used as a ping-pong, depends on dark implementation details of stdio). – Mark Lakata Aug 01 '14 at 21:05
  • I don't think this will work with sub processes, ie. `system("/bin/echo foo > /dev/stderr");`, because you are only changing the buffering for the *stream* interface to stderr, and not the actual `stderr` file descriptor. – Mark Lakata Aug 01 '14 at 21:11
  • How can I prevent fprintf call to be printed out to the console in this example? – Bren Aug 27 '23 at 22:17
2
  1. Redirect stderr to stdout and pipe to your C program. See How to pipe stderr, and not stdout?
  2. Read from stdin in your C program, of course.

This is assuming stderr is coming from another program. If you want to capture all stderr output from your program and process, then in a separate thread listen for writes to stderr via fopen("/dev/stderr", "r").

Community
  • 1
  • 1
djechlin
  • 59,258
  • 35
  • 162
  • 290
  • I'll give this a shot. I am trying to capture stderr from within the program and use it within that same program so, I would use fopen on stderr then redirect to stdout? – user1660675 Feb 05 '13 at 19:55
-1

I gave an solution using C++ to redirect stdout and stderr to a function (called for each line). I know this was tagged as C, but the guts of my solution use the POSIX api.

See https://stackoverflow.com/a/25087408/364818

Community
  • 1
  • 1
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123