PIPES

Brian Bliss bliss at sp64.csrd.uiuc.edu
Fri Dec 7 09:30:01 AEST 1990


I've done this before, and ran into this problem.
well, you perfrom the fork, test whether you are child or
parent, and then get ready to dup the pipes:


	if(c) {
		/* parent */
		dup2(p2c[1], 1);
		dup2(c2p[0], 0);
	}
	else {
		/* child */
		dup2(c2p[1], 1);
		dup2(p2c[0], 0);
	}


consider the case of the parent:  what if c2p[0] is fd 1?
then the first dup2 call overwrites fd 1 before it can be
copied to 0.

it's really a pain if you need to dup fd 0 to 1, and fd 1 to 0,
but here's a fix I wrote that should do what you want:



/*****************************************************************************/
/* this file, "fork_cpp.c", is the source for a command which exec's a       */
/* child process, sets the child's stdin to be to_child and returns a FILE   */
/* pointer to its stdout (*from_child) and the child's process id (the       */
/* function's return val).                                                   */
/*****************************************************************************/



# include <stdio.h>
# include <signal.h>



#define	RDR	0
#define	WTR	1



int ae_fork_cpp (cmd, to_child, from_child)
/*****************************************************************************/
/* ae_popen2 exec's cmd, sets the child's stdin to *to_child, and creats a   */
/* a pipe from the child's stdout to *from_child.  ae_fork_cpp () returns    */
/* the process id of the child, or -1 for an error.   It is used by the      */
/* application executive to invoke the C preprocessor.                       */
/*****************************************************************************/
   char *cmd;
   FILE *to_child;
   FILE **from_child;
   {
      int c2p[2];
      register int child_stdin;
      register int child_stdout;
      register int parent_reader;
      register int pid;

      if (pipe (c2p) < 0) {
         return (-1);
      }
      child_stdout = c2p[WTR];
      parent_reader = c2p[RDR];
      child_stdin = fileno (to_child);

      /*************************************************/
      /* if child_stdout == 0, it will be overwritten  */
      /* when dup2'ing child_stdin to 0, so change it. */
      /* this should be done before the fork, in case  */
      /* of an error.                                  */
      /*************************************************/
      if (child_stdout == 0) {
         if ((child_stdout = dup (child_stdout)) == -1) {
            close (child_stdout);
            close (parent_reader);
            return (-1);
         }
         close (child_stdout);
      }

      /********************/
      /* perform the fork */
      /********************/
      if ((pid = fork ()) == -1) {
         close (child_stdout);
         close (parent_reader);
         return (-1);
      }
      if (pid == 0) {
         /**************************************************/
         /* we are the child process - close the parent's  */
         /* file descriptor, and copy our file descriptors */
         /* to 0 and 1, our stdin and stdout fd's.  then,  */
         /* exec the appropriate command.                  */
         /**************************************************/
            close (parent_reader);
            if (child_stdout != 0) {
               if (child_stdin != 0) {
                  dup2 (child_stdin, 0);
                  close (child_stdin);
               }
               if (child_stdout != 1) {
                  dup2 (child_stdout, 1);
                  close (child_stdout);
               }
            }
            else {
               int temp;
               temp = open ("/dev/null", "w");
               dup2 (child_stdout, temp);
               close (child_stdout);
               if (child_stdin != 0) {
                  dup2 (child_stdin, 0);
                  close (child_stdin);
               }
               dup2 (temp, 1);
               close (temp);
            }
            execl("/bin/sh", "sh", "-c", cmd, 0);
            /* it is an error to get past here */
            exit(1);
	}
      else {
         /**************************************************/
         /* we are the parent process - close the child's  */
         /* stdout file descriptor, set the from_child     */
         /* file pointer, and return the pid of the child. */
         /**************************************************/
         close (child_stdout);
         *from_child = fdopen (parent_reader, "r");
         return(pid);
      }
   }



More information about the Comp.unix mailing list