:
#	@(#) fs.sh 23.5 91/12/06 
#
#	Copyright (C) 1986-1991 The Santa Cruz Operation, Inc.
#		All Rights Reserved.
#	The information in this file is provided for the exclusive use of
#	the licensees of The Santa Cruz Operation, Inc.  Such users have the
#	right to use, modify, and incorporate this code into other products
#	for purposes authorized by the license agreement provided they include
#	this notice and the associated copyright notice with any such product.
#	The information in this file is provided "AS IS" without warranty.
#
#	mkdev/fs - File System Configuration
#
PATH=/etc:/bin:/usr/bin
LANG=english_us.ascii
export PATH LANG

fstab=/etc/default/filesys
checklist=/etc/checklist
tmp=/tmp/fs$$

# Define return values
: ${OK=0}  ${FAIL=1}  ${STOP=10}  ${HALT=11}

# FUNCTION DEFINITIONS
#########################

# Define traps for critical and non critical code.
set_trap()  {	
	trap 'echo "Interrupted! Exiting ..."; cleanup 1' 1 2 3 15
}
unset_trap()  {
	trap '' 1 2 3 15
}

# Remove temp files and exit with the status passed as argument
cleanup() {
	trap '' 1 2 3 15
	[ "$tmp" ] && rm -f $tmp*
	exit $1
}

# clear the screen if it is supported
clearscr() {
	# check if the terminal environment is set up
	[ "$TERM" ] && clear 2> /dev/null
}

getyn() {
	while	echo "\n$* (y/n) \c" >&2
	do	read yn rest
		case $yn in
		[yY])	return $OK 				;;
		[nN])	return $FAIL				;;
		*)	echo "\nPlease answer y or n" >&2	;;
		esac
	done
}

# Prompt with mesg, return non-zero on q. Also allows setting -x and +x,
# shell escapes and the passing of default values
prompt() {
	mesg=$1
	while	echo "\n${mesg}or enter q to quit: \c" >&2
	do	read cmd
		case $cmd in
		+x|-x)	set $cmd					;;
		-v)	# Print the values of requested variables
			read x
			for var in $x
			do
				eval echo \$$var
			done
			;;
		Q|q)	return $FAIL					;;
		!*)	eval `expr "$cmd" : "!\(.*\)"`			;;
		"")	# If there is a second argument use it
			# as the default, else loop until 'cmd' is set
			[ "$2" ] && { 
				cmd=$2
				return $OK
			}
			: continue
			;;
		*)	return $OK					;;
		esac
	done
}

get_dev() {
	while	echo "
Enter a device name and press <Return> or q to quit: \c"
	do	read dev
		case $dev in
			"")	continue	;;
			q|Q)	cleanup $OK	;;
			/dev/*)	break		;;
			/*)	dev=/dev$dev	;;
			*)	dev=/dev/$dev	;;
		esac
		echo "\nDevice name modified to $dev"
		getyn "Do you wish to continue? " && break
	done
	cdev=`echo $dev | sed 's^/dev/^/dev/r^'`
	fgrep "bdev=$dev " $fstab >/dev/null
	return $?
}

get_dir()  {
	while	echo "
Enter a directory name and press <Return> or q to quit: \c"
	do	read dir
		case $dir in
			"")	continue	;;
			q|Q)	cleanup $OK	;;
			/*)	break		;;
			*)	dir=/$dir	;;
		esac
		echo "\nDirectory name was modified to $dir."
		getyn "Do you wish to continue? " && break
	done
	[ -b $dev ] || {
		echo "\nWarning: $dev is not a block special device."
		getyn "Do you wish to continue? " || cleanup $FAIL
	}
	return
}

fsadd()  {
	get_dev && {
		echo "\nWarning: There is already an entry for $dev in $fstab.
This may cause conflict during autoboot and when entering multiuser mode."
		getyn "Do you wish to continue? " || cleanup $FAIL
	}
	get_dir

	# If mount point does not exist then create it and set correct 
	# ownership and permissions.  (If it exists, then leave the 
	# permissions as they are.)
	[ -d $dir ] || { 
		mkdir $dir
		chmod 775 $dir
		chown root $dir
		chgrp auth $dir
	}

	# mount $dir file structure, clean if necessary
	max=0
	until	/etc/mount $dev $dir > $tmp 2>&1
	do	case $? in
		2)	echo "\nCleaning $dev ... \c"
			fsck -y -t $tmp.fsck $dev >> $tmp 2>&1
			# If fsck can't clean fs in two rounds, give it up.
			max=`expr $max + 1`
			[ $max -gt 1 ] && {
				mv $tmp /tmp/fs.LOG
				echo "
Unable to mount $dev. See /tmp/fs.LOG for details. Exiting ... \n"
				cleanup $FAIL
			}
			;;
		*)	/etc/umount 2>> $tmp && continue
			echo "
Sorry, cannot access $dev. See /tmp/fs.LOG for details."
			mv $tmp /tmp/fs.LOG
			cleanup $FAIL
			;;
		esac
	done

	[ "`fstyp $dev 2>/dev/null`" = "HS" ] || {
		# If lost+found does not exist then create it and set correct 
		# ownership and permissions.  (If it exists, then leave the 
		# permissions as they are.)
		[ -d $dir/lost+found ] || { 
			mkdir $dir/lost+found
			chmod 700 $dir/lost+found
			chown bin $dir/lost+found
			chgrp bin $dir/lost+found
		}
		# Make 62 empty entries in lost+found
		# This allocates inodes for the directory, so that if the filesys is
		# corrupted and runs out of inodes, fsck is still able to recover files.
		echo "\nReserving slots in lost+found directory ...\c"
		for i in 1 2 3 4 5 6 7 8
		do	for j in 1 2 3 4 5 6 7 
			do	> $dir/lost+found/x$i$j
			done
		done
		for i in 1 2 3 4 5 6
		do  > $dir/lost+found/xz$i
		done
		rm -f $dir/lost+found/x??
		echo
	}

	# unmount $dir file structure
	/etc/umount $dev

	# Add the device to fsck checklist
	fgrep -x "$dev" $checklist > /dev/null || {
		unset_trap
		echo $dev >> $checklist
		set_trap
	}

	# Add pertinent information to fs file
	while echo "
When entering multiuser mode:
	1. Always mount $dev.
	2. Never mount $dev.
	3. Prompt before mounting $dev.

Select an option: \c" >&2
	do
	     read answer rest
	     case $answer in
		     1)  mountstring="rcmount=yes"		;;
		     2)  mountstring="rcmount=no"		;;
		     3)  mountstring="rcmount=prompt"	;;
		     *)  echo "\nEnter either 1, 2 or 3" >&2
		     continue				;;
	     esac
	     if getyn "Do you want to allow users to mount this file system? " 
	     then
		 u_mnt="yes" 
	     else
		 u_mnt="no" 
	     fi	
	     echo "\nUpdating system files ...\c"
	     unset_trap
	     echo "bdev=$dev cdev=$cdev mountdir=$dir $mountstring mount=$u_mnt fsckflags=-y" >> $fstab
	     set_trap
	     break
	done
	echo "\n\nFilesystem has been successfully added.\n"
	return
}

fsrm()  {
	while :
	do
		echo "\nThe following devices are currently listed in $fstab:\n"
		for var in `fgrep "bdev=" $fstab`
		do
			echo $var | fgrep "bdev=" > /dev/null && {
				eval $var
				echo $bdev
			}
		done
		get_dev && break
		echo "\n$dev is not listed in $fstab"
	done

	echo "\nUpdating system files ...\c"

	# Remove pertinent information from fs file,
	# correctly handling line continuation
	awk_dev=`echo $dev | sed 's%/%\\\/%g'`
	awk '
	/bdev='"$awk_dev"' /	{ while ($0 ~ /.*\\$/ && getline) ; next ; }
				{ print }' < $fstab > $tmp
	unset_trap
	cp $tmp $fstab
	set_trap

	# Remove the device from fsck checklist
	fgrep -xv "$dev" $checklist > $tmp
	unset_trap
	cp $tmp $checklist
	set_trap

	echo "\n\nFilesystem successfully removed from system files.\n"
	return
}

# main()
#########################

set_trap
cd /

clearscr
while :
do prompt "\n\nFilesystem Initialization Program \n
This program performs maintenance tasks required to add or delete
an existing filesystem. Would you like to:\n 
	1. Add a new filesystem to system.
	2. Remove a filesystem. 
	
Select an option " || break
  	case $cmd in
		1) fsadd  
		   break     ;;

		2) fsrm   
		   break     ;;

		*) echo "$cmd is not valid. Try again."
		   continue  ;;
	esac
done
	
cleanup $OK
