richard@aiai.ed.ac.uk (Richard Tobin) (08/07/90)
In article <6366.26be9bd9@csv.viccol.edu.au> timcc@csv.viccol.edu.au (Tim Cook) writes: > if (fork ()) { > /* Subprocess */ No, fork() returns non-zero in the parent, so you're having the parent rather than the child exec /dir/command. This is why you are returning to the shell and leaving the other process in the background. Try if(fork() == 0) instead. The other problem is that the process reading the pipe doesn't close the other (write) end. Read from a pipe returns eof if there is no process that could write more data. The parent should do this after the fork(): close(pipe_descriptors[1]); -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
timcc@csv.viccol.edu.au (Tim Cook) (08/07/90)
I am having a bit of fun writing a utility that parses the output of a
command that it exec's in a subprocess. What I am doing is basically
(minus error checking):
int pipe_descriptors[2] ;
pipe (pipe_descriptors) ;
if (fork ()) {
/* Subprocess */
dup2 (pipe_descriptors[1], 1) ;
execl ("/dir/command", "command", "arg", 0) ;
/*NOTREACHED*/ }
/* Parent continues here */
pipe_stream = fdopen (pipe_descriptors[0], "r") ;
while (! feof (pipe_stream)) {
fgets (buffer, sizeof (buffer) - 1, pipe_stream) ;
/* Parsing of what is in "buffer"... */
}
Well, I get the output of "command" coming through on "pipe_stream", but
I don't get end-of-file. The fgets call just blocks when there is nothing
left in the pipe (and not because the last record output by "command" was
not terminated by a newline).
Can anyone help me set this up so that I see EOF? Can anyone also tell me
how to have the parent process retain control of the tty that it was
invoked on? At the moment, the shell regains control when the process
exec-ed by the child completes, indicating that the child got control.
md@sco.COM (Michael Davidson) (08/08/90)
In article <6366.26be9bd9@csv.viccol.edu.au> timcc@csv.viccol.edu.au (Tim Cook) writes: >I am having a bit of fun writing a utility that parses the output of a >command that it exec's in a subprocess. What I am doing is basically >(minus error checking): > > int pipe_descriptors[2] ; > > pipe (pipe_descriptors) ; > if (fork ()) { > /* Subprocess */ > dup2 (pipe_descriptors[1], 1) ; /* Hey!! how about doing a close(pipe_descriptors[0]; here .... */ > execl ("/dir/command", "command", "arg", 0) ; > /*NOTREACHED*/ } > > /* Parent continues here */ > pipe_stream = fdopen (pipe_descriptors[0], "r") ; /* Hey!! how about doing a close(pipe_descriptors[1]; here .... */ > > while (! feof (pipe_stream)) { > fgets (buffer, sizeof (buffer) - 1, pipe_stream) ; /* now when the child closes the write side of the pipe (probably */ /* when it exits) you should see an EOF ... */ /* in the interests of "keeping your process table tidy" it would */ /* also be a really GOOD IDEA (TM) to do a wait() here */ > > /* Parsing of what is in "buffer"... */ > } > >Well, I get the output of "command" coming through on "pipe_stream", but >I don't get end-of-file. The fgets call just blocks when there is nothing >left in the pipe (and not because the last record output by "command" was >not terminated by a newline). Because there is still an open file which refers to the "write" side of the pipe - the fact that it is in your own process doesn't matter - you will never get an EOF from a pipe unless you set it up properly. In general, unless you *know* how to handle the necessary low level process and file manipulation necessary to set up pipes correctly *and* you have a good reason why the functionality provided by the library routine "popen()" is either unsuitable or inadequate you should use "popen()" and "pclose()"
timcc@csv.viccol.edu.au (Tim Cook) (08/08/90)
In article <6366.26be9bd9@csv.viccol.edu.au>, I asked for help with pipes.
Well, it seems I did overlook something that should have been obvious.
Both processes needed to close the write end of the pipe before the read
end would see EOF. My other problem where my ``child'' process got control
of the tty was due to a switch statement that I wrote but did not
double-check (I did not actually use an if statement like the one in my
example code). I got the parent confused with the child.
Thanks to those who wrote with answers, and to those who are yet to write
(due to the propagation properties of Usenet and the wizards mailing list).
One last thing. Only one person has written so far and suggested popen(3),
which would have done what I was wanting to do nicely. I didn't think of
it because I don't get mention of it when I do a "man -k pipe" on my
system.
--
Tim Cook Systems Administrator, Victoria College Computer Services
parrot - n. An animal that has the ability to imitate man, but not the
intelligence to refrain from doing so.