0

I want to do simple thing: my_process | proc2 | proc3, but programatically - without using shell, that can do this pretty easy. Is this possible? I cannot find anything :(

EDIT: Well, without code, nobody will know, what problem I'm trying to resolve. Actually, no output is going out (I'm using printfs)

int pip1[2];
pipe(pip1);

dup2(pip1[1], STDOUT_FILENO); 
int fres = fork();

if (fres == 0) {
    close(pip1[1]);
    dup2(pip1[0], STDIN_FILENO);
    execlp("wc", "wc", (char*)0);
}
else {
    close(pip1[0]);
}
Vality
  • 6,577
  • 3
  • 27
  • 48
Mike S.
  • 1,995
  • 13
  • 25

3 Answers3

1

Please learn about file descriptors and the pipe system call. Also, check read and write.

Community
  • 1
  • 1
Alex
  • 635
  • 6
  • 15
1

Your 'one child' code has some major problems, most noticeably that you configure the wc command to write to the pipe, not to your original standard output. It also doesn't close enough file descriptors (a common problem with pipes), and isn't really careful enough if the fork() fails.

You have:

int pip1[2];
pipe(pip1);

dup2(pip1[1], STDOUT_FILENO);      // The process will write to the pipe
int fres = fork();                 // Both the parent and the child will…
                                   // Should handle fork failure
if (fres == 0) {
    close(pip1[1]);
    dup2(pip1[0], STDIN_FILENO);   // Should close pip1[0] too
    execlp("wc", "wc", (char*)0);
}
else {                             // Should duplicate pipe to stdout here
    close(pip1[0]);                // Should close pip1[1] too
}

You need:

fflush(stdout);    // Print any pending output before forking

int pip1[2];
pipe(pip1);

int fres = fork();

if (fres < 0)
{
    /* Failed to create child */
    /* Report problem */
    /* Probably close both ends of the pipe */
    close(pip1[0]);
    close(pip1[1]);
}
else if (fres == 0)
{
    dup2(pip1[0], STDIN_FILENO);
    close(pip1[0]);
    close(pip1[1]);
    execlp("wc", "wc", (char*)0);
}
else
{
    dup2(pip1[1], STDOUT_FILENO);
    close(pip1[0]);
    close(pip1[1]);
}

Note that the amended code follows the:

Rule of thumb: If you use dup2() to duplicate one end of a pipe to standard input or standard output, you should close both ends of the original pipe.

This also applies if you use dup() or fcntl() with F_DUPFD.

The corollary is that if you don't duplicate one end of the pipe to a standard I/O channel, you typically don't close both ends of the pipe (though you usually still close one end) until you're finished communicating.

You might need to think about saving your original standard output before running the pipeline if you ever want to reinstate things.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

As Alex answered, you'll need syscalls like pipe(2), dup2(2), perhaps poll(2) and some other syscalls(2) etc.

Read Advanced Linux Programming, it explains that quite well...

Also, play with strace(1) and study the source code of some simple free software shell.

See also popen(3) -which is not enough in your case-

Recall that stdio(3) streams are buffered. You probably need to fflush(3) at appropriate places (e.g. before fork(2))

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547