usenet@carssdf.UUCP (John Watson) (07/11/90)
I have a perl script that needs to send a few lines to a filter process and read a few lines back. (I have no sockets, forget that.) I would like to do something like pipe, fork, exec, dup2, etc... The way I do it in "c". But the key here is that I need to be able to use something like dup2 to make the pipe in and pipe out handles look like STDIN and STDOUT to the child process before I do the exec. I would like to retain the filter aspect, reads STDIN, writes STDOUT, of the child process. If that were not possible, I would still need a way to pass the file handle numbers (the fd ints, not the *FILE's). Any Ideas? John Watson ...!rutgers!carssdf!usenet
poage@sunny.ucdavis.edu (Tom Poage) (07/11/90)
Here's some clips of code I've experimented with to perform multiple (sorta ad-hoc) database queries from another program using a single invocation of SQL. The query language is written to the SQL process and the results are read back from the same process. I thought it'd be efficient to start SQL only once since it is a BIG program with lots of internal initialization. BTW, I used a named pipe instead of piping stdin directly to SQL because of the vendor's (Un*fy) stupid implementation; this SQL doesn't know if it's getting input from a pipe or a tty, hence writes prompts, etc., to stdout along with query results--this makes for ugly output. The only way around it is to dupe SQL into thinking it's getting query input from a file (Un*fy, do you read this group?). Unfortunately, this example needs select(), so is not portable to all UNIX domains. In the end, I just used temporary files instead of pipes. Lots deleted .... $NAMED_PIPE = "/var/tmp/PIPE.$$"; if (system("/usr/etc/mknod $NAMED_PIPE p")) { die "mknod(named-pipe): $!\n"; } ... # The pipe open fails (hangs) if the following construct is used. # This happens on a Sun 3/150 (4.0.3)--anyone else? #if (!open(SQLOUT, "SQL $NAMED_PIPE |")) { die "open(SQL): $!\n"; } open(SQLOUT, "-|") || exec 'SQL', $NAMED_PIPE; if (!open(SQLSCRIPT, ">$NAMED_PIPE")) { die "open(named-pipe): $!\n"; } ... vec($rin, fileno(SQLOUT), 1) = 1; vec($win, fileno(SQLSCRIPT), 1) = 1; loop: for (;;) { $n = select($rout=$rin, $wout=$win, undef, undef); die "select error: $!\n" if ($n < 0); if ($wout eq $win) { # write some stuff to the process. } if ($rout eq $rin) { last loop unless ($_ = <SQLOUT>); # Do something with what you've just read. } } close(SQLOUT); unlink($NAMED_PIPE); exit(0); -- Tom Poage, Clinical Engineering Universiy of California, Davis, Medical Center, Sacramento, CA poage@sunny.ucdavis.edu {...,ucbvax,uunet}!ucdavis!sunny!poage
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (07/17/90)
In article <250@carssdf.UUCP> usenet@carssdf.UUCP (John Watson) writes: : I have a perl script that needs to send a few lines to a filter : process and read a few lines back. (I have no sockets, forget that.) : I would like to do something like pipe, fork, exec, dup2, etc... : The way I do it in "c". But the key here is that I need to be able : to use something like dup2 to make the pipe in and pipe out handles : look like STDIN and STDOUT to the child process before I do the exec. : I would like to retain the filter aspect, reads STDIN, writes STDOUT, : of the child process. If that were not possible, I would still need : a way to pass the file handle numbers (the fd ints, not the *FILE's). Here's a simple-minded routine. It could be extended to use (or generate) arbitrary filehandles, but for this one you just write to W1 and read from R2. Don't try to write more than 4096 bytes, of course, or you'll deadlock... #!/usr/bin/perl sub filter { pipe(R1,W1); pipe(R2,W2); local($pid) = fork; if (!defined($pid)) { close R1; close R2; close W1; close W2; } elsif ($pid) { close R1; close W2; } else { close W1; close R2; open(STDIN,">&R1") || die "Can't dup to STDIN: $!\n"; open(STDOUT,">&W2") || die "Can't dup to STDOUT: $!\n"; close R1; close W2; print STDERR "execing @_\n"; exec @_; die "Can't exec @_: $!\n"; } $pid; } &filter('tr a-z A-Z'); while (<>) { print W1 $_; } close W1; while (<R2>) { print; } Larry Wall lwall@jpl-devvax.jpl.nasa.gov