[comp.sources.misc] pipe - multi-in multi-out pipelining BUG and fix.

tcjones@watdragon.waterloo.edu (Crocodile Dundee) (11/14/87)

Ooops. It turns out that under certain conditions "pipe" will do strange
things. This occurred when someone did the following

    cat fred | pipe -o ">list1" "|sort>list2"

The script was copying its input to its output with

    while read line
    do
        echo $line >> wherever
    done

and this got totally mixed up when the input line contained a "*"
which was passed on to echo and expanded into all the filenames in the
directory. I should have used cat in the first place and all this wouldn't have
gone on. Anyway, here it is again, fixed (and faster due to cat).

Terry

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by watdragon!tcjones on Tue Nov 10 18:38:38 EST 1987
# Contents:  pipe
 
echo x - pipe
sed 's/^@//' > "pipe" <<'@//E*O*F pipe//'
#!/bin/sh

#
# pipe  --  multi-input, multi-output pipelining
#
#           Terry Jones 19/10/87 (tcjones@watdragon)
#
#-------------------------------------------------------------------------------
#             Department Of Computer Science, University Of Waterloo
#             Waterloo Ontario Canada N2L 3G1
#
#{ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones
#tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
#tcjones%watdragon@waterloo.csnet [from oz, tcjones@dragon.waterloo.cdn@munnari]
#-------------------------------------------------------------------------------
#

myname=`basename $0`

if [ $# -eq 0 ]
then
    cat > /dev/tty
    exit 1
fi

def_shell=/bin/sh

if [ -z "$SHELL" ]
then
    echo No '$SHELL' variable set, using $def_shell
    SHELL=$def_shell
fi

cum_in=/tmp/pipe_$$

if [ -f $cum_in -a ! -w $cum_in ]
then
    echo ${myname}: could not use temporary ${cum_in} - try again.
    exit 1
fi

>$cum_in
tty=`tty`

IN=1
SOME_IN=0
SOME_OUT=0
ANY_OUT=0
while [ -n "$1" ]
do
    case $1 in
        -in|-i) 
            IN=1
            SOME_IN=0

            if [ "$SOME_OUT" = "0" ]
            then
                SOME_OUT=1
                cat $cum_in
            fi

            shift;;
        -out|-o)
            IN=0
            SOME_OUT=0
            ANY_OUT=1

            if [ "$SOME_IN" = "0" ]
            then
                SOME_IN=1
                cat >> $cum_in
            fi
            shift;;
        *) 
            if [ "$IN" = "1" ]
            then
                SOME_IN=1
                if [ "$1" = "-" ]
                then
                    cat >> $cum_in
                else
                    echo $1 | $SHELL >> $cum_in
                fi
            else
                SOME_OUT=1
                if [ "$1" = "-" ]
                then
                    cat $cum_in
                else
                    eval "cat $cum_in" "$1"
                fi
            fi

            shift;;
    esac
done

if [ "$SOME_OUT" = "0" -o "$ANY_OUT" = "0" ]
then
    cat $cum_in
fi

/bin/rm -f $cum_in
@//E*O*F pipe//
chmod u=rwx,g=,o= pipe
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
     103     207    2054 pipe
!!!
wc  pipe | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
 -b -b