Blame maint/pipestatus

Packit 0848f5
# -*- mode: sh; -*-
Packit 0848f5
Packit 0848f5
#
Packit 0848f5
# Public domain
Packit 0848f5
#
Packit 0848f5
# Written by Aleksey Cheusov <vle@gmx.net>
Packit 0848f5
# based on the code from FAQ of comp.unix.shell newsgroup
Packit 0848f5
#
Packit 0848f5
# Set of shell functions for running pipe and checking
Packit 0848f5
# exit status of ALL programs, not only last one.
Packit 0848f5
#
Packit 0848f5
# Version 0.6.0
Packit 0848f5
#
Packit 0848f5
Packit 0848f5
# 
Packit 0848f5
__shquote (){
Packit 0848f5
    __cmd=`printf '%s\n' "$1" | sed "s|'|'\\\\\''|g"`
Packit 0848f5
    printf "%s\n" "'$__cmd'"
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
__pipestatus_err_msg (){
Packit 0848f5
    if test "$PIPESTATUS_VERBOSE"; then
Packit 0848f5
	echo "Pipe failed, pipestatus_all='$pipestatus_all'" 1>&2
Packit 0848f5
    fi
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# run pipe and set pipestatus_1, pipestatus_2, ... and pipesize variables
Packit 0848f5
# Example: runpipe_base prog1 arg11 arg12 '|' prog2 arg21 arg22 '|' prog3
Packit 0848f5
# Always return zero exit status
Packit 0848f5
runpipe_base (){
Packit 0848f5
    #
Packit 0848f5
    pipesize=0
Packit 0848f5
Packit 0848f5
    # whole command
Packit 0848f5
    __pipestatus_com=
Packit 0848f5
Packit 0848f5
    # token count
Packit 0848f5
    __pipestatus_k=1
Packit 0848f5
Packit 0848f5
    # program in pipe (between |)
Packit 0848f5
    __pipestatus_l=
Packit 0848f5
Packit 0848f5
    # counter
Packit 0848f5
    __pipestatus_j=1
Packit 0848f5
Packit 0848f5
    # generating whole command
Packit 0848f5
    for __pipestatus_a in "$@"; do
Packit 0848f5
        if [ "_$__pipestatus_a" = '_|' ]; then
Packit 0848f5
            __pipestatus_com="$__pipestatus_com {
Packit 0848f5
   if $__pipestatus_l 3>&-"'; then
Packit 0848f5
      echo "pipestatus_'$__pipestatus_j'=0" 1>&3
Packit 0848f5
   else
Packit 0848f5
      echo "pipestatus_'$__pipestatus_j'=$?" 1>&3
Packit 0848f5
   fi
Packit 0848f5
} 4>&- |
Packit 0848f5
'
Packit 0848f5
            __pipestatus_j=`expr $__pipestatus_j + 1`
Packit 0848f5
	    __pipestatus_l=
Packit 0848f5
        else
Packit 0848f5
            __pipestatus_l="$__pipestatus_l `__shquote \"$__pipestatus_a\"`"
Packit 0848f5
        fi
Packit 0848f5
        __pipestatus_k=`expr $__pipestatus_k + 1`
Packit 0848f5
    done
Packit 0848f5
    __pipestatus_com="if $__pipestatus_com $__pipestatus_l 3>&- 1>&4 4>&-"'; then
Packit 0848f5
      echo "pipestatus_'"$__pipestatus_j"'=0"
Packit 0848f5
   else
Packit 0848f5
      echo "pipestatus_'"$__pipestatus_j"'=$?"
Packit 0848f5
   fi'
Packit 0848f5
Packit 0848f5
    #
Packit 0848f5
#    echo "$__pipestatus_com"
Packit 0848f5
Packit 0848f5
    # '|| true' - trick for 'set -e'
Packit 0848f5
    exec 4>&1 
Packit 0848f5
    eval `exec 3>&1; eval "$__pipestatus_com" || true`
Packit 0848f5
    exec 4>&- 
Packit 0848f5
Packit 0848f5
    #
Packit 0848f5
    pipesize=$__pipestatus_j
Packit 0848f5
Packit 0848f5
    # pipestatus_all
Packit 0848f5
    __pipestatus_j=2
Packit 0848f5
    pipestatus_all=$pipestatus_1
Packit 0848f5
    while [ "$__pipestatus_j" -le "$pipesize" 2>/dev/null ]; do
Packit 0848f5
	eval "pipestatus_all=\"$pipestatus_all \$pipestatus_$__pipestatus_j\""
Packit 0848f5
        __pipestatus_j=`expr $__pipestatus_j + 1`
Packit 0848f5
    done
Packit 0848f5
Packit 0848f5
    return 0
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# returns zero exit status if ALL progs in pipe return zero
Packit 0848f5
check_status0 (){
Packit 0848f5
    __pipestatus_j=1
Packit 0848f5
    while [ "$__pipestatus_j" -le "$pipesize" ]; do
Packit 0848f5
	eval "[ \$pipestatus_$__pipestatus_j -eq 0 ]" || {
Packit 0848f5
	    __pipestatus_err_msg
Packit 0848f5
	    return 1
Packit 0848f5
	}
Packit 0848f5
	__pipestatus_j=`expr $__pipestatus_j + 1`
Packit 0848f5
    done
Packit 0848f5
Packit 0848f5
    return 0
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# returns zero exit status if ALL progs in pipe return zero
Packit 0848f5
runpipe0 (){
Packit 0848f5
    runpipe_base "$@"
Packit 0848f5
    check_status0
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# match all statuses with the pattern
Packit 0848f5
# example: check_status_re '0 . 0'
Packit 0848f5
# . means "any status"
Packit 0848f5
check_status_re (){
Packit 0848f5
    __pipestatus_re=`echo $1 | sed 's/[.]/[0-9][0-9]*/g'`
Packit 0848f5
    __pipestatus_j=1
Packit 0848f5
    __pipestatus_ps=
Packit 0848f5
    while [ "$__pipestatus_j" -le "$pipesize" ]; do
Packit 0848f5
	eval '__pipestatus_ps="$__pipestatus_ps ${pipestatus_'$__pipestatus_j'}"'
Packit 0848f5
	__pipestatus_j=`expr $__pipestatus_j + 1`
Packit 0848f5
    done
Packit 0848f5
Packit 0848f5
    # trick for set -e
Packit 0848f5
    if echo "$__pipestatus_ps" | grep -E "^ $__pipestatus_re"'$' > /dev/null
Packit 0848f5
    then
Packit 0848f5
	__pipestatus_ret=0
Packit 0848f5
    else
Packit 0848f5
	__pipestatus_ret=$?
Packit 0848f5
	__pipestatus_err_msg
Packit 0848f5
    fi
Packit 0848f5
Packit 0848f5
    # egrep not found?
Packit 0848f5
    case "$__pipestatus_ret" in
Packit 0848f5
	0|1)
Packit 0848f5
	    ;;
Packit 0848f5
	*)
Packit 0848f5
	    exit 2; # fatal error with egrep
Packit 0848f5
    esac
Packit 0848f5
Packit 0848f5
    return $__pipestatus_ret
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# match all statuses with the pattern
Packit 0848f5
# example: runpipe_re '0 . 0' prog1 '|' prog2 '|' prog3
Packit 0848f5
# . means "any status"
Packit 0848f5
runpipe_re (){
Packit 0848f5
    __pipestatus_re="$1"
Packit 0848f5
    shift
Packit 0848f5
Packit 0848f5
    runpipe_base "$@"
Packit 0848f5
    check_status_re "$__pipestatus_re"
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# return exit code of the last program in pipe
Packit 0848f5
check_status (){
Packit 0848f5
    eval return '$pipestatus_'${pipesize}
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
# similar to plain pipe but set 'pipestatus_XX' and 'pipesize' variables
Packit 0848f5
runpipe (){
Packit 0848f5
    runpipe_base "$@"
Packit 0848f5
    check_status
Packit 0848f5
}