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