#!/bin/csh -f
#
#/*****************************************************************************
#                Copyright Carnegie Mellon University 1992
#
#                      All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of CMU not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
# CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
#*****************************************************************************/
#
#
#	verify -- Miro' Verifier
#
#	Program by:  Mark Maimone  (29-Nov-90)  CMU Computer Science
#			mwm@cs.cmu.edu
#
#
#  Usage:   verify <filename> [iff-file] [ambig-flags] [vf-flags] [switches]
#
#	where:
#		<filename>	is the root of the directory tree to be
#				probed
#		[iff-file]	is the (optional) name of the .iff file to
#				be compared against the filesystem (if none
#				is given stdin will be used)
#		[ambig-flags]	are optional flags for the ambiguity checker
#				(e.g., -s, -1, -=, -x)
#		[vf-flags]	are optional flags for the verifier (e.g.,
#				-q, -v)
#		[switches]	are switches for this program (-t)
#


set bn=`basename $0`

set DEFAULTAWKDIR="/usr/miro/bin"
set DEFAULTTEMP=/tmp
set DEFAULTPERMISSIONS=/usr/miro/libi/vf/permissions.unix
set DEFAULTAWKPROG=bawk
set DEFAULTAMBIGPROG=ambig
set DEFAULTPROBEPROG=probe
set DEFAULTRMNLPROG=rmnl
set DEFAULTIFFVFPROG=iff2vf
set DEFAULTVFPROG=vf
set DEFAULTVFLOG=vf.log

set ambigparams=""
set atomic="-a"
set probeparams=""
set vfparams=""
set permissions=$DEFAULTPERMISSIONS
set vflog=$DEFAULTVFLOG
set temp=$DEFAULTTEMP
set exit = 0
unset ifffile rmiff probedir rmausersort rmapermsort
unset rmprobeusers rmprobeout rmprobegroups rmrelsfile
unset ausersort apermsort probeusers probeout probegroups
unset skipprobe skipambig relsfile

#
#  Make sure we can access all the subprograms we'll need
#

if ( "${?awkprog}" == "0" ) set awkprog="$DEFAULTAWKPROG"
if ( "${?ambigprog}" == "0" ) set ambigprog="$DEFAULTAMBIGPROG"
if ( "${?probeprog}" == "0" ) set probeprog="$DEFAULTPROBEPROG"
if ( "${?rmnlprog}" == 0 ) set rmnlprog="$DEFAULTRMNLPROG"
if ( "${?vfprog}" == "0" ) set vfprog="$DEFAULTVFPROG"
if ( "${?iffvfprog}" == "0" ) set iffvfprog="$DEFAULTIFFVFPROG"

wh $awkprog >& /dev/null
if ($status) then
	if (! -r $DEFAULTAWKDIR/$awkprog) then
		echo $bn":  Can't find $awkprog on your path"
		echo "     or in $DEFAULTAWKDIR, quitting"
		exit 1
	endif
	set awkprog = $DEFAULTAWKDIR/$awkprog
endif
wh $ambigprog >& /dev/null
if ($status) then
	echo $bn":  Can't find $ambigprog on your PATH, quitting"
	exit 1
endif
wh $iffvfprog >& /dev/null
if ($status) then
	echo $bn":  Can't find $iffvfprog on your PATH, quitting"
	exit 1
endif
wh $probeprog >& /dev/null
if ($status) then
	echo $bn":  Can't find $probeprog on your PATH, quitting"
	exit 1
endif
wh $rmnlprog >& /dev/null
if ($status) then
	echo $bn":  Can't find $rmnlprog on your PATH, quitting"
	exit 1
endif
wh $vfprog >& /dev/null
if ($status) then
	echo $bn":  Can't find $vfprog on your PATH, quitting"
	exit 1
endif

#
# Parse the command line arguments
#

while ($#argv > 0)
	switch ("$1")
	case -[hH\?]*:
usage:
		echo "Usage:  $bn [switches] [directory] [iff-file]"
		echo ""
		echo "     Switches:  (may appear anywhere)"
		echo "        -h         Show this Help message"
		echo "        -np        Do not invoke probe, use old files"
		echo "        -na        Do not invoke ambig, use old files"
		echo "        -t [dir]   Temporary file directory [$DEFAULTTEMP]"
		echo "        -T         Keep temporary files around"
		echo "        -q         Quiet mode ($vfprog)"
		echo "        -v         Verbose mode ($vfprog)"
		echo "        -l [file]  Log file [$DEFAULTVFLOG] ($vfprog)"
		echo "        -oldambig  Use the old ambiguity checker."
		echo ""
		echo "   The next five files, if named, will be overwritten by default.  However,"
		echo "   if -np or -na is also present, the appropriate files will *not* be"
		echo "   overwritten, but instead will be used as the output from those programs."
		echo ""
		echo "        -au [file] Ambig Users file ($ambigprog)"
		echo "        -ap [file] Ambig Permissions file ($ambigprog)"
		echo "        -ar [file] Ambig Relations file ($ambigprog)"
		echo "        -pu [file] Prober Users file ($probeprog)"
		echo "        -pp [file] Prober Permissions file ($probeprog)"
		echo "        -pg [file] Prober Group file ($probeprog)"
		echo ""
		exit
	case -q:
	case -v:
		set vfparams="$vfparams $1"
		breaksw
	case -pu:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -pu, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto dopu
	case -pu*:
		set pfile=`echo $1|sed s/^-pu//`
dopu:
		set probeusers=$pfile
		breaksw
	case -pp:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -pp, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto dopp
	case -pp*:
		set pfile=`echo $1|sed s/^-pp//`
dopp:
		set probeout="$pfile"
		breaksw
	case -pg:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -pg, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto dopg
	case -pg*:
		set pfile=`echo $1|sed s/^-pg//`
dopg:
		set probegroups="$pfile"
		breaksw
	case -au:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -au, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto doau
	case -au*:
		set pfile=`echo $1|sed s/^-au//`
doau:
		set ausersort="$pfile"
		breaksw
	case -ap:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -ap, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto doap
	case -ap*:
		set pfile=`echo $1|sed s/^-ap//`
doap:
		set apermsort="$pfile"
		breaksw
	case -ar:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -ar, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto doar
	case -ar*:
		set pfile=`echo $1|sed s/^-ar//`
doar:
		set relsfile="$pfile"
		breaksw
	case -l:
		if ($#argv < 2) then
			echo $bn":  Filename expected after -l, ignored"
			breaksw
		endif
		set pfile="$2"; shift
		goto dolog
	case -l*:
		set pfile=`echo $1|sed s/^-l//`
dolog:
		set vflog="$pfile"
		breaksw
	case -t:
		if ($#argv < 2) then 
			echo $bn":  Directory expected after -t, ignored"
			breaksw
		endif
		set temp="$2"; shift
		goto dotemp
	case -t*:
		set temp=`echo $1|sed s/^-t//`
dotemp:
		if (! -d "$temp") then
			echo $bn": $temp is not a directory\!  Using $DEFAULTTEMP"
			set temp = $DEFAULTTEMP
		endif
		breaksw
	case -T:
		set savetemp
		breaksw
	case -np:
		set skipprobe
		breaksw
	case -na:
		set skipambig
		breaksw
	case -oldambig:
		set ambigprog="ambig.old"
		set atomic=""
		breaksw
	default:
		if (! $?probedir) then
			set probedir="$1"
		else if (! $?ifffile) then
			set ifffile="$1"
		else
			echo $bn":  unknown switch '$1' ignored"
		endif
	endsw
	shift
end

if ($?probedir == 0) then
	echo $bn":  You must specify a directory to be probed\!"
	goto usage
endif

onintr end

# Make sure we have the .iff information stored in a real file

if ($?ifffile == 0) then
	set ifffile = $temp/ver_iff_$$
	set rmiff
	cat > $ifffile
endif 
if (! -r "$ifffile") then
	echo $bn":  Couldn't access iff file '$ifffile', quitting."
	set exit = 1
	goto end
endif

#
#  Run ambig to generate the access matrix
#

if ( $?skipambig) then
	if ((! $?ausersort) || (! $?apermsort)) then
		echo "==> You must specify both -au and -ap when skipping ambig\!"
		echo "==> Quitting."
		set exit = 1
		goto end
	endif
	echo "==> Skipping ambig, will use results in '$ausersort'"
	echo "    and '$apermsort', which are expected to be sorted."
	goto skipambig

endif

echo "==> Generating access matrix from $ifffile"

if (! $?relsfile) then
	set relsfile = $temp/ver_rel_$$
	set rmrelsfile
endif
$ambigprog $atomic -p read -p write -p exec -M -l $ambigparams $ifffile | sort +2 +3 +1 > $relsfile
set s=$status
if ($s) then
	echo $bn":  $ambigprog failed with status $s, quitting."
	set exit = $s
	goto end
endif

#
#  Reformat the access matrix for the verifier
#

set ausers = $temp/ver_au_$$
set aperms = $temp/ver_ap_$$
$iffvfprog $ifffile $relsfile $ausers > $aperms
set s=$status
if ($s) then
	echo $bn":  $iffvfprog failed with status $s, quitting"
	set exit = $s
	goto end
endif
if (! -r $ausers) then
	echo $bn":  $iffvfprog failed to generate a user list, quitting"
	set exit = 1
	goto end
else if (! -r $aperms) then
	echo $bn":  $iffvfprog failed to generate the access matrix, quitting"
	set exit = 1
	goto end
endif

#
# Now we have to sort the user names and access lists
#

echo "==> Sorting the access matrix"

if (! $?ausersort) then
	set ausersort=$ausers.srt
	set rmausersort
endif
if (! $?apermsort) then
	set apermsort=$aperms.srt
	set rmapermsort
endif
sort <$ausers >$ausersort
$rmnlprog $aperms | sort -t: +0 -1 | $awkprog -e '/^*:/ { print $1; $1 = "" }  { print }' > $apermsort
set s=$status

if ($s) then
	echo $bn":  Sort failed with status $s, plodding on anyway...."
endif

skipambig:

#
#  Generate output from the prober
#

if ($?skipprobe) then
	if ((! $?probeout) || (! $?probeusers) || (! $?probegroups)) then
		echo "==> You must set -pp, -pu and -pg when skipping probe\!"
		echo "==> Quitting."
		set exit = 1
		goto end
	endif
	echo "==> Skipping probe, will use results in '$probeout',"
	echo "    '$probeusers', and '$probegroups'."
	goto skipprobe
endif

if (! $?probeout) then
	set probeout = $temp/ver_pr_$$
	set rmprobeout
endif
if (! $?probeusers) then
	set probeusers = $temp/ver_pru_$$
	set rmprobeusers
endif
if (! $?probegroups) then
	set probegroups = $temp/ver_prg_$$
	set rmprobegroups
endif

echo "==> Now probing with root directory $probedir"
$probeprog -uo $probeusers -go $probegroups $probedir $probeparams > $probeout

set s=$status
if ($s) then
	echo $bn":  $probeprog failed with status $s, quitting"
	set exit = $s
	goto end
endif

skipprobe:

#
#  Run the verifier
#

echo "==> Now comparing the Instance access matrix with the filesystem"

$vfprog -pu $probeusers -g $probegroups -au $ausersort -ap $apermsort -pp $probeout -p "$permissions" -l "$vflog" $vfparams
set s=$status
if ($s) then
	echo $bn":  $vfprog failed with exit status $s"
	set exit = $s
endif

end:
if ($?savetemp == 0) then
	if ($?rmrelsfile) then
		rm -f $relsfile
	endif
	if ($?ausers) then
		rm -f $ausers
	endif
	if ($?aperms) then
		rm -f $aperms
	endif
	if ($?rmprobeout) then
		rm -f $probeout
	endif
	if ($?rmausersort) then
		rm -f $ausersort
	endif
	if ($?rmapermsort) then
		rm -f $apermsort
	endif
	if ($?rmprobeusers) then
		rm -f $probeusers
	endif
	if ($?rmprobegroups) then
		rm -f $probegroups
	endif
	if ($?rmiff) then
		rm -f $ifffile
	endif
endif
exit $exit
