Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!mit-eddie!genrad!panda!condor!charlie From: charlie@condor.UUCP (Charlie Havener) Newsgroups: comp.unix.questions,comp.unix.wizards Subject: Re: Running stdin/out through a pipe to a child process Message-ID: <7787@condor.UUCP> Date: Mon, 12-Jan-87 16:38:58 EST Article-I.D.: condor.7787 Posted: Mon Jan 12 16:38:58 1987 Date-Received: Tue, 13-Jan-87 00:55:24 EST References: <136@cogent.UUCP> Reply-To: charlie@condor.UUCP (Charlie Havener) Distribution: world Organization: GenRad, Inc., Bolton, Mass. Lines: 270 Xref: mnetor comp.unix.questions:620 comp.unix.wizards:574 In article <136@cogent.UUCP> mark@cogent.UUCP (Mark Steven Jeghers) writes: >I need to know how I might create a child process with 2 pipes connected to >it, one with which the parent process feeds a stream to the childs stdin, >and one from which the parent reads a stream from the childs stdout. I >understand how to use popen() to connect either stdin OR stdout between >processes, but I need to have BOTH. Here is the source code of a program that will do what you request: -------------------------------------------------------------------- /* Sample pipe master diagnostic control program - cdh April 29 1985 */ /* this program shows how to spawn other programs, pass them command line */ /* arguments, and attach to their standard input and output so all */ /* I/O goes thru the parent program. This program works on both */ /* the Berkeley 4.2BSD and on the 68000 Unisoft Sys V UNIX */ /* this is a framework to be modified as you wish. It has more comment */ /* messages than you will want to keep in a finished product */ /* This is all the result of one day's experimenting. */ #include#include char *pgms[] = /* here is an array of programs this one will try to invoke */ { "test2", "test1", 0, }; char *argsv[]= /* here are some sample command line arguments which */ { /* will be passed to the programs that are spawned */ "vi", "fi", "fo", "fum", 0, }; /* we will use two pipes for two way communication */ int fd1[2]; /* pipe channel from child to parent */ int fd2[2]; /* pipe channel from parent to child */ /*--------------------------------------------------------*/ main(argc,argv,envp) int argc; char **argv, **envp; { int i,k; char *pgmptr; /* pointer to a test program name */ int pid; int suicide_note; /* where the child exit status goes */ int death_note; /* where the child exit status goes */ int ch; char chr; char c; int status; int pid_listen; int pid_talker; int pid_program; int fda,fdb,fdc; for ( k=0 ; k < sizeof(pgms) ; k++ ) { pgmptr = pgms[k]; /* get the name of a program to run */ if ( pgmptr == 0 ) { printf("No more test programs to execute\n"); exit(0); } if ( (access(pgmptr,01) != 0) ) /* see if it is there before making pipes */ { printf("test program %s not found\n",pgmptr); continue; } printf("now trying to get pipes for %s\n",pgms[k]); if ( pipe(fd1) < 0 ) { perror("pipemaster"); printf("Couldn't get pipe file descriptors\n"); exit(); } if ( pipe(fd2) < 0 ) { perror("pipemaster"); printf("Couldn't get pipe file descriptors\n"); exit(); } printf("Got two pipes successfully\n"); printf("In pipemaster diagnostic control program, fork() is next\n"); /* don't use vfork() for this tricky stuff. No vfork on 68k anyway */ if ( ( pid_program = fork()) < 0 ) /* fork failed */ { printf("Couldn't fork"); exit(); } if ( pid_program == 0 ) /* the diagnostic program i.e. the child */ { close(0); close(1); close(2); /* close original stdin, stdout, stderr */ fda = dup(fd2[0]); /* dup into childs stdin */ if ( fda == -1 ) printf("dup returned error\n"); fdb = dup(fd1[1]); /* dup into childs stdout */ if ( fdb == -1 ) printf("dup returned error\n"); fdc = dup(fd1[1]); /* dup into childs stderr */ if ( fdc == -1 ) printf("dup returned error\n"); printf("fda=%d fdb=%d fdc=%d\n",fda,fdb,fdc); /* close all extra descriptors */ close(fd1[0]); close(fd1[1]); close(fd2[0]); close(fd2[1]); execve(pgmptr,argsv,envp); /* never returns if it works */ exit(0200); /* report to parent that the exec failed */ } else /* the parent, set up talker and listener processes */ { close(fd2[0]); close(fd1[1]); /* close unused pipe ends for safety */ printf("Will now set up talker and listener processes\n"); if ( ( pid_talker = fork()) < 0 ) /* fork failed */ { printf("Couldn't fork the 2nd time"); exit(); } if ( pid_talker != 0 ) /* the parent, listen to pipe and echo */ { while ( (status = read(fd1[0],&c,1) ) > 0 ) { putchar(c); } printf("sending kill signal to pid_talker process\n"); kill(pid_talker,SIGKILL); /* kill the child */ pid = wait(&death_note); /* so no zombies left around */ printf("pid %d, the wait status from death_note was %o\n",pid,death_note ); printf("wait for death_note completed, death_note = %d\n",death_note); } else /* the child talker, reads stdin and writes down the pipe */ { while ( (ch = getchar()) != EOF ) { chr = ch; /* the 68000 byte ordering requires */ /* addr of char not int!! */ if ( write(fd2[1],&chr,1) != 1 ) printf("Couldn't write to pipe\n"); } close(fd2[1]); printf("willingly leaving the talker subprocess\n"); exit(0); } } printf("in pipemaster main program, waiting for child to finish\n"); pid = wait(&suicide_note); /* wait for child to finish */ printf("pid %d, the wait status was %o\n",pid,suicide_note ); if ( (suicide_note >> 8) == 0200 ) printf("the exec failed\n"); close(fd2[1]); close(fd1[0]); /* clean up */ printf("clean up complete, end of for loop\n"); } printf("exiting pipemaster main program\n"); } ---------------------------------------------------------------------- here are some sample programs for it to invoke ---------------------------------------------------------------- #include /* test1 - a sample program too be invoked by the expert system */ /* Global Data , Defined here and used in other modules */ char *version = "V1.00"; /* string built at initialize time */ int debuglevel = 0; /* used to turn debug printouts on and off */ int expert = 0; /* set to 1 if program is to run in expert mode */ int parameter = 0; int subtest = 0; /*-------------------------------------------------------------------*/ main(argc,argv) int argc; char *argv[]; { int c; char buf[80]; char *u; int status; setbuf(stdout,NULL); printf("argc = %d, argv[0] = %s, argv[1] = %s\n",argc,argv[0],argv[1]); while ( --argc > 0 && (*++argv)[0] == '-') for ( u = argv[0] + 1 ; *u != '\0' ; u++ ) switch(*u) { case 'd': /* turns on debug */ debuglevel++; /* the more d's the higher the debug level */ break; case 'v': printf("\nVersion %s\n",version); exit(1); break; case 's': sscanf(*++argv,"%d",&subtest); if ( debuglevel ) printf("subtest = %d\n",subtest); break; case 'x': expert = 1; break; case 'p': sscanf(*++argv,"%d",¶meter); if ( debuglevel ) printf("parameter = %d\n",parameter); break; case 'f': /* replace description with your programs function */ printf("This test verifies that the ibus is functional by\n"); printf("reading and writing the page register on both T bus\n"); printf("driver boards if both are present\n"); exit(0); default: printf("\nIllegal option -%c\n", *u); case 'h': /* help */ printf("usage: -v -h -d -x -s # -p # -f\n"); printf(" -d The more d's the higher the debug e.g. -ddddd \n"); printf(" -v reports the version number of the program\n"); printf(" -x invokes program in 'expert' mode\n"); printf(" -h help, provides this flag option list\n"); printf(" -s # where # is a number means do sub-test #\n"); printf(" -p # is a parameter number for use by the program\n"); printf(" -f print a brief functional description of test\n"); exit(1); } printf("I am test1\n"); while ( argc-- ) { printf("arg%d = %s\n",argc,argv[argc]); } c = 'a'; printf("enter text: "); /* fflush(stdout); */ gets(buf); /* while ( (status = read(0,&c,1)) > 0 ) { printf("%c",c); fflush(stdout); } */ printf("\nI am leaving test1 now\n"); } -------------------------------------------------------------------------- #include main(argc,argv) int argc; char *argv[]; { setbuf(stdout,NULL); /* note that you should do this when using pipes */ printf("I am test2\n"); printf("argc = %d, argv[0] = %s, argv[1] = %s\n",argc,argv[0],argv[1]); while ( argc-- ) { printf("arg%d = %s\n",argc,argv[argc]); } printf("I am leaving test2 now\n"); }