[comp.lang.c] Filtering I/O -- both of them.

d89cb@efd.lth.se (Christian Brunschen) (07/08/90)

I'm working an a small program that will function as an i/o filter for
mail (1) -- fyi, so tat all occurrences of 'mail' can be replaced with
'femail' (No, not my idea -- I'm doing this for a friend :)

Anyway, i could use popen(), but that only lets me specify either
stdin or stdout replacement -- not both, the way I need it.

So I thought of :
* creating two pipes
* fork()ing
* in the child process, redirect stdin to one pipe & stdout to the other
* in the cild process, execve() mail(1)
* in the parent process, perform i/o and filtering

BUT (and here's my question) :
how do I actually redirect stdin / stdout to the pipes I created ?

I tried

stdin = fdopen (MyPipe [1], "r");

but that, naturally, didn't work (illegal lhs of assignment)

So, if anyone has any ideas, please tell me; All help will be greatly
appreciated!

aTdHvAaNnKcSe

-- Christian Brunschen

-- 
+--------------------------------+---------------------------------+
| Internet  : d89cb@efd.lth.se   | IRC : snooker                   |
+------------------------------------------------------------------+
| Apart from the unknowns, everything is obvious."                 |
|                     - ZORAC, board computer of the Shapieron, in |
|                       James P. Hogan's "Giants' Star"            |
+------------------------------------------------------------------+

cpcahil@virtech.uucp (Conor P. Cahill) (07/09/90)

In article <1990Jul8.120742.18213@lth.se> d89cb@efd.lth.se (Christian Brunschen) writes:
>So I thought of :
>* creating two pipes
>* fork()ing
>* in the child process, redirect stdin to one pipe & stdout to the other

You have to be very carefule to avoid a deadlock when using pipes in both
directions between two processes.

>BUT (and here's my question) :
>how do I actually redirect stdin / stdout to the pipes I created ?

>stdin = fdopen (MyPipe [1], "r");

This is real close.  what you do is:

	(void) fclose(stdin);		/* close stdin 			*/
	(void) close(0);		/* should be unnecessary	*/
	i = dup(pipe_read_fd);		/* i should be 0		*/
	(void) fdopen(i, "r");		/* stdin should map to pipe 0 	*/
	close(pipe_read_fd);		/* dont need anymore		*/

The reason for doing the dup() & fdopen is to ensure that fd0 gets 
assigned to stdin since there may be software that does a read(0,...).

Note that I did no error checking.  You should add the appropriate error
checking for each step (other than the close(0) which should fail if 
stdin was appropriately mapped to 0).


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

leo@ehviea.ine.philips.nl (Leo de Wit) (07/10/90)

In article <1990Jul08.223103.1244@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
|In article <1990Jul8.120742.18213@lth.se> d89cb@efd.lth.se (Christian Brunschen) writes:
    []
|>BUT (and here's my question) :
|>how do I actually redirect stdin / stdout to the pipes I created ?
|
|>stdin = fdopen (MyPipe [1], "r");
|
|This is real close.  what you do is:
|
|	(void) fclose(stdin);		/* close stdin 			*/
|	(void) close(0);		/* should be unnecessary	*/
|	i = dup(pipe_read_fd);		/* i should be 0		*/
|	(void) fdopen(i, "r");		/* stdin should map to pipe 0 	*/
|	close(pipe_read_fd);		/* dont need anymore		*/
|
|The reason for doing the dup() & fdopen is to ensure that fd0 gets 
|assigned to stdin since there may be software that does a read(0,...).
|
|Note that I did no error checking.  You should add the appropriate error
|checking for each step (other than the close(0) which should fail if 
|stdin was appropriately mapped to 0).

The dup() should indeed return 0 (or alternatively, use
dup2(pipe_read_fd,0)), but I think there is no guarantee that
fdopen(i,"r") returns stdin (though 'old-style' stdio implementations
will probably do so).

How about:
    (void)dup2(pipe_read,fileno(stdin));
    (void)close(pipe_read);

(I'm pretty sure there are problems with this as well)?

    Leo.