From: FangQ on
thank you very much for all of the responses. I found all your
comments very helpful and Marcel's example code worked beautifully for
me.

To answer the question about using popen and pipe together, I actually
don't know other alternatives to save the output into a buffer, except
running an external command via popen and read from it. Most of the
examples I saw invoke exec* to pipe the data to an external process,
but I don't have access (or know how to gain access) to the output.

For Marcel's example, I am trying to understand the 3 dup2.calls, can
some one commend on this?

dup2(STDIN_FILENO, d[1]); /*make d[1] pipe be the stdin of the
parent ?*/
dup2(d[0], STDIN_FILENO); close(d[0]);
f = popen("tac", "r");
dup2(d[1], STDIN_FILENO); close(d[1]);

thank you again

Qianqian

On Sep 19, 1:22 am, Barry Margolin <bar...(a)alum.mit.edu> wrote:
> In article <h91mfh$mm...(a)aioe.org>, pac...(a)kosh.dhis.org (Alan Curry)
> wrote:
>
> > In article <h91eoh$f1...(a)aioe.org>, I wrote:
>
> > >The next major thing is why are you using popen() at all? You already created
> > >a pipe and a child process, you don't need yet another pipe and yet another
> > >process (which is what popen gives you).
>
> > Correction: You do need another pipe (since you're piping in and out of the
> > "tac" process) but you don't really need the extra process.
>
> You may need it to avoid deadlock.  If the writer tries to write
> everything to the send pipe before reading anything, the receive pipe's
> buffer may fill up, and then the tac process would block, and stop
> reading from the send pipe, so it will fill up and the writer will block.
>
> I don't think this can happen with a command like "tac", since it can't
> start writing until it reads everything you send it.  But it can happen
> with other programs that produce output as they go (e.g. awk, grep,
> sed).  And even if you know the program produces one line of output for
> each line of input, you can't solve it by doing alternating writes and
> reads, because it's likely that the program uses stdio, which by default
> does full buffering when output is to a pipe.
>
> Using separate processes (or threads) for writing and reading solves
> this problem.  You could also do it with select(), but that's a little
> more complicated to code.
>
> --
> Barry Margolin, bar...(a)alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***

From: Marcel Bruinsma on
Am Samstag 19 September 2009 18:57, FangQ a écrit :

> For Marcel's example, I am trying to understand the 3 dup2
> calls, can some one comment on this?
>
> dup2(STDIN_FILENO, d[1]); /*make d[1] pipe be the stdin
> of the parent ?*/

Save the original stdin in d[1] (else it will be lost).

I should have added,
fcntl(d[1], F_SETFD, fcntl(d[1], F_GETFD)|FD_CLOEXEC);
otherwise this copy of the original stdin will remain open
in the 'tac' process created by popen().

> dup2(d[0], STDIN_FILENO); close(d[0]);

Redirect stdin for the 'tac' command, which reads its input from
stdin; and after duplicating d[0] (the read end of the pipe) to
stdin, close d[0], because it is no longer needed in the parent.

> f = popen("tac", "r");

Open 'tac' with stdin coming from the read end of the pipe,
and stdout going to fileno(f).

> dup2(d[1], STDIN_FILENO); close(d[1]);

Restore the original stdin, which was saved in d[1], and then
release the d[1] descriptor.

--
printf -v email $(echo \ 155 141 162 143 145 154 142 162 165 151 \
156 163 155 141 100 171 141 150 157 157 056 143 157 155|tr \ \\\\)
# Live every life as if it were your last! #