1

If I use printf ("Hello!"); are there any ways to read what I've printed into stdout?

I saw C language. Read from stdout (it uses pipe) but it doesn't work:

#define _XOPEN_SOURCE

#include <stdio.h>
#include <unistd.h>

#define DIM 10

int main(void)
{
    char s[DIM];
    int fds[2];

    pipe(fds);
    dup2(fds[1], fileno(stdout)); //I added fileno()

    printf("Hello world!");

    read(fds[0], s, DIM);
    printf("\n%s",s);

    return 0;
}

I also tried using a file descriptor but neither it doesn't work:

#define _XOPEN_SOURCE

#include <stdio.h>
#include <unistd.h>

#define DIM 10
#define MYFILE "/path/file"

int main(void)
{
    FILE *fd;
    char s[DIM];

    fd = fopen(MYFILE,"w+");
    dup2(STDOUT_FILENO, fileno(fd));

    printf("Hello world!");

    fseek(fd, 0, SEEK_SET);
    fgets(s, DIM, fd);

    printf("\n%s",s);
    return 0;
}

How can I do?

untitled
  • 389
  • 4
  • 13
  • In the first code, redirection is active, so any *print* will go to the pipe, you can't see anything. In example 2, redirection was made in reverse (change args order to dup2 call). Anyway, read from stdout is a non sense, stdout is a out stream; and read what you wrote to stdout can't be made this way from a single process. But more generally, what you want is *strange*, why do you want this? – Jean-Baptiste Yunès Jan 24 '16 at 06:43

4 Answers4

2

Generally not, unless standard output has been redirected to a file. Functions which write to standard output (like printf()) don't record their output anywhere within your process, and there's no way to read your previous output back from anything other than a normal file*. For instance, if your process is printing its output to a terminal, trying to read data from the terminal will give you back what the user is inputting, not what you previously output.

Your second program is almost working. There's a few small issues you'll need to fix first, though:

  1. The output from your first printf() won't be output, as it's missing a newline. Either add a newline, or call fflush(stdout) to force it to be output anyway.

  2. You're trying to printf() your results, but standard output is still pointing to that file, so you'll never see it. The easiest way to display something after overwriting standard output will be to use fprintf(stderr, ...).

(*: Or certain things which behave a lot like files, like block devices or named pipes. But you're probably not working with those.)

  • If I use terminal I can obtain only input? Not ouput? – untitled Jan 23 '16 at 19:15
  • @SimoneBonato Correct. Writing to a terminal generates output; reading from a terminal gives you input. –  Jan 23 '16 at 19:20
  • I'm referring to "Functions which write to standard output (like printf()) don't record their output anywhere within your process". In terminal there are also my previous output... – untitled Jan 23 '16 at 19:24
  • 2
    What does "In terminal there are also my previous output" mean? You write data to the pipe, the terminal driver reads it and displays it on the terminal, but the data doesn't exist in memory anywhere (other than memory of the terminal emulator, or the windowing system, etc.) It just appears as glyphs on your screen. – William Pursell Jan 23 '16 at 19:47
  • If I prints "Hello", I see it in my terminal. – untitled Jan 23 '16 at 19:52
  • "For instance, if your process is printing its output to a terminal, trying to read data from the terminal will give you back what the user is inputting, not what you previously output." – untitled Jan 23 '16 at 20:07
  • I also have to change `dup2(FILENO_STDOUT, fileno(fd))` into `dup2(fileno(fd), FILENO_STDOUT)`. Now it works. – untitled Jan 24 '16 at 12:50
1

If stdout is a file, you can open another file descriptor on it and seek and read. If it is a pipe, on the other hand, you cannot. Data written into a pipe can be read only once. If the read end of that pipe is associated with a tty, then it will be read by the device driver and no longer be available for your process to read. duping a file descriptor does not make the data available twice, so the approach with dup2 cannot work (indeed, dup2(fds[1], STDOUT_FILENO) first closes STDOUT_FILENO, so now you're just going to write into the pipe). You could fork a process that duplicates the data, or use the splice/tee system calls to duplicate the data, but really you need to ask: why do you want to do this?

William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

Visit here:

https://github.com/pouyanh/isolated-iostream

This is about transparently output buffering of stdout when calling another function

pouyan
  • 307
  • 1
  • 5
0

If you are on Linux you could use fmemopen:

#include <iostream>
#include <stdio.h>
char mybuffer[BUFF_SIZE];
FILE * pFile = fmemopen(mybuffer, BUFF_SIZE, "w");
std::swap(stdout, pFile); //swap pFile to stdout

rc = someFunctionWritingToStdout();

std::swap(stdout, pFile); //restore
fclose(pFile); // flush and close stream
cout << "-....-" << endl;
cout << mybuffer << endl;
cout << "-....-" << endl;

https://www.systutorials.com/docs/linux/man/3-fmemopen/

kaah
  • 121
  • 1
  • 3