Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!usc!snorkelwacker.mit.edu!shelby!msi.umn.edu!noc.MR.NET!gacvx2.gac.edu!gacvx2.gac.edu!scott From: scott@erick.gac.edu (Scott Hess) Newsgroups: comp.unix.questions Subject: Re: Master/Slave Processes? Message-ID: Date: 10 Feb 91 00:39:04 GMT References: <1991Feb08.085034.13605@ariel.unm.edu> Distribution: usa Organization: Gustavus Adolphus College Lines: 87 Nntp-Posting-Host: erick.gac.edu In-reply-to: mdiehl@hydra.unm.edu's message of 8 Feb 91 08:50:34 GMTLines: 87 In article <1991Feb08.085034.13605@ariel.unm.edu> mdiehl@hydra.unm.edu (J. Michael Diehl) writes: I am trying to spawn a process and be able to write to it's stdin and read from it's stdout. Pipe, Exec, System don't seem to do the trick. Any ideas? I know this is possible since the window system seems to do this. Please Help Me! [Since there appears to be some small interest in this (I've seen a couple posts which do not quite answer this), and I'd really have enjoyed an explaination when _I_ was trying to figure this out, I've posted a simple explaination to the net. -scott] What you want is a more capable version of the popen(3) call, I presume. popen(3) only allows you to start a subprocess for reading from its stdout, or for writing to its stdin. There are good reasons for this. The problem is deadlock. If you were to open a file for both stdin and stdout, you run the risk of having the child process waiting for data on it's stdin before proceeding, while you are waiting for data on the child's stdou before proceeding. Also, if you attempt to write more than some system defined amount to the stdin, the buffers will fill (say you try to write, oh, 16k of data to the child's stdin. Then, the child processes some, and writes the result to stdout. Let's use cat(1) as the child. If your system buffers could only hold 4k, you'll write 4k, the child transfers that to its stdout, you write 4k, and you deadlock - the child's stdout is full, so it cannot run anymore. You're waiting to finish the 16k write, so you cannot run anymore. Apply kill(1) repeatedly :-). That out of the way, how can you boldly forge ahead and accomplish this thing anyhow? The simplest case is fairly simple. To get a file descriptor for reading and writing to a child process's stdin, stdout (and stderr, which I'll map to stdout) do something like the following (under BSD 4.3, using ANSI-C): int sys( const char *cmd) { int fds[ 2]; int cpid; if( socketpair( AF_UNIX, SOCK_STREAM, AF_UNSPEC, fds)==-1) return -1; if( !(cpid=fork())) { /* On the child side */ const char *shell=getenv( "SHELL"); if( shell==NULL) shell="/bin/sh"; close( fds[ 0]); /* Close the parent's fd */ dup2( fds[ 1], 0); /* dup into stdin */ dup2( fds[ 1], 1); /* stdout */ dup2( fds[ 1], 2); /* and stderr */ close( fds[ 1]); execl( shell, shell, "-c", cmd, NULL); exit( 1); /* didn't succeed, exit w/error */ } if( cpid==-1) /* If there was a fork() error, */ { close( fds[ 1]); /* Close up the sockets */ close( fds[ 0]); return -1; } close( fds[ 1]); /* Close the child-side fd */ return fds[ 0]; /* Return the parent-side file descriptor */ } [This has been very minimally tested on a BSD 4.3 system, and probably won't work at all in the real world. It's just meant as an example, anyhow -scott] The socketpair() call returns a sort of two-way pipe [the pipe() call returns a one-way pipe]. Either end can read/write from it. After the fork(), the child closes the parent's side, duplicates the child side fd into 0, 1, and 2 (note that this code requires that 0, 1, and 2 exist, so that socketpair() doesn't put one of the ends into 0, 1, or 2), closes the child side, and execs a shell to attempt to run the program. On the parent side, just close up the child side, and away we go. This is very quick and dirty - you'll probably want more pre and post processing in there. It also doesn't address how to avoid the deadlock problems - that's going to be up to you . . . -- scott hess scott@gac.edu Independent NeXT Developer GAC Undergrad "Tried anarchy, once. Found it had too many constraints . . ." "Buy `Sweat 'n wit '2 Live Crew'`, a new weight loss program by Richard Simmons . . ."