What I would like to do is to redirect stdout of some application, let say A to another application, let say B. All this from another external application (written in C).

Any ideas?

Dani AI

Generated

Short answer: run A and B as two child processes and connect them with two pipes: one pipe carries A's stdout into B's stdin, the other carries B's stdout back to the controller. That gives full control from your C program and lets you read B's output into a buffer and collect exit status information.

Steps to implement (POSIX):

  • create two pipes (p_ab for A->B, p_out for B->parent) before any fork.
  • fork child A: dup2 p_ab write end onto STDOUT, close unused fds, exec A.
  • fork child B: dup2 p_ab read end onto STDIN, dup2 p_out write end onto STDOUT, close unused fds, exec B.
  • in the parent: close the ends you do not use, read from p_out read end into a dynamically grown buffer (or fdopen + fgets), and waitpid both children to get exit statuses.

A minimal sketch (error checks omitted for clarity):

int p_ab[2], p_out[2];
pipe(p_ab);   /* A -> B */
pipe(p_out);  /* B -> parent */

if (fork() == 0) {           /* child A */
  dup2(p_ab[1], STDOUT_FILENO);
  close(p_ab[0]); close(p_ab[1]);
  close(p_out[0]); close(p_out[1]);
  execlp("progA", "progA", (char*)NULL);
  _exit(127);
}

if (fork() == 0) {           /* child B */
  dup2(p_ab[0], STDIN_FILENO);
  dup2(p_out[1], STDOUT_FILENO);
  close(p_ab[0]); close(p_ab[1]);
  close(p_out[0]); close(p_out[1]);
  execlp("progB", "progB", (char*)NULL);
  _exit(127);
}

/* parent */
close(p_ab[0]); close(p_ab[1]);
close(p_out[1]);
/* read p_out[0] into memory, then close and waitpid children */

Notes and pitfalls:

  • Always close unused file descriptors in each process to avoid hangs.
  • If either program buffers output when not on a TTY, you may see delayed data; use line/unbuffered modes or a pty if interactive behavior is required.
  • For large or bidirectional streams avoid simple blocking reads; use select/poll or nonblocking I/O to prevent deadlocks.
  • Use waitpid and WIFEXITED/WEXITSTATUS to get each child's exit status.

This follows the direction pointed to (use pipes), addresses 's need to capture B's output into a variable, and answers 's question about collecting exit status as well.

Recommended Answers

All 7 Replies

Do some research on pipes. Your system likely has a function you can call from C (popen, or similar) for opening a pipe based stream. Or, if you don't need access to the output from B, you can use the equivalent command line piping with the system function:

system ( "A | B" );

Thanks for your reply!
So, now I have:

fprintf(some_pipe, "%s", "some_input_text");

When I write "some_input_text" to some_pipe it then works on this input and produces the output, which is redirected to stdout (displayed on screen).

Is there any way to redirect it somewhere else, like local variable so I have access to it?

>Is there any way to redirect it somewhere else, like local variable so I have access to it?
Erm, you could use sprintf instead of fprintf to write to a string. But I'm not entirely sure how we got from "send the output of program A to program B from program C" to "write formatted output to a variable"...

>Is there any way to redirect it somewhere else, like local variable so I have access to it?
Erm, you could use sprintf instead of fprintf to write to a string. But I'm not entirely sure how we got from "send the output of program A to program B from program C" to "write formatted output to a variable"...

fprintf(some_pipe, "%s", "some_input_text");

"some_input_text" is an output read from pipe 'A' (which was in 'r' mode - to read from it), some_pipe is pipe 'B' (which was in 'w' mode - for write). Pipe A didn't have to have any 'input' to produce output, but pipe B did - unfortunately I also need the output of pipe B and I don't know how to create read/write pipe to make it work. I think there is some easier way for this...
I only wanted to put some data through a couple of 'sub-applications' and read the effects in some 'controlling application'...

>I don't know how to create read/write pipe to make it work.
Have you tried creating two pipes? One for input and one for output?

>I don't know how to create read/write pipe to make it work.
Have you tried creating two pipes? One for input and one for output?

I'm accually trying to do so, but I'm new to this stuff and It is not easy for me to understand how to use fork() and pipe() - which I think I should use...

> All this from another external application (written in C).
So is this application interested in any way as to what "A | B" does ?

Does it say
- collect the output of B
- get the exit status of A

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.