#!/bin/sh

# plt-checker - check for evidence of the ".plt - 1" bug
#
# Usage:
#	plt-checker
#		Check every installed debian package
#	plt-checker package-names/*.deb
#		Check *.deb files and/or installed packages.  Can be
#		intermixed on command line
#
# This thing is sorta interactive, and slow.  Final results are stored in
# plt-debchecker.out (so run it from a directory where you can write a file)

BASE=$(basename $0)
TMPDIR=${TMPDIR:-/tmp/${BASE}.$$}

if [ ! -z "$BASH_VERSION" ]
then
    function echo()
    {
	builtin echo -e "$@"
    }
    export -f echo
fi

if [ $(objdump -d /bin/ls 2>&- | wc -l) == 0 -o \
	$(nm -on --dynamic /lib/libc.so.6 2>&- | wc -l) == 0 ]
then
    echo "Either objdump or nm is busted -- can't run $0" >&2
    exit 3
fi

echo "$(date) $0 " '$Revision: 1.9 $' >>${BASE}.out

badstubcheck()
{
    objdump -d $1 2>&- |
	grep -l 'ldw  *-*[0-9a-f].*[13579bdf](.*r1),r21' >/dev/null
}

badlibcheck()
{
    nm --dynamic -n $1 2>&- | grep -Fl '$$'
}

badfile()
{
    case "$1" in
	"") return 5;;
	*bin*) true;;
	*lib*) true;;
	*) return 6;;
    esac
    case $(file $1) in
	*ELF*shared*PA-RISC*)
	    badstubcheck $1 && return 0
	    badlibcheck $1 && return 0
	    ;;
	*ELF*PA-RISC*dynamic*)
	    badstubcheck $1 && return 0
	    ;;
	*) return 3 ;;
    esac
    return 4
}

checkdotdeb()
{
    mkdir -p $TMPDIR
    pkg=$1
    echo -e "\nchecking $pkg\c" >&2
    dpkg-deb -x $n $TMPDIR
    find $TMPDIR -type f -print |
    {	# bash sucks
	skip=false
	while read file
	do
	    $skip && continue
	    echo -e ".\c" >&2

	    if badfile $file
	    then
		echo "bad" >&2
		echo "package\t$pkg\tfile\t$file" >> ${BASE}.out
		skip=true
	    fi
	done
    }
    rm -fr ${TMPDIR}
}

checkdeb()
{
    pkg=$1
    echo -e "\nchecking installed $pkg\c" >&2
    dpkg --listfiles $pkg | 
    {	# bash sucks
	skip=false
	while read file
	do
	    $skip && continue
	    echo -e ".\c" >&2

	    if badfile $file
	    then
		echo "bad" >&2
		echo "package\t$pkg\tfile\t$file" >> plt-checker.out
		skip=true
	    fi
	done
    }
}

if [ $# != 0 ]
then
    for n in $*
    do
	case $n in
	    *.deb) checkdotdeb $n;;
	    *) checkdeb $n
	esac
    done
else
    dpkg --get-selections |
	while read pkg status
	do
	    checkdeb $pkg $status
	done
fi

echo "\nSee ${BASE}.out for bad package list" >&2

