pratt@zztop.rutgers.edu (Lorien Y. Pratt) (11/03/88)
OK, an even easier question than I posted last time, I'd really appreciate your help. I have two processes that I want to communicate. I want the parent to be able to fprintf to the child's stdin and to fscanf from the child's stdout. I know that I need to fork and then in the child do an execlp, but I can't figure out how to set up the file descriptors so I can do what I want. The Sun IPC guide does not help me here. I know that I need to do a dup and a fork and a pipe, but I'm not sure in what order and with what parameters. Here's what I have so far, which I know is wrong. #include <netdb.h> #include <stdio.h> #define STRLEN 40 main() { int pid; FILE *fdopen(); FILE *sql; char from_sql[256]; char *fgets(); int i; pid = fork(); if (pid == 0) /* We are the children */ { /* This part works. I tested it in its own program without being a child. */ i = execlp("rsh", "rsh", "topaz", "/u2/ingres/bin/sql", "spam", 0); printf("execlp didn't work, return code is %d\n", i); } else { printf( "Child's process ID is %d\n", pid ); fflush(stdout); /* Open file descriptor to talk to child. I know it's wrong to pass a pid to fdopen, but how do I get the right fdes instead? */ sql = fdopen( pid, "a+" ); printf( "result of fdopen is %d\n", sql ); fflush(stdout); /* Start talking to child */ fgets(from_sql, 256, sql ); printf("SQL says: %s\n", from_sql ); fclose( sql ); } } Of course, this core dumps on the fgets call, because fdopen returns zero because I'm passing it a useless first argument. I thought that my best shot would help you to help me, though. AdTHANKSvance! --Lori -- ------------------------------------------------------------------- Lorien Y. Pratt Computer Science Department pratt@paul.rutgers.edu Rutgers University Busch Campus (201) 932-4634 Piscataway, NJ 08854
keith@execu.UUCP (Keith Pyle) (11/03/88)
In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu> pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: >OK, an even easier question than I posted last time, I'd really appreciate >your help. > >I have two processes that I want to communicate. I want the parent to >be able to fprintf to the child's stdin and to fscanf from the child's >stdout. I know that I need to fork and then in the child do an execlp, >but I can't figure out how to set up the file descriptors so I can do >what I want. The Sun IPC guide does not help me here. I know that I >need to do a dup and a fork and a pipe, but I'm not sure in what order >and with what parameters. > > [code deleted...] Here's a quickly hacked version of the code Lorien posted that illustrates setting up a pipe: #include <stdio.h> main() { int pid; FILE *fdopen(); FILE *sql; char from_sql[256]; char *fgets(); int i; int filedes[2]; pipe(filedes); pid = fork(); if (pid == 0) /* We are the children */ { close(1); i = dup(filedes[1]); i = execlp("rsh", "rsh", "mesquite", "cat /usr/keith/bin/chkmail", 0); printf("execlp didn't work, return code is %d\n", i); } else { printf( "Child's process ID is %d\n", pid ); fflush(stdout); sql = fdopen( filedes[0], "r" ); printf( "result of fdopen is %d\n", sql ); fflush(stdout); /* Start talking to child */ fgets(from_sql, 256, sql ); printf("SQL says: %s\n", from_sql ); fclose( sql ); } } The basic problem was that you need to call pipe(2) prior to fork(2) and then dup(2) the 'write' file descriptor to be the stdout of the child process. For the parent, you need to call fdopen(3s) with the file descriptor for reading created by pipe(2). Note also that the mode supplied to fdopen(3s) must match the with which the file descriptor was created. In the example code by Lorien, the mode was "a+". ----------------------------------------------------------------------------- Keith Pyle ...!{rutgers | tut.cis.ohio-state.edu}!cs.utexas.edu!execu!keith Disclaimer: What?? You actually believed me? -----------------------------------------------------------------------------
rar@nascom.UUCP (Alan Ramacher) (11/03/88)
In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu>, pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: > > I have two processes that I want to communicate. I want the parent to (text and code deleted) (code deleted) see: Advanced Unix Programmin by Marc Rochkind Chapter 6 Basic Interprocess Communications After reading this, you will have no difficulity writing the code you need.
avr@mtgzz.att.com (a.v.reed) (11/04/88)
In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu>, pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: > I have two processes that I want to communicate. I want the parent to > be able to fprintf to the child's stdin and to fscanf from the child's > stdout. I know that I need to fork and then in the child do an execlp, > but I can't figure out how to set up the file descriptors so I can do > what I want. The Sun IPC guide does not help me here. I know that I > need to do a dup and a fork and a pipe, but I'm not sure in what order > and with what parameters. The most legible, general, portable (at least to other Sun and AT&T derived systems), easy to maintain and modify, and only slightly less then optimally efficient solution is to start up your process from a shell script after creating a named pipe, and passing its name as an argument to the process: if /etc/mknod /usr/tmp/pipe$$ p then exec $LIB/yourprocess -p /usr/tmp/pipe$$ fi echo "yourprocess: can't make named pipe /usr/tmp/pipe$$; exiting" exit 5 # EIO In the executable $LIB/yourprocess, read the pipe name with getopt(), fopen it for "r+", then fork and exec, write in the parent and read in the child. When the child is finished fclose() the pipe fd, and, in the parent, fclose() and unlink the named pipe when an attempt to write sets errno to EPIPE. Adam Reed (avr@mtgzz.ATT.COM)
avr@mtgzz.att.com (a.v.reed) (11/04/88)
In article <4629@mtgzz.att.com>, I wrote: < In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu>, pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: < > I have two processes that I want to communicate. I want the parent to < > be able to fprintf to the child's stdin and to fscanf from the child's < > stdout. I know that I need to fork and then in the child do an execlp, < > but I can't figure out how to set up the file descriptors so I can do < > what I want. The Sun IPC guide does not help me here. I know that I < > need to do a dup and a fork and a pipe, but I'm not sure in what order < > and with what parameters. < < The most legible, general, portable (at least to other Sun and AT&T < derived systems), easy to maintain and modify, and only slightly less < then optimally efficient solution is to start up your process from a < shell script after creating a named pipe, and passing its name as an < argument to the process: < < if /etc/mknod /usr/tmp/pipe$$ p < then exec $LIB/yourprocess -p /usr/tmp/pipe$$ < fi < echo "yourprocess: can't make named pipe /usr/tmp/pipe$$; exiting" < exit 5 # EIO < < In the executable $LIB/yourprocess, read the pipe name with getopt(), < fopen it for "r+", then fork and exec, write in the parent and read in < the child. When the child is finished fclose() the pipe fd, and, < in the parent, fclose() and unlink the named pipe when an attempt to < write sets errno to EPIPE. < Adam Reed (avr@mtgzz.ATT.COM) To clarify: popen(), about which you can read in section 3S of the manual, or just with $ man popen, will do what Lorien Y. Pratt wants to do, perfectly well, as long as only ONE pipe, in ONE direction, is all that is needed. The solution I outlined above has the advantage of generality, in that it can be readily extended to bidirectional communication (one named pipe in each direction) and to an arbitrarily complex network of communicating processes with arbitrarily many pipes. Adam Reed (avr@mtgzz.ATT.COM)
syeh@caip.rutgers.edu (Simon Yeh) (11/04/88)
In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu>, pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: >OK, an even easier question than I posted last time, I'd really appreciate >your help. >Here's what I have so far, which I know is wrong. You may try this....[Note: lines starting with /*@*/ are what I added] #include <netdb.h> #include <stdio.h> #define STRLEN 40 main() { int pid; char from_sql[256]; char *fgets(); int i; /*@*/ int fd[2]; /* store file descriptors for pipe */ /*@*/ pipe(fd); /* creat pipe */ pid = fork(); if (pid == 0) /* We are the children */ { /*@*/ dup2(fd[1], 1); /* redirect child's stdout to fd[1] so child can talk to parent */ /*@*/ close(df[0]); close(fd[1]); /* This part works. I tested it in its own program without being a child. */ i = execlp("rsh", "rsh", "topaz", "/u2/ingres/bin/sql", "spam", 0); printf("execlp didn't work, return code is %d\n", i); /*@*/ exit(1); } else { printf( "Child's process ID is %d\n", pid ); fflush(stdout); /*@*/ close(fd[1]); /* Start talking to child */ /*@*/ fgets(from_sql, 256, fd[0] ); /* read what child says from fd[0] */ printf("SQL says: %s\n", from_sql ); /*@*/ fclose( fd[0] ); ...... } ..... } >Lorien Y. Pratt Computer Science Department >pratt@paul.rutgers.edu Rutgers University Hope this will help. --- Simon Yeh
m2@insyte.UUCP (Mike Arena) (11/10/88)
In article <Nov.2.14.51.36.1988.8260@zztop.rutgers.edu> pratt@zztop.rutgers.edu (Lorien Y. Pratt) writes: >OK, an even easier question than I posted last time, I'd really appreciate >your help. > >I have two processes that I want to communicate. I want the parent to >be able to fprintf to the child's stdin and to fscanf from the child's >stdout. ... stuff deleted ... >Here's what I have so far, which I know is wrong. ... code deleted ... > --Lori >-- >------------------------------------------------------------------- >Lorien Y. Pratt Computer Science Department >pratt@paul.rutgers.edu Rutgers University > Busch Campus >(201) 932-4634 Piscataway, NJ 08854 Here is a procedure to execute a command and creates three pipes to the child. The pid of the child is returned. The parent then can write to the child's standard input (fdin) and read from the childs standard output and error (fdout and fderr). If you need FILE pointers, then use the fdopen() function of the three file descriptors. Obviously, you should do more error checking than what I did below. Also, I used vfork() instead of fork() since an exec is done in the child immediately. Vfork() saves a lot of time and space. You will have to change the arguments for the function if you need to use execlp() or whatever instead of execvp(). int execute(name,args,fdin,fdout,fderr) char *name, *args[]; int *fdin, *fdout, *fderr; { int Pfdin[2], Pfdout[2], Pfderr[2], pid; pipe (Pfdin); pipe (Pfdout); pipe (Pfderr); switch (pid = vfork ()) { case -1: printf("vfork error"); case 0: close(0); /* Close child's stdin stream then ... */ dup(Pfdin[0]); /* make child's stdin be the first pipe */ close(1); /* Close child's stdout stream then ... */ dup(Pfdout[1]); /* make child's stdout be the second pipe */ close(2); /* Close child's stderr stream then ... */ dup(Pfderr[1]); /* make child's stderr be the third pipe */ execvp (name, args); } *fdin = Pfdin[1]; /* Parent will write to child's stdin */ *fdout = Pfdout[0]; /* Parent will read from child's stdout */ *fderr = Pfderr[0]; /* Parent will read from child's stderr */ return( pid ); } -- Michael J. Arena Innovative Systems Techniques (INSYTE) 1 Gateway Center, Newton, MA (617) 965-8450 UUCP: ...harvard!linus!axiom!insyte!m2