Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send file writes to in-memory buffer (fopen something, but write to buffer, not disk)

Tags:

c

ios

I'd like to:

  1. redirect stdout/stderr
  2. to an in-memory buffer, rather than to disk
  3. while leaving stdout/err running as normal

I know how to use dup2 and freopen to:

  • redirect stdout/err to a file of my choosing
  • while leaving stdout/err running as normal

...but I'm not sure about item 2?

REASON: I want to post-process the data going to stdout/err (that's coming from 3rd party code), and then send it to a webserver - while leaving the application running as normal.

WHY? ... because right now when our app runs we're seeing critical data go to stdout (and err) from 3rd party code, and it's a PITA getting users to try and mess around with local logfiles. I'd rather capture "the last N bytes" into a ring buffer, post-process it, and then - iff there's a problem that the user reports - send that to server.

WHY AVOID FILES? ... because this is for code that has to run on iOS as well as desktop, and "constantly writing to a file" is something I want to avoid, since I don't want it as a file anyway. Also ... I'd have to worry about maintaining that file, proactively trimming its size, etc.

like image 614
Adam Avatar asked Mar 06 '12 20:03

Adam


1 Answers

Stdout is a basic file handle, which means its a pointer.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv);

int main (argc,argv)
int argc;
char **argv;
{
    stdout = &(*stderr);
    fprintf(stdout, "test");
    return 0;
}

By declaring stdout to point to a different file handle, this program redirects stdout. To test it, compile it as test, and then type ./test > t and ./test 2> t on the command line.

The redirected stdout pipe will still output the word test, whereas the redirected stderr pipe will not.

Since files are streams, read this section of the GNU C Library for how to create memory streams. This example creates a text buffer to dynamically resize for holding input, and redirects stdout to point to it.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv);

int main (argc,argv)
int argc;
char **argv;
{
    char *bp;
    size_t size;
    FILE *stream;

    stream = open_memstream (&bp, &size);
    stdout = &(*stream);
    fprintf(stdout, "test");
    fflush(stdout);
    fprintf(stderr, "buf = %s, size = %d\n", bp, size);
    fclose (stream);
    free(bp);
    return 0;
}

Pay careful attention to the sections on flushing the buffers when switching between input and output in the manual.

like image 124
Spencer Rathbun Avatar answered Sep 29 '22 11:09

Spencer Rathbun