2

I am programming a shell in c++. It needs to be able to pipe the output from one thing to another. For example, in linux, you can pipe a textfile to more by doing cat textfile | more.

My function to pipe one thing to another is declared like this:

void pipeinput(string input, string output);

I send "cat textfile" as the input, and "more" as the output.

In c++ examples that show how to make pipes, fopen() is used. What do I send as my input to fopen()? I have seen c++ examples of pipeing using dup2 and without suing dup2. What's dup2 used for? How do you know if you need to use it or not?

neuromancer
  • 53,769
  • 78
  • 166
  • 223

3 Answers3

4

For a simple, two-command pipeline, the function interface you propose may be sufficient. For the general case of an N-stage pipeline, I don't think it is flexible enough.

The pipe() system call is used to create a pipe. In context, you will be creating one pipe before forking. One of the two processes will arrange for the write end of the pipe to become its standard output (probably using dup2()), and will then close both of the file descriptors originally returned by pipe(). It will then execute the command that writes to the pipe (cat textfile in your example). The other process will arrange for the read enc of the pipe to become its standard input (probably using dup2() again), and will then close both of the file descriptor originally returned by pipe(). It will then execute the command that reads from the pipe (more in your example).

Of course, there will be still a third process around - the parent shell process - which forked off a child to run the entire pipeline. You might decide you want to refine the mechanisms a bit if you want to track the statuses of each process in the pipeline; the process organization is then a bit different.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • cat textfile will write to stdout, correct? So what I'm actually pipeing is stdout? What's the code to do that? – neuromancer Apr 30 '11 at 23:18
  • @Phenom: what I said in my answer: _arrange for the write end of the pipe to become its standard output (probably using `dup2()`), and will then close both of the file descriptors originally returned by `pipe()`. It will then execute the command that writes to the pipe (`cat textfile` in your example)_ – Jonathan Leffler May 01 '11 at 00:27
  • Cool. I thought that dup2() was just a safer form of close(). However, it seems that it can do redirection of stdout as well. – neuromancer May 01 '11 at 00:56
4

Take a look at popen(3), which is a way to avoid execvp.

Paul Beckingham
  • 14,495
  • 5
  • 33
  • 67
  • One thing to note is that you can easily get stdout but if you also want to stderr, take a look at previous post - http://stackoverflow.com/questions/280571/how-to-control-popen-stdin-stdout-stderr-redirection In the past, I had to spend some amount of time to figure out when there was an error in the command. – istudy0 May 01 '11 at 00:30
1

fopen() is not used to create pipes. It can be used to open the file descriptor, but it is not necessary to do so.

Pipes are created with the pipe(2) call, before forking off the process. The subprocess has a little bit of file descriptor management to do before execing the command. See the example in pipe's documentation.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • `fopen()` may use a file descriptor behind the scenes, but it creates (opens) a file stream, not a file descriptor. – Jonathan Leffler Apr 30 '11 at 23:06
  • @Johnathan: I meant that the `fdopen()` variant of `fopen()` can be used to open an existing file descriptor. – wallyk Apr 30 '11 at 23:09