redirecting standard i/o from an exec'ed programme

William Bill Mayne mayne at VSSERV.SCRI.FSU.EDU
Fri Aug 17 03:38:04 AEST 1990


In article <377 at fe2o3.UUCP> michael at fe2o3.UUCP (Michael Katzmann) writes:
>
>I have a task that requires the ability to fork off another programme but
>to supply it's standard input and output. The SysV manuals describe
>
>	FILE *popen( command, type )
>	char *command, *type;
>
>which execs the command  a la "system()" and creates a pipe. "type" and be
>"r" if you want to read from the standard output of "command", or "w" if
>you want to write to standard input. However there doesn't seem to be any
>way to use this routine to do both similtaneously.
>
>What is the usual way to to this?
>
>Important points: The exec'ed command must run asynchronously (obvious if
>			the parent is supplying input.)
>
>		  The child process id must be available to the parent.
>			(so that it can be killed if necessary)
>
>
>Any ideas would be appreciated.
>
>
>---------------------------------------------------------------------
>email to 
>UUCP:       uunet!mimsy!{arinc,fe2o3}!vk2bea!michael
>						  _ _ _                    _
> 	Amateur	|    VK2BEA	(Australia)      ' ) ) )      /           //
> 	Radio	|    G4NYV	(United Kingdom)  / / / o _. /_  __.  _  //
>	Stations|    NV3Z	(United States)	 / ' (_<_(__/ /_(_/|_</_</_
>
>Michael Katzmann
>Broadcast Sports Technology.
>2135 Espey Ct. #4
>Crofton Md. 21114 USA
>
>Ph: +1 301 721 5151

Although, as a response on the net indicates, there can be problems
connecting both stdin and stdout from a child if you aren't
very careful about protocols there are cases where it is useful.
As you have discovered popen() won't do it, though. I have
waited to see if a detailed answer was provided by others.
Since I haven't seen one I will post part of a program I wrote
which does this. The key is that the child inherits stdin and
stdout from the parent, so the parent changes his own stdin
and stdout to pipes before spawning the child, using dup() to
change file desciptors.

The purpose of this program is to run all permutations of given
string through the program used by the standard spell script
looking for all the words which can be formed from the letters
in the input, as when solving word puzzles such as "Jumbles"
found in many newspapers. I have omitted the details and tried
to leave everything necessary to (1) see how to do the i/o
redirection you wanted to do and (2) see the whole structure
of the process tree in which this was used in a realistic
(or at least fun) application. The permutation generator
created the list of permutations in sorted order since this
was much faster than creating the whole list and then sorting,
even if space permitted. It also actually generated two 
separate streams of permutations since that was actually more
efficient than splitting one up and avoided possible deadlock
problems. I hope the editting jobs leaves enough for you to
see what is going on without getting lost in details.

Incidentally I tried to email the whole thing but got
"host not known". Can experienced netters suggest how I might
be able to use the routing show at the top of a post to
reply even when my local host doesn't know the final
destination?

/* anagram.c - extracted fragments to show redirection */
#include <string.h>
#include <stdio.h>
#ifndef SPELLPROG
#define SPELLPROG "/usr/bin/spellout"
#endif
#ifndef DICT
#define DICT "/usr/dict/hlista"
#endif

/* Omitting some irrelevant stuff here */

main(argc,argv,envp) int argc; char **argv, **envp;
{
int pipe1[1], pipe2[2];
char word[21];
int i;
#define TOCHILD pipe1[1]
#define FROMCHILD pipe2[0]
#define TOPARENT pipe2[1]
#define FROMPARENT pipe1[0]

/* Stuff omitted */
pipe(pipe1);
pipe(pipe2);
if (fork()==0)
  {
  if (fork()==0)
    {
    /* Child to invoke spell program in a pipeline */
    /* Close unused pipes */
    close (TOCHILD);
    close (FROMCHILD);
    /* Change stdin and stdout to pipe */
    close(0);
    dup(FROMPARENT);
    close(1);
    dup(TOPARENT);
    /* Invoke spell command */
    execl(SPELLPROG,"spellout",DICT,(char *)0);
    /* No return to here. For completeness make parent terminate */
    }
  else
    {
    /* Process to send distinct permutations to spelling checker */
    /* Close unused pipes */
    close(FROMCHILD);
    close(TOPARENT);
    close(FROMPARENT);
    /* Switch stdout to TOCHILD pipe */ 
    close(1);
    dup(TOCHILD);
    /* Send all distinct permutations to spell child */
    /* by writing them to stdout - details omitted   */
    }
  }
else
  {
  /* Root process invokes permute() to display accepted permutations */
  /* Close unused pipes */
  close(TOCHILD);
  close(TOPARENT);
  close(FROMPARENT);
  /* Change stdin to pipe from speller */
  close(0);
  dup(FROMCHILD);
  /* Generate permutations in sorted order; 
     Read misspellings from pipe;
     Print everything not on misspell list;
     - details omitted */
  } 
}



More information about the Comp.unix.questions mailing list