1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
# -*- mode: sh; -*-
#
# Public domain
#
# Written by Aleksey Cheusov <vle@gmx.net>
# based on the code from FAQ of comp.unix.shell newsgroup
#
# Set of shell functions for running pipe and checking
# exit status of ALL programs, not only last one.
#
# Version 0.6.0
#
#
__shquote (){
__cmd=`printf '%s\n' "$1" | sed "s|'|'\\\\\''|g"`
printf "%s\n" "'$__cmd'"
}
__pipestatus_err_msg (){
if test "$PIPESTATUS_VERBOSE"; then
echo "Pipe failed, pipestatus_all='$pipestatus_all'" 1>&2
fi
}
# run pipe and set pipestatus_1, pipestatus_2, ... and pipesize variables
# Example: runpipe_base prog1 arg11 arg12 '|' prog2 arg21 arg22 '|' prog3
# Always return zero exit status
runpipe_base (){
#
pipesize=0
# whole command
__pipestatus_com=
# token count
__pipestatus_k=1
# program in pipe (between |)
__pipestatus_l=
# counter
__pipestatus_j=1
# generating whole command
for __pipestatus_a in "$@"; do
if [ "_$__pipestatus_a" = '_|' ]; then
__pipestatus_com="$__pipestatus_com {
if $__pipestatus_l 3>&-"'; then
echo "pipestatus_'$__pipestatus_j'=0" 1>&3
else
echo "pipestatus_'$__pipestatus_j'=$?" 1>&3
fi
} 4>&- |
'
__pipestatus_j=`expr $__pipestatus_j + 1`
__pipestatus_l=
else
__pipestatus_l="$__pipestatus_l `__shquote \"$__pipestatus_a\"`"
fi
__pipestatus_k=`expr $__pipestatus_k + 1`
done
__pipestatus_com="if $__pipestatus_com $__pipestatus_l 3>&- 1>&4 4>&-"'; then
echo "pipestatus_'"$__pipestatus_j"'=0"
else
echo "pipestatus_'"$__pipestatus_j"'=$?"
fi'
#
# echo "$__pipestatus_com"
# '|| true' - trick for 'set -e'
exec 4>&1
eval `exec 3>&1; eval "$__pipestatus_com" || true`
exec 4>&-
#
pipesize=$__pipestatus_j
# pipestatus_all
__pipestatus_j=2
pipestatus_all=$pipestatus_1
while [ "$__pipestatus_j" -le "$pipesize" 2>/dev/null ]; do
eval "pipestatus_all=\"$pipestatus_all \$pipestatus_$__pipestatus_j\""
__pipestatus_j=`expr $__pipestatus_j + 1`
done
return 0
}
# returns zero exit status if ALL progs in pipe return zero
check_status0 (){
__pipestatus_j=1
while [ "$__pipestatus_j" -le "$pipesize" ]; do
eval "[ \$pipestatus_$__pipestatus_j -eq 0 ]" || {
__pipestatus_err_msg
return 1
}
__pipestatus_j=`expr $__pipestatus_j + 1`
done
return 0
}
# returns zero exit status if ALL progs in pipe return zero
runpipe0 (){
runpipe_base "$@"
check_status0
}
# match all statuses with the pattern
# example: check_status_re '0 . 0'
# . means "any status"
check_status_re (){
__pipestatus_re=`echo $1 | sed 's/[.]/[0-9][0-9]*/g'`
__pipestatus_j=1
__pipestatus_ps=
while [ "$__pipestatus_j" -le "$pipesize" ]; do
eval '__pipestatus_ps="$__pipestatus_ps ${pipestatus_'$__pipestatus_j'}"'
__pipestatus_j=`expr $__pipestatus_j + 1`
done
# trick for set -e
if echo "$__pipestatus_ps" | grep -E "^ $__pipestatus_re"'$' > /dev/null
then
__pipestatus_ret=0
else
__pipestatus_ret=$?
__pipestatus_err_msg
fi
# egrep not found?
case "$__pipestatus_ret" in
0|1)
;;
*)
exit 2; # fatal error with egrep
esac
return $__pipestatus_ret
}
# match all statuses with the pattern
# example: runpipe_re '0 . 0' prog1 '|' prog2 '|' prog3
# . means "any status"
runpipe_re (){
__pipestatus_re="$1"
shift
runpipe_base "$@"
check_status_re "$__pipestatus_re"
}
# return exit code of the last program in pipe
check_status (){
eval return '$pipestatus_'${pipesize}
}
# similar to plain pipe but set 'pipestatus_XX' and 'pipesize' variables
runpipe (){
runpipe_base "$@"
check_status
}
|