[comp.unix.questions] Return values in pipelines

ilan343@violet.berkeley.edu (08/23/90)

 The /bin/sh (and the ksh) set the parameter ? to the return value of
 the last excuted command.  When I use a number of piped commands, say

prog1 | prog2 | prog3  ,

$? is set to the return value of the last command in the pipeline
(prog3) .  How can I detect if something went wrong on the previous
commands in the pipeline (prog2, prog3)?

Geraldo Veiga

maart@cs.vu.nl (Maarten Litmaath) (08/24/90)

In article <1990Aug22.211057.19850@agate.berkeley.edu>,
	ilan343@violet.berkeley.edu writes:
)
) The /bin/sh (and the ksh) set the parameter ? to the return value of
) the last excuted command.  When I use a number of piped commands, say
)
)prog1 | prog2 | prog3  ,
)
)$? is set to the return value of the last command in the pipeline
)(prog3) .  How can I detect if something went wrong on the previous
)commands in the pipeline (prog2, prog3)?

You can do something like this:
-------------------------------------------------------------------------------
#!/bin/sh

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 each but the last component of the pipeline in a subshell,
# with fd 3 closed (it doesn't need 3).
# In each subshell execute the command with fd 4 closed as well.
# Then echo the exit status to the remembered captured stdout.
# Before executing the last component of the pipeline, connect its stdout
# to the original stdout, and close fd 3.

error=`
	exec 4>&1
	(A 4>&-; echo A=$? >&4) 3>&- |
	(B 4>&-; echo B=$? >&4) 3>&- |
	(C 4>&-; echo C=$? >&4) 3>&- |
	(D 4>&-; echo D=$? >&4) >&3 3>&-
`

exec 3>&-

case $error in
*=[1-9]*)
	echo "Cut off mee legs an' call me shorty if it ain't wrong!  Lessee:"
	echo "$error"
	;;
*)
	echo "That's a big ten-four, little buddy!"
	;;
esac
--
        "[Your C code] seems about as portable as the Rock of Gibraltar."
                                 (Wayne Throop)

merlyn@iwarp.intel.com (Randal Schwartz) (08/24/90)

In article <7372@star.cs.vu.nl>, maart@cs (Maarten Litmaath) writes:
| In article <1990Aug22.211057.19850@agate.berkeley.edu>,
| )	      How can I detect if something went wrong on the previous
| )commands in the pipeline (prog2, prog3)?
| 
| You can do something like this:
[program using fd 3 and /bin/sh fd duping deleted]

Hmm.  Similar to what I was going to do, except that I would have used
temp files (remember... a temp file is just a pipe with an attitude
and a strong will to live).

#!/bin/sh
trap "rm /tmp/r$$.*; exit" 0 1 2 3 15

rm -f /tmp/r$$.?
(A || echo A exited with $? >/tmp/r$$.A) |
(B || echo B exited with $? >/tmp/r$$.B) |
(C || echo C exited with $? >/tmp/r$$.C) |
(D || echo D exited with $? >/tmp/r$$.D)

case /tmp/r$$.? in
	/tmp/r$$.\?)
		exit 0;;
	*)
		cat /tmp/r$$.?; exit 1;;
esac

With temp files, you won't get a race condition if both processes
decide to exit at *exactly* the same time (rare, but it'll happen!).

Just another /bin/sh hacker,
-- 
/=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!"=/

richard@aiai.ed.ac.uk (Richard Tobin) (08/24/90)

In article <7372@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>	echo "Cut off mee legs an' call me shorty if it ain't wrong!  Lessee:"

I see the Dutch have been trying to internationalise their error messages...

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

maart@cs.vu.nl (Maarten Litmaath) (08/24/90)

In article <1990Aug23.215612.12422@iwarp.intel.com>,
	merlyn@iwarp.intel.com (Randal Schwartz) writes:
)In article <7372@star.cs.vu.nl>, maart@cs (Maarten Litmaath) writes:
					^^
					Still broken software, Randal?

)| In article <1990Aug22.211057.19850@agate.berkeley.edu>,
)| )	      How can I detect if something went wrong on the previous
)| )commands in the pipeline (prog2, prog3)?
)| 
)| You can do something like this:
)[program using fd 3 and /bin/sh fd duping deleted]
)
)Hmm.  Similar to what I was going to do, except that I would have used
)temp files (remember... a temp file is just a pipe with an attitude
)and a strong will to live).

Yes, and that's why I _hate_ 'em!  You can always get screwed if someone
else decides to ``rm /tmp/*''...
Furthermore pipes have nice blocking & signaling semantics.

)...
)With temp files, you won't get a race condition if both processes
)decide to exit at *exactly* the same time (rare, but it'll happen!).

There is _no_ race condition with my solution, as each of the write()s
to the pipe is atomic, because the number of bytes is smaller than
4096 (<= PIPESIZE, or whatever it's called).

Only the _order_ in which the various messages arrive is undetermined.

BTW, I expected a Perl solution from you...  :-)
Larry?
--
        "[Your C code] seems about as portable as the Rock of Gibraltar."
                                 (Wayne Throop)