corkum@csri.toronto.edu (Brent Thomas Corkum) (11/06/90)
What I want to do is start up and run another program in the background from within a C program. I want to continue to run the program that invokes the other program. To make things a little more clear what I'm doing is interacting with a user interface and at some point wish to run some analysis program. The analysis program is a standalone program that accepts command line arguments to run. But after I start the analysis I want to continue within the interface. Now, I can successfully do this using the system function with the following syntax: system("analysis test.dat &"); /* test.dat is the data file */ What I want to know is whether this is the best way of doing it and what other options are there. I looked at exec but this seems to kill the parent process. Also, I want to have the analysis program ring a bell when it's done. I looked at the man pages for setbell and ringbell but I can't seem to get the program to compile, I get the old Undefined function error. So how do I use these? Or is there another way to ring the keyboard bell from within a C program. Brent corkum@boulder.civ.toronto.edu
jmb@patton.wpd.sgi.com (Doctor Software) (11/07/90)
In article <1990Nov5.124751.14923@jarvis.csri.toronto.edu>, corkum@csri.toronto.edu (Brent Thomas Corkum) writes: > What I want to do is start up and run another program in the background from > within a C program. I want to continue to run the program that invokes the > other program ... Now, I can successfully do this using > the system function with the following syntax: > > system("analysis test.dat &"); /* test.dat is the data file */ > > What I want to know is whether this is the best way of doing it and what > other options are there. I looked at exec but this seems to kill the parent > process. > Exec in all it's forms does NOT kill the parent process - the only way to do that is to signal(2) the parent or for it to call exit(2). Your mistake is probably in not calling fork(2) before calling exec(2) - as it says in the man page, exec(2) "overlays the current process image with a new image taken from the named file". Thus, it probably seemed like your parent exited - but you never had one! Rather than go into the arcane incantation needed to do the fork/exec sequence, I prefer to use the popen()/pclose() library routines. popen() does what system() does, except it returns a FILE * (a standard IO file descriptor) which is attached to the process. Thus allows you to send data to the program, or to get data back. pclose() can be used to pick up the exit status of the process, and to kill it if you want. However, if you need to both write to the child and read from it, popen() won't do it. In that case, you need to do the classic fork/exec sequence: int readpipe[2]; int writepipe[2]; pipe(readpipe); pipe(writepipe); if (fork() == 0) { close(readpipe[1]); close(0); dup(readpipe[0]); close(writepipe[0]); close(1); dup(writepipe[1]); close(2); dup(writepipe[1]); execl("/bin/myprog", "myprog", arg1, arg2, 0); } close(readpipe[0]); close(writepipe[1]); Now in this sequence I left out all the error checking a good programmer would do, but this is the core of what needs to be done. Essentially, after this sequence, data written to readpipe[1] will appear as standard input to the child, and standard output and standard error in the child will appear on the writepipe[0] descriptor. Examination of the man pages for pipe(2) and dup(2) is left as an excersize for the reader. Of course, you probably want to save the process ID returned by fork() so you can manipulate the process at some later time (e.g., kill(2) it or wait(2) for it). If you get really creative, you can catch SIGCHLD (signal(2)) so you get an interrupt if the child terminates unexpectedly. Now you understand why I like to use popen()/pclose(). > > Also, I want to have the analysis program ring a bell when it's done. I > looked at the man pages for setbell and ringbell but I can't seem to get > the program to compile, I get the old Undefined function error. So how > do I use these? Or is there another way to ring the keyboard bell from > within a C program. > Basically, your parent program should ring the bell when the child terminates. It can find out when the child is done as I described above (i.e., wait(2) or SIGCHLD) and when that happens, ring the bell. > Brent > corkum@boulder.civ.toronto.edu -- Jim Barton Silicon Graphics Computer Systems jmb@sgi.com
sgf@cs.brown.edu (Sam Fulcomer) (11/09/90)
In article <1990Nov7.155855.16316@odin.corp.sgi.com> jmb@patton.wpd.sgi.com (Doctor Software) writes: >... >Now you understand why I like to use popen()/pclose(). >... Bear in mind that one of the things that makes popen more convenient is its use of /bin/sh to exec the command. It's not always the most secure method.
vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (11/10/90)
In article <55759@brunix.UUCP>, sgf@cs.brown.edu (Sam Fulcomer) writes: > In article <1990Nov7.155855.16316@odin.corp.sgi.com> jmb@patton.wpd.sgi.com (Doctor Software) writes: > >... > >Now you understand why I like to use popen()/pclose(). > >... > > Bear in mind that one of the things that makes popen more convenient is > its use of /bin/sh to exec the command. It's not always the most secure > method. Elaboration: Never use popen() in a set-uid program for any UNIX system, unless you understand the hole, and have done something about it. (If you just want to open a hole, create a suid copy of your favorite shell--it's easier to use.) vjs