montnaro@sprite (Skip Montanaro) (02/06/88)
I want to execute a Bourne shell pipeline using system(3) and get a non-zero exist status from sh(1) if any of the elements of the pipe return non-zero statuses. As a concrete example, we have a remote nroff/troff execution evironment on our Suns called format that is accessible from our VMS VAXes. The user never sees the UNIX side of things, just gives a filename argument to format: format whiffle.nro What format does is rummage through the input file and transfer it and any other included files to the Sun, and send a command like: tbl whiffle.nro | neqn | nroff -mm > whiffle.prf When the command terminates, the output file is transferred back to the VAX for printing. My problem occurs when either the tbl or neqn segments of the pipe terminate with a non-zero exit status. The system(3) call never sees those errors, since sh(1) returns the exit status of the last command in the pipe. Can someone offer a suggestion regarding how I might get sh(1) to return the exit status of the first (or any) segment of the pipe that is non-zero, without losing the simplicity of a pipeline. (I can write a shell script to do what I want.) Thanks, Skip (montanaro@ge-crd.arpa, uunet!steinmetz!sprite!montanaro)
jdpeek@rodan.acs.syr.edu (Jerry Peek) (03/08/90)
I'm using these lines in a BSD-type Bourne shell script. They give me the last command line argument in $last and the others in $first: last="`expr \"$*\" : '.* \(.*\)'`" # LAST ARGUMENT first="`expr \"$*\" : '\(.*\) .*'`" # ALL BUT LAST ARG Seems like, years ago, I needed to put doublequotes around the backquotes to protect any spaces from the shell. So, I write quoting nightmares like that one. But maybe I've got over-quoting paranoia. :-) Would this be safe? last=`expr "$*" : '.* \(.*\)'` # LAST ARGUMENT first=`expr "$*" : '\(.*\) .*'` # ALL BUT LAST ARG Our BSD-type sh(1) man page seems to say that it's okay (?): After parameter and command substitution, any results of substitution are scanned for internal field separator char- acters (those found in $IFS) and split into distinct argu- ments where such characters are found... I'd like this script to be portable. Is there any Bourne shell (including mine!) that will choke on the less-quoted version? Thanks. --Jerry Peek; Syracuse University Academic Computing Services; Syracuse, NY jdpeek@rodan.acs.syr.edu, JDPEEK@SUNRISE.BITNET +1 315 443-3995
maart@cs.vu.nl (Maarten Litmaath) (03/09/90)
In article <2387@rodan.acs.syr.edu>, jdpeek@rodan.acs.syr.edu (Jerry Peek) writes: )... ) last="`expr \"$*\" : '.* \(.*\)'`" # LAST ARGUMENT ) first="`expr \"$*\" : '\(.*\) .*'`" # ALL BUT LAST ARG ) )Seems like, years ago, I needed to put doublequotes around the backquotes )to protect any spaces from the shell. [...] Indeed. Let's assume the IFS characters are space, tab and newline, and no argument contains such characters; then you could remove the outer double quotes. Example: $ set a b c $ last=`expr "$*" : '.* \(.*\)'` $ first=`expr "$*" : '\(.*\) .*'` $ echo "=$first=$last=" =a b=c= This should work too (more consistent, IMHO): $ last=`expr "$*" : '.* \\(.*\\)'` Right, let's try some funny arguments: $ set a ' ' b $ last=`expr "$*" : '.* \(.*\)'` $ first=`expr "$*" : '\(.*\) .*'` $ echo "=$first=$last=" =a =b= $ /bin/echo `expr "$*" : '\(.*\) .*'` | od -a 0000000 a nl 0000002 Huh?! In an assignment the results of command substitution are NOT scanned for IFS characters! (At least on SunOS 4.0.3c and 4.3BSD.) All the SunOS manual has to say about assignments: Keyword parameters (also known as variables) may be assigned values by writing: name=value [ name=value ] ... Pattern-matching is not performed on value. So: $ a=* $ echo "$a" * Anyway, here's an example showing the effect of an embedded space in the last argument: $ set a b c' 'd $ last=`expr "$*" : '.* \(.*\)'` $ first=`expr "$*" : '\(.*\) .*'` $ echo "=$first=$last=" =a b c=d= -- "Belfast: a sentimental journey to the Dark Ages - Crusades & Witchburning - Europe's Lebanon - Book Now!" | maart@cs.vu.nl, uunet!mcsun!botter!maart