#!/sbin/sh
#	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
#	  All Rights Reserved

#	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
#	The copyright notice above does not evidence any
#	actual or intended publication of such source code.

#ident	"@(#)mountall.sh	1.16	93/04/08 SMI"	SVr4.0 1.18.6.1

#
#	checkmessage raw_device fstype mountpoint
#
# Simple auxilary routine to the shell function checkfs. Prints out
# instructions for a manual file system check before entering the shell.
#
checkmessage() {
	echo ""
	echo "WARNING - Unable to repair the $3 filesystem. Run fsck"
	echo "manually (fsck -F $2 $1). Exit the shell when"
	echo "done to continue the boot process."
	echo ""
}

#
#	checkfs raw_device fstype mountpoint
#
# Check the file system specified. The return codes from fsck have the
# following meanings.
#	 0 - file system is unmounted and okay
#	32 - file system is unmounted and needs checking (fsck -m only)
#	33 - file system is already mounted
#	34 - cannot stat device
#	36 - uncorrectable errors detected - terminate normally (4.1 code 8)
#	37 - a signal was caught during processing (4.1 exit 12)
#	39 - uncorrectable errors detected - terminate rightaway (4.1 code 8)
#	40 - for root, same as 0 (used by bcheckrc to remount root)
# Note that should a shell be entered and the operator be instructed to
# manually check a file system, it is assumed the operator will do the right
# thing. The file system is not rechecked.
#
checkfs() {
	/usr/sbin/fsck -F $2 -m $1  >/dev/null 2>&1

	if [ $? -ne 0 ]
	then
		# Determine fsck options by file system type
		case $2 in
			ufs)	foptions="-o p"
				;;
			s5)	foptions="-y -t /var/tmp/tmp$$ -D"
				;;
			*)	foptions="-y"
				;;
		esac

		echo "The $3 file system ($1) is being checked."
		/usr/sbin/fsck -F $2 ${foptions} $1
	
		case $? in
			0|40)	# file system OK
				;;

			*)	# couldn't fix the file system - enter a shell
				checkmessage "$1" "$2" "$3"
				/sbin/sulogin < /dev/console
				echo "resuming mountall"
				;;
		esac
	fi
}

USAGE="Usage:\nmountall [-F FSType] [-l|-r] [file_system_table]"
TYPES="all"
while getopts ?rlF: c
do
	case $c in
	r)	RFLAG="r";;
	l)	LFLAG="l";;
	F)	FSType=$OPTARG;
		if [ "$TYPES" = "one" ]
		then
			echo "mountall: more than one FSType specified"
			exit 2
		else
			TYPES="one"
		fi;
		case $FSType in
		?????????*) 
			echo "mountall: FSType $FSType exceeds 8 characters"
			exit 2
		esac
		;;
	\?)	echo "$USAGE" 1>&2; exit 2;;
	esac
done
oi=0
for i in 0 1 2 3 4 5 6 7 8 9
do
	if [ $i = $OPTIND ]
	then
		OPTIND=$oi
		break
	fi
	oj=0
	for j in 0 1 2 3 4 5 6 7 8 9
	do
		if [ $i$j = $OPTIND ]
		then
			if [ $j = 0 ]
			then
				OPTIND=${oi}9
			else
				OPTIND=$i$oj
			fi
			break 2
		fi
		oj=$j
	done
	oi=$i
done
shift $OPTIND
if [ "$RFLAG" = "r" -a "$LFLAG" = "l" ]
then
	echo "mountall: options -r and -l incompatible" 1>&2
	echo "$USAGE" 1>&2
	exit 2
fi
if [ $# -gt 1 ]
then
	echo "mountall: multiple arguments not supported" 1>&2
	echo "$USAGE" 1>&2
	exit 2
fi

# get file system table name and make sure file exists
case $1 in
	"-")	FSTAB=""
		;;
	"")	FSTAB=/etc/vfstab
		;;
	*)	FSTAB=$1
		;;
esac
if [ "$FSTAB" != ""  -a  ! -s "$FSTAB" ]
then
	echo "mountall: file system table ($FSTAB) not found"
	exit 1
fi

if [ \( "$FSType" = "cachefs" -o "$FSType" = "nfs" \) -a "$LFLAG" = "l" ]
then
	echo "mountall: option -l and FSType are incompatible" 1>&2
	echo "$USAGE" 1>&2
	exit 2
fi
if [ \( "$FSType" = "s5" -o "$FSType" = "ufs" -o "$FSType" = "bfs" \) -a "$RFLAG" = "r" ]
then
	echo "mountall: option -r and FSType are incompatible" 1>&2
	echo "$USAGE" 1>&2
	exit 2
fi

#	file-system-table format:
#
#	column 1:	special- block special device or resource name
#	column 2: 	fsckdev- char special device for fsck 
#	column 3:	mountp- mount point
#	column 4:	fstype- File system type
#	column 5:	fsckpass- number if to be checked automatically
#	column 6:	automnt-	yes/no for automatic mount
#	column 7:	mntopts- -o specific mount options

#	White-space separates columns.
#	Lines beginning with \"#\" are comments.  Empty lines are ignored.
#	a '-' in any field is a no-op.

#
#	preen ufs filesystems first
#
ufslist=""
exec < $FSTAB
while  read special fsckdev mountp fstype fsckpass automnt mntopts 
do
	case $special in
	'#'* | '')	#  Ignore comments, empty lines
			continue ;;
	'-')		#  Ignore no-action lines
			continue
	esac 

	if  [ "$FSType" ]
	then			# ignore different fstypes
		if [ "$FSType" != "$fstype" ]
		then
			continue
		fi
	fi

	if [ "$LFLAG" ]
	then
		if [ "$fstype" = "cachefs" -o  "$fstype" = "nfs" ]
		then
			continue
		fi
	fi
	if [ "$RFLAG" ]
	then
		if [ "$fstype" != "nfs" ]
		then
			continue
		fi
		if [ "$fstype" = "swap" ]
		then
			continue
		fi
	fi
	if [ "$automnt" != "yes" ]
	then
		continue
	fi
	if [ "$fstype" != "ufs" ]
	then
		continue
	fi

	#	Only possible is an fsck-device is specified.
	if [ "$fsckdev" = "-" ]
	then
		continue
	fi

	ufslist="$ufslist $mountp"

done
if [ "$ufslist" ]; then
	echo "checking filesystems"
	/usr/sbin/fsck -o p $ufslist
	case $? in
	0)	# file system OK
		;;

	*)	# couldn't fix the filesystems - enter a shell
		echo ""
		echo "WARNING - Unable to repair some of the following filesystems:"
		echo "\t$ufslist"
		echo "Run fsck manually (fsck filesystem...)."
		echo "Exit the shell when done to continue the boot process."
		echo ""
		/sbin/sulogin < /dev/console
		echo "resuming mountall"
		;;
	esac
fi

#
#	fsck and mount filesystems
#
exec < $FSTAB
while  read special fsckdev mountp fstype fsckpass automnt mntopts 
do
	case $special in
	'#'* | '')	#  Ignore comments, empty lines
			continue ;;
	'-')		#  Ignore no-action lines
			continue
	esac 

	if  [ "$FSType" ]
	then			# ignore different fstypes
		if [ "$FSType" != "$fstype" ]
		then
			continue
		fi
	fi

	if [ "$LFLAG" ]
	then
		if [ "$fstype" = "cachefs" -o "$fstype" = "nfs" ]
		then
			continue
		fi
	fi
	if [ "$RFLAG" ]
	then
		if [ "$fstype" != "nfs" ]
		then
			continue
		fi
		if [ "$fstype" = "swap" ]
		then
			continue
		fi
	fi
	if [ "$automnt" != "yes" ]
	then
		continue
	fi
	if [ "$fstype" = "-" ]
	then
		echo "mountall: FSType of $special cannot be identified" 1>&2
		continue
	fi
	# 	Use mount options if any
	if  [ "$mntopts" != "-" ]
	then
		OPTIONS="-o $mntopts"
	else
		OPTIONS=""
	fi

	#	First check file system state and repair if necessary.
	#	Only possible is an fsck-device is specified.

	if [ "$fsckdev" = "-" ]
	then
		/sbin/mount "-F" $fstype $OPTIONS $special $mountp
		continue
	fi

	/usr/sbin/fsck "-m" "-F" $fstype $fsckdev >/dev/null 2>&1
	case $? in
	0)	/sbin/mount "-F" $fstype $OPTIONS $special $mountp
		#
		# check mount's return; if there was an error, mount will
		# have already printed an informative message.  If it
		# succeeded, we report that here
		#
		if [ $? -eq 0 ]
		then
			echo "$special mounted"
		fi
		;;

	32)	checkfs $fsckdev $fstype $mountp
		/sbin/mount "-F" $fstype $OPTIONS $special $mountp
		;;

	33)	# already mounted
		echo "$special already mounted"
		;;
	34)	# bogus special device
		echo "Cannot stat $fsckdev - ignoring"
		;;
	*)	# uncorrectable errors
		echo "$fsckdev uncorrectable error"
		;;
	esac

done
