#! /bin/sh
#
# AFS	Start and stop AFS components
# 
# 
# chkconfig: 345 60 20
# description:  AFS is a distributed file system which provides location
#		transparency, caching and secure authentication.
#		Additional configuration can be done in the /etc/sysconfig/afs
#		file. Read the documentation in that file for more information.
#
# Note that AFS does not use a pid file in /var/run. It is turned off by
# unmounting /afs.
# 
# Modified by Troy Dawson March 9, 2001
#  functions were put in to check to make sure we can reach the servers
# Modified by Troy Dawson May 14, 2001
#  a new algorithum for determining kernel modules was put in.
#  this also gave way so that we can use both 2.2 and 2.4 kernels
#  with the same startup script.
# Modified by Troy Dawson May 17, 2001
#  I added a check to make sure the afs directory is there
# Modified by Troy Dawson June 7, 2001
#  Added the touch to /var/lock/subsys/afs, as well as it's removal
#  Also make the 2.4 module a 2.4.2 kernel, since that is what shipped
#  with RedHat
# Modified by Troy Dawson August 28, 2001
#  Removed all of the stuff dealing with the 2.2 kernel
#
#*******************************
# Global Variables
#*******************************
AFSETCDIR=/usr/vice/etc
MODLOADDIR=$AFSETCDIR/modload
KSYMS_FILE=/proc/ksyms
SEARCH_STR="unregister_filesystem"
DEFAULT_SMP_PREFIX="smp_" # Redhat kernels need "smp" instead
PREFIX="" # none needed for UP with <= 1Gig memory

# Gather up options and post startup script name, if present
if [ -f /etc/sysconfig/afs ]; then
	. /etc/sysconfig/afs
fi

# Make sure the afs directory is there, various things have
#   been taking it off
if [ ! -d /afs ] ; then
	mkdir /afs
fi

# is_on returns 1 if value of arg is "on"
is_on() {
	if  test "$1" = "on" ; then return 0
	else return 1
	fi
}

# If choose_client can't correctly determine which client to use, set
# LIBAFS manually.
choose_client() {

	# Use the second field of the uname -v output instead of just
	# doing a match on the whole thing to protect against matching
	# a timezone named SMP -- I don't know of one, but let's be
	# paranoid.
	set X `uname -v`; shift
	case $2 in
	SMP) MP=.mp
	     PREFIX="-P smp" ;;	# MP system
	*)   MP= ;;	# SP system
	esac

	#*******************************************
	# Begin of modifications done by Troy Dawson
	#*******************************************

	# use uname -r to get the module version. 
	#  Use the module version to determin both the
	#  major and the minor kernel numbers
	VERSION=`uname -r`
	MAJOR=`echo $VERSION | cut -d. -f2`
	MINOR=`echo $VERSION | cut -d. -f3 | cut -d- -f1`
	LIBAFS=libafs-$VERSION$MP.o
	
	# See if we actually have that module or are just linking to it
	# If we are just linking to it remove the link, just in case it's
	# an old link.
	if [ -L $MODLOADDIR/$LIBAFS ] ; then
		rm -f $MODLOADDIR/$LIBAFS
	fi
	
	# We will need to do various things depending on if this is
	#  a 2.4 kernel or a 2.2 kernel.
	# NOTE: Many lines have just been commented out instead of removed
	#  to ease programming if later changes are needed.
#	if [ $MAJOR -ge 4 ] ; then
		#WE ARE A 2.4 KERNEL
		# We need to change two files dependant on the kernel
		rm -f $AFSETCDIR/afsd
		ln -s $AFSETCDIR/afsd.24 $AFSETCDIR/afsd
		rm -f /lib/security/pam_afs.so
		ln -s /lib/security/pam_afs.so.1.24  /lib/security/pam_afs.so
		rm -f /usr/afsws
		ln -s /afs/fnal.gov/afs36/i386_linux24 /usr/afsws
		# We now have to determine which module to link to.
		if [ $MINOR -ge 9 ] ; then
			# If we need to, link to the module
			if [ ! -f $MODLOADDIR/$LIBAFS ] ; then
				ln -s $MODLOADDIR/libafs-2.4.9-6$MP.o $MODLOADDIR/$LIBAFS
			fi
		elif [ $MINOR -ge 7 ] ; then
			# If we need to, link to the module
			if [ ! -f $MODLOADDIR/$LIBAFS ] ; then
				ln -s $MODLOADDIR/libafs-2.4.7-10$MP.o $MODLOADDIR/$LIBAFS
			fi
		elif [ $MINOR -ge 3 ] ; then
			# If we need to, link to the module
			if [ ! -f $MODLOADDIR/$LIBAFS ] ; then
				ln -s $MODLOADDIR/libafs-2.4.3-12$MP.o $MODLOADDIR/$LIBAFS
			fi
		else
			# If we need to, link to the module
			if [ ! -f $MODLOADDIR/$LIBAFS ] ; then
				ln -s $MODLOADDIR/libafs-2.4.2-2$MP.o $MODLOADDIR/$LIBAFS
			fi
		fi
#	else
#		#WE ARE A DIFFERNT KERNEL
#	fi
	#*******************************************
	# End of modifications done by Troy Dawson
	#*******************************************
	
}

#
# Find prefix symbol to use with insmod.  We find the unregister_filesystem
# string from /proc/ksyms since we know it's there.  If /proc/ksyms does not
# exist, we print that info to the console and use the uname -v output to
# decide on a prefix.
# unregister_filesystem_Rsmp_b240cad8 is a typcial SMP version string from
# a kernel built from ftp.kernel.org
#

set_prefix()
{
	h='[0-9a-fA-F]'
	h8="$h$h$h$h$h$h$h$h"
	prefix_set=0

	set X `fgrep $SEARCH_STR $KSYMS_FILE 2> /dev/null`; shift
	str=$2
	case $str in
	${SEARCH_STR}_R$h8)
		# No prefix required
		;;
	$SEARCH_STR)
		# No versioning in kernel symbols
		;;
	${SEARCH_STR}_R*$h8)
		suffix=${str#${SEARCH_STR}_R}
		PREFIX=${suffix%$h8}
		;;
	*)
		case $str in
		'')
			echo afsd: Cannot find \"$SEARCH_STR\" in file $KSYMS_FILE
			;;
		*)
			echo afsd: Malformed kernel version symbol \"$str\"
			;;
		esac

		echo Guessing prefix from output of uname -v
		set X `uname -v`; shift
		case $2 in
		SMP)
			PREFIX=$DEFAULT_SMP_PREFIX
			;;
		esac
		;;
	esac
}


# load_client loads the AFS client module if it's not already loaded. 
load_client() {
	# If LIBAFS is set, use it.
	if [ -z "$LIBAFS" ] ; then
		# Try to determine the right client.
		choose_client
	fi
    
	if [ ! -f $MODLOADDIR/$LIBAFS ] ; then
		echo AFS module $MODLOADDIR/$LIBAFS does not exist. Not starting AFS.
		exit 1
	fi

	# use the prefix command if required
	set_prefix
	/sbin/insmod ${PREFIX:+-P $PREFIX} -f -m $MODLOADDIR/$LIBAFS > $MODLOADDIR/libafs.map 2>&1
}

##################
# Find the servers from the server file and ping them
# Written by Troy Dawson March 9, 2001
##################
findServer() {
	FOUNDSERVER="no"
	FINISHED="no"
	CELL="$(cat /usr/vice/etc/ThisCell)"
	cat /usr/vice/etc/CellServDB | {
		while [ "$FINISHED" = "no" ] 
		do
			read line
			CHAR="$(echo $line | cut -c1)"
			if [ "$CHAR" = ">" ] ; then
				if [ "$FOUNDSERVER" = "yes" ] ; then
					FINISHED="yes"
				else
					LINECELL="$(echo $line | cut -d' ' -f1 | cut -d'>' -f2)"
					if [ "$CELL" = "$LINECELL" ] ; then
						FOUNDSERVER="yes"
					fi
				fi
			else
				if [ "$FOUNDSERVER" = "yes" ] ; then
					SERVER="$(echo $line | cut -d' ' -f1)"
					ping -c 1 $SERVER > /dev/null
					if [ $? -eq 0 ] ; then
						return 0
					fi

				fi
			fi
		done
		return 1
	}
	return
}

case "$1" in 
  start)
	## Start AFS client
	#First make sure we can reach the servers
	findServer
	if [ $? -eq 0 ] ; then
		# Load kernel extensions
		if  load_client  ; then :
		else
			echo Failed to load AFS client, not starting AFS services.
			exit 1
		fi
		
		# Start AFS client
		if  is_on $AFS_CLIENT && test -x /usr/vice/etc/afsd  ; then
			/usr/vice/etc/afsd ${OPTIONS}
	
# These were removed for security purposes
#			# Start AFS version of inetd.conf if present.
#			if  test -f /usr/afsws/etc/inetd.conf -a -x /usr/afsws/etc/inetd.afs ; then
#				/usr/afsws/etc/inetd.afs /usr/afsws/etc/inetd.conf
#			fi
			$AFS_POST_INIT
		fi

		# Link the update_afs_cellservdb.pl to run daily
		if [ -s $AFSETCDIR/update_afs_cellservdb.pl ] ; then
			ln -sf $AFSETCDIR/update_afs_cellservdb.pl /etc/cron.daily/update_afs_cellservdb.pl
		fi
		
		# Just do things right
		touch /var/lock/subsys/autofs
	else
		echo "  AFS Servers were not reachable"
		# unLink the update_afs_cellservdb.pl to run daily
		if [ -a /etc/cron.daily/update_afs_cellservdb.pl ] ; then
			rm -f /etc/cron.daily/update_afs_cellservdb.pl
		fi
		exit 1
	fi

	;;

  stop)
	#sync the hardware clock to AFS
	/sbin/hwclock --systohc
	
	# Stop AFS
	echo "Stopping AFS services..... "
	if  is_on $AFS_CLIENT  ; then
		killall inetd.afs
		umount /afs
	fi

	LIBAFS=`/sbin/lsmod | fgrep libafs`
	if [ -n "$LIBAFS" ] ; then
		LIBAFS=`echo $LIBAFS | awk 'BEGIN { FS = " " } { print $1 }'`
		/sbin/rmmod $LIBAFS
	fi
	
	# unLink the update_afs_cellservdb.pl to run daily
	if [ -a /etc/cron.daily/update_afs_cellservdb.pl ] ; then
		rm -f /etc/cron.daily/update_afs_cellservdb.pl
	fi
	
	rm -f /var/lock/subsys/afs
	;;

  *)
	echo Usage: 'afs <start|stop>'

esac

exit 0


