More on how to do a pipe (was re: system() problem)

Brad Appleton brad at SSD.CSD.HARRIS.COM
Thu Mar 7 01:21:43 AEST 1991


In article <1991Mar6.025034.8697 at csusac.csus.edu> emmonsl at athena.ecs.csus.edu (L. Scott Emmons) writes:
>
>After some thinking about my pipe(), fork(), exec() implementation in my
>last post, I knew there was something funky about the way I did it...
>
>Here is another version of my pipe program, about as efficient as my
>previous version, but a bit cleaner (unless use of SIGCHLD is used for
>something other than just closing the pipe() down.)

I hate to be critical but I didnt care for the way the status codes from
dup2 and pipe were ignored. I have a piece of code from a while back that
was created specifically for the purpose of illustrating how to use fork and
how to redirect parent/child i/o. Its a bit longer than yours but is cleaner
(IMHO) and is easy to read. (BTW let me know ASAP of any errors - I thought
they were all worked out be now but who knows):

------------------------------------- cut here --------------------------------
/* I/O Redirection example */
#include <stdio.h>

#define  BUF_LEN  256
#define  NULLSTR  (char *)NULL

  /* read & write ends of a pipe */
#define  READ_END  0
#define  WRITE_END 1

  /*
  ** macro to replace the dup2 system call (if its not present) */
  **
  **  NOTE: dup() returns the LOWEST NUMBERED available file descriptor.
  **        it is assumed below, that no file descriptors numbered lower
  **        than <from> are available before the dup2 macro is invoked!!
  */
#ifdef DONT_HAVE_DUP2_SYSTEM_CALL
# define  dup2(to,from)  ( (close(from) || (to = dup()) < 0) ? -1 : 0 )
#endif

main( argc, argv )
  int  argc;
  char *argv[];
{
  int  nbytes,         /* number of bytes read */
       status,         /* return-code/status for various system calls */
       pipe_fd[2];     /* pipe file-descriptor array */ 
  char buf[ BUF_LEN ]; /* character buffer*/

  /* open a pipe */
  if ( pipe(pipe_fd) < 0 ) {
    perror( "unable to open unnamed pipe\n" );
    exit( 1 );
  }
  
  switch ( fork() ) {
    case -1: /* failure */
      perror( "Unable to fork off a process" );
      break;

    case  0: /* child */
      /* redirect stdout to the write end of the pipe */

      if ( dup2( pipe_fd[ WRITE_END ], fileno(stdout) ) < 0 ) {
        perror( "unable to redirect STDOUT to write end of pipe" );
        exit( 1 );
      }

      fprintf( stderr, "Child: Going to exec uptime (pid=%x).\n", getpid() );
      fflush( stderr );
      execl( "/usr/ucb/uptime", "uptime", NULLSTR );
      break;

    default: /* parent */
      do {  /* read output from child (until see '\n' ) */
        printf( "\n\nParent: reading from pipe\n\n" );
        fflush( stdout );

        if ( (nbytes=read( pipe_fd[ READ_END ], buf, BUF_LEN )) <0 ) {
          perror( "failed on pipe read" );
        }

        if ( write( fileno(stdout), buf, nbytes ) != nbytes ) {
          perror( "failed on STDOUT write" );
        }
      } while ( buf[ nbytes-1 ] != '\n' );

      printf( "Parent: Waiting for child (pid=%x).\n", getpid() );
      fflush( stdout );

      wait( &status );
      printf( "Parent: Child died (status=%x).\n", status );
      fflush( stdout );
      close( pipe_fd[ READ_END ] );
      break;
  }

  exit( 0 );
}


______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad at ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~



More information about the Comp.unix.programmer mailing list