One possibility requires named pipes, which are not available on all systems:
TEMP="/tmp/AB.$$"
trap "fuser -k $TEMP >/dev/null 2>/dev/null; rm -f $TEMP; exit 130" \
1 2 3 13 15
rm -f $TEMP
mknod $TEMP p
A "$@" <$TEMP &
B >$TEMP
RC=$?
rm -f $TEMP
trap 1 2 3 13 15
exit $RC
Another possibility uses a temporary file for passing the exit code:
TEMP="/tmp/AB.$$"
trap "rm -f $TEMP; exit 130" 1 2 3 13 15
echo 'A "$@"; echo $? >'$TEMP | sh -s "$@" | B
exit `cat $TEMP; rm -f $TEMP`
This second script has the significant problem that the command A cannot read
the standard input of the shell script.
What alternatives are there, preferably ones that don't require named pipes,
that still allow A to read the standard input of the shell script? If
nothing else, what can I do to simplify the first script? There ought to be
a simple way to filter the output of a command but still capture it's exit
value!
My NEWS processing is not entirely reliable. Therefore, please also send a
copy of any followup postings to me by e-mail.
--
==========================================================================
| Richard H. Gumpertz r...@CPS.COM (913) 642-1777 or (816) 891-3561 |
| Computer Problem Solving, 8905 Mohawk Lane, Leawood, Kansas 66206-1749 |
==========================================================================
Indeed.
)Also, the "$?" may be evaluated before invoking the
)subshell, not in it.
Only in a buggy implementation...
){ ... } sometimes spawns a subshell, so it won't help
)either.
Where did I hear this before? :-) :-(
[ugly workaround deleted]
Here's a hack that ought to work on every sh implementation since V7;
it doesn't use a temp file!
exec 3>&1 # Make file descriptor 3 a duplicate of stdout.
# Below: make fd 4 a dup of the new stdout, i.e. the output stream
# that's being captured.
# Then execute a subshell with fd 3 closed (it doesn't need 3),
# and stdout connected to the pipe.
# In this subshell execute `A' with fd 4 closed as well.
# Echo the exit status to the remembered captured stdout.
# Before executing `B', connect its stdin to the pipe, its stdout
# to the original stdout, and close fd 3 and 4.
RC=`
exec 4>&1
(A "$@" 4>&-; echo $? >&4) 3>&- | B >&3 3>&- 4>&-
`
exit $RC
Piece of cake. :-)
--
Antique fairy tale: Little Red Riding Hood. |Maarten Litmaath @ VU Amsterdam:
Modern fairy tale: Oswald shot Kennedy. |ma...@cs.vu.nl, uunet!cs.vu.nl!maart
This reminds me of a related problem with pipe lines, where one needs an
indication of "success" or "failure". "success" means that *each* stage
of a pipe line completed with zero exit status. The following idiom may
be useful for the original problem as well:
trap 'exit 1' 15
(A || kill $$) |
(B || kill $$) |
...
If you're not into large numbers of small numbers, how 'bout a one-liner:
perl -e 'open(X, "| B"); open(STDOUT, ">&X"); exec "A";'
Or you could write a little script to grab an arbitrary status out of
the middle of a command, to be invoked something like:
statusof "A | B | C |# D #| E | F | G"
and the script:
#!/usr/bin/perl
($pre,$cmd,$post) = split(/#/,shift);
open(I,$pre); open(STDIN, "<&I");
open(O,$post); open(STDOUT,">&O");
exec $cmd;
These seem fairly self-explanatory to me.
Larry Wall
lw...@jpl-devvax.jpl.nasa.gov