grady@scam.Berkeley.EDU (Steven Grady) (03/27/90)
I have a perl program which starts another process and reads
the input, using open(). Specifially, the relevant part of the
code looks something like:
open(RLOG, "rlog $files |") || die "rlog: $@";
while (<RLOG>) {
...
}
The problem is that I don't find out if there's an error. What
would be really useful is for the "$?" variable (or something
like it) to be set to the status of the program when it exits.
Currently, $? is only set by backquoted programs, wait(), and
system(). Is there any possibility of adding generic open'ed
commands to this list, or at least some mechanism to provide
similar functionality?
--
Steven
grady@postgres.berkeley.edu
...!ucbvax!grady
"Shall we go down and give blood?"
"Oh, I don't want a great bat flapping round my neck."
merlyn@iwarp.intel.com (Randal Schwartz) (03/28/90)
In article <23449@pasteur.Berkeley.EDU>, grady@scam (Steven Grady) writes: | The problem is that I don't find out if there's an error. What | would be really useful is for the "$?" variable (or something | like it) to be set to the status of the program when it exits. | Currently, $? is only set by backquoted programs, wait(), and | system(). Is there any possibility of adding generic open'ed | commands to this list, or at least some mechanism to provide | similar functionality? Already done. 'close' does it. Quoting from the manpage: Closing a pipe explicitly also puts the status value of the command into $?. For example, open(TRUE,"true|") || die "Cannot open true... sad but true! ($!)"; print grep(s/^/true: /, <TRUE>); # show all the output (if any) close(TRUE) || die "Cannot close true... very weird ($!)"; print "true exited with $?\n"; open(FALSE,"false|") || die "Cannot open false... sad but false! ($!)"; print grep(s/^/false: /, <FALSE>); # show all the output (if any) close(FALSE) || die "Cannot close false... very weird ($!)"; print "false exited with $?\n"; generates: true exited with 0 false exited with 256 Hope this helps... $|=1;$_=<<'-- ';s#..#printf"%c",(fork?wait&&$?/256:exit hex($&))#eg; 4a75737420616e6f74686572205065726c206861636b65722c -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
tchrist@convex.COM (Tom Christiansen) (03/28/90)
In article <23449@pasteur.Berkeley.EDU> grady@postgres.berkeley.edu writes: >I have a perl program which starts another process and reads >the input, using open(). Specifially, the relevant part of the >code looks something like: > > open(RLOG, "rlog $files |") || die "rlog: $@"; > while (<RLOG>) { > ... > } > >The problem is that I don't find out if there's an error. I addressed this in <5016@convex.convex.com> of very nearly two months ago. It's brief, so I'll include the original here. --tom Date: 31 Jan 90 05:54:28 GMT From: tchrist@convex.com (Tom Christiansen) Subject: Testing successful pipe opens Organization: Convex Computer Corp, Richardson, TX Message-ID: <5016@convex.convex.com> Newsgroups: comp.lang.perl It's known that opening pipes to non-existent programs doesn't usually trigger useful error diagnostics. In particular, while writing on a badly-opened output pipe will (eventually) trigger a SIGPIPE (which you can look for), reading from a badly-opened input pipe just gets you EOF. A possible work-around for the bad input pipe follows: $kid = open (PIPE, "bogus_command |"); # really should check $kid != 0 (kill 0, $kid) || die "bogus_command failed"; This works fine if bogus_command doesn't have shell metas in it, but if it does, the shell may well not have exited before the kill 0. You can introduce a delay, $kid = open (PIPE, "bogus_command </dev/null |"); sleep 1; (kill 0, $kid) || die "bogus_command failed"; but this is sometimes undesirable and in any event does not guarantee correct behavior. But it seems slightly than nothing. --tom -- Tom Christiansen {uunet,uiucdcs,sun}!convex!tchrist Convex Computer Corporation tchrist@convex.COM "EMACS belongs in <sys/errno.h>: Editor too big!"
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/30/90)
In article <100906@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes: : It's known that opening pipes to non-existent programs doesn't : usually trigger useful error diagnostics. In particular, while : writing on a badly-opened output pipe will (eventually) trigger a : SIGPIPE (which you can look for), reading from a badly-opened input : pipe just gets you EOF. : : A possible work-around for the bad input pipe follows: : : $kid = open (PIPE, "bogus_command |"); # really should check $kid != 0 : (kill 0, $kid) || die "bogus_command failed"; : : : This works fine if bogus_command doesn't have shell metas in it, but : if it does, the shell may well not have exited before the kill 0. : : You can introduce a delay, : : $kid = open (PIPE, "bogus_command </dev/null |"); : sleep 1; : (kill 0, $kid) || die "bogus_command failed"; : : but this is sometimes undesirable and in any event does not guarantee : correct behavior. But it seems slightly than nothing. If you want to get a SIGPIPE on a bad input command, you can do it like this if you don't have shell metacharacters, or if the supposed metacharacters really aren't. $kid = open(PIPE, "-|"); die "Couldn't fork" unless defined $kid; if (!$kid) { # we don't have kid, so we are one exec "this", "is", "a", "bogus", "command"; kill 'PIPE', getppid; exit 1; } while (<PIPE>) { ... If you do want the shell to run, then you can probably do something like open(PIPE, "bogus command || kill -PIPE $$ |") Larry