1#!/bin/sh
2# find_sh4errors utility
3# Copyright (c) 2004 Steve Grubb. ALL RIGHTS RESERVED.
4# sgrubb@redhat.com
5#
6# This software may be freely redistributed under the terms of the GNU
7# public license.
8#
9# You should have received a copy of the GNU General Public License
10# along with this program; if not, write to the Free Software
11# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12
13# This script will search a directory and its subdirectories for every shell
14# script. It then runs sh -n to see if bash can determine if there are obvious
15# parsing errors. It does have a bug in that bash -n does not take into
16# account someone may program an unconditional exit and then include man page
17# generation information. It also fails to notice the exec command. When you
18# run across files that do either of the above, add it to the KNOWN_BAD list.
19
20if [ $# -ge 2 ] ; then
21	echo "Usage: find_sh4errors [directory]" 1>&2
22	exit 1
23fi
24INTERPRETERS="wish wishx tclsh guile rep itkwish expect /etc/kde/kdm/Xsession /etc/X11/xdm/Xsession /usr/bin/festival perl hfssh"
25SKIP_DIRS="/opt /home /root"
26KNOWN_BAD="/usr/bin/kde-build /usr/bin/cvsversion samples/copifuncs/copi.sendifm1 bashdb bash_completion_test"
27DIR="/"
28if [ $# -eq 1 ] ; then
29	if [ -d "$1" ] ; then
30		DIR="$1"
31	else
32		echo "Option passed in was not a directory" 1>&2
33		exit 1
34	fi
35fi
36tempfile=`mktemp /tmp/sh4.XXXXXX`
37tempfile2=`mktemp /tmp/sh4.XXXXXX`
38if [ -z "$tempfile" -o -z "$tempfile2" ] ; then
39        echo ; echo "Unable to create tempfiles...aborting." 1>&2 ; echo
40        exit 1
41fi
42trap "rm -f $tempfile; rm -f $tempfile2; exit 2" 1 2 3 5 15
43
44# Get executable files
45#echo "Locating executables..."
46/usr/bin/find $DIR -type f -perm /0111 -print >> $tempfile 2>/dev/null
47FOUND=0
48#echo "Refining list to shell scripts..."
49while read f
50do
51	# Get just the shell scripts
52	testf=`echo $f | /usr/bin/file -n -f - | egrep 'ourne|POSIX shell'`
53	if [ x"$testf" != x ] ; then
54		echo $f >> $tempfile2
55		FOUND=1
56	fi
57done < $tempfile
58/bin/rm -f $tempfile
59if [ $FOUND -eq 0 ] ; then
60	# Nothing to report, just exit
61#	echo "Examining shell scripts in $DIR"
62#	echo "No problems found"
63	/bin/rm -f $tempfile2
64	exit 0
65fi
66#echo "Examining shell scripts in $DIR"
67FOUND=0
68while read i
69do
70	# First see if the script calls an interpreter
71	SKIP=0
72	for lang in $INTERPRETERS
73	do
74		if `/bin/cat "$i" 2>/dev/null | \
75				grep "exec[ \t].*$lang" >/dev/null` ; then
76			SKIP=1
77			break
78		fi
79	done
80
81	if [ $SKIP -eq 1 ] ; then
82		continue
83	fi
84
85	# See if this is in a dir we want to ignore
86	for d in $SKIP_DIRS
87	do
88		if `echo "$i" | /bin/grep "^\$d" >/dev/null`; then
89			SKIP=1
90			break
91		fi
92	done
93
94	if [ $SKIP -eq 1 ] ; then
95		continue
96	fi
97
98	# Don't do the known naughty files
99	for bad in $KNOWN_BAD
100	do
101		if `echo "$i" | /bin/grep "$bad" >/dev/null`; then
102			SKIP=1
103			break
104		fi
105	done
106
107	if [ $SKIP -eq 1 ] ; then
108		continue
109	fi
110
111	# Now examine them for correctness
112	interp=`/usr/bin/head -n 1 "$i" | /bin/awk '{ print $1 }' | \
113							/usr/bin/tr -d '#!'`
114	if [ x"$interp" = "x" -o ! -x "$interp" ] ; then
115		interp="/bin/sh"
116	fi
117	$interp -n "$i" 2>/dev/null
118	if [ $? -ne 0 ] ; then
119		printf "%-44s" "$i"
120		rpm -qf --queryformat "%{NAME}-%{VERSION}" $i
121		echo
122		FOUND=1
123	fi
124done < $tempfile2
125/bin/rm -f $tempfile2
126if [ $FOUND -eq 0 ] ; then
127        # Nothing to report, just exit
128#        echo "No problems found"
129	exit 0
130fi
131exit 1
132
133