[Midnightbsd-cvs] src: rc.subr: Add kld loader functions and make several changes with

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Jan 17 19:36:38 EST 2009


Log Message:
-----------
Add kld loader functions and make several changes with mounting

Modified Files:
--------------
    src/etc:
        rc.subr (r1.10 -> r1.11)

-------------- next part --------------
Index: rc.subr
===================================================================
RCS file: /home/cvs/src/etc/rc.subr,v
retrieving revision 1.10
retrieving revision 1.11
diff -L etc/rc.subr -L etc/rc.subr -u -r1.10 -r1.11
--- etc/rc.subr
+++ etc/rc.subr
@@ -41,6 +41,7 @@
 #
 
 : ${rcvar_manpage:='rc.conf(5)'}
+: ${RC_PID:=$$}; export RC_PID
 
 #
 #	Operating System dependent/independent variables
@@ -55,7 +56,8 @@
 CMD_OSTYPE="${SYSCTL_N} kern.ostype"
 OSTYPE=`${CMD_OSTYPE}`
 ID="/usr/bin/id"
-JID=`ps -p $$ -o jid=`
+PS="/bin/ps -ww"
+JID=`$PS -p $$ -o jid=`
 IDCMD="if [ -x $ID ]; then $ID -un; fi"
 
 SYSCTL_W="${SYSCTL}"
@@ -144,6 +146,27 @@
 	echo $_revlist
 }
 
+# stop_boot always
+#	If booting directly to multiuser or $always is enabled,
+#	send SIGTERM to the parent (/etc/rc) to abort the boot.
+#	Otherwise just exit.
+#
+stop_boot()
+{
+	local always
+
+	if [ -n "$1" ] && checkyesno $1; then
+		always=true
+	else
+		always=false
+	fi
+	if [ "$autoboot" = yes -o "$always" = true ]; then
+		echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
+		kill -TERM ${RC_PID}
+	fi
+	exit 1
+}
+
 #
 # mount_critical_filesystems type
 #	Go through the list of critical filesystems as provided in
@@ -244,16 +267,30 @@
 
 	_pref=
 	if [ $_interpreter != "." ]; then	# an interpreted script
-		read _interp < $_procname	# read interpreter name
-		_interp=${_interp#\#!}		# strip #!
-		set -- $_interp
-		case $1 in
-		*/bin/env)
-			shift			#drop env to get real name
-			;;
-		esac
-		if [ $_interpreter != $1 ]; then
-			warn "\$command_interpreter $_interpreter != $1"
+		_script=${_chroot}${_chroot:+"/"}$_procname
+		if [ -r $_script ]; then
+			read _interp < $_script	# read interpreter name
+			case "$_interp" in
+			\#!*)
+				_interp=${_interp#\#!}	# strip #!
+				set -- $_interp
+				case $1 in
+				*/bin/env)
+					shift	# drop env to get real name
+					;;
+				esac
+				if [ $_interpreter != $1 ]; then
+					warn "\$command_interpreter $_interpreter != $1"
+				fi
+				;;
+			*)
+				warn "no shebang line in $_script"
+				set -- $_interpreter
+				;;
+			esac
+		else
+			warn "cannot read shebang line from $_script"
+			set -- $_interpreter
 		fi
 		_interp="$* $_procname"		# cleanup spaces, add _procname
 		_interpbn=${1##*/}
@@ -267,13 +304,10 @@
 		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
 	fi
 
-	_proccheck='
-		ps 2>/dev/null -o "pid,jid,command" '"$_psargs"' |
+	_proccheck="\
+		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
 		while read _npid _jid '"$_fp_args"'; do
-			case "$_npid" in
-			PID)
-				continue;;
-			esac; '"$_fp_match"'
+			'"$_fp_match"'
 				if [ "$JID" -eq "$_jid" ];
 				then echo -n "$_pref$_npid";
 				_pref=" ";
@@ -399,12 +433,25 @@
 #				returned a zero exit code.
 #
 #	required_dirs	n	If set, check for the existence of the given
-#				directories before running the default
-#				(re)start command.
+#				directories before running a (re)start command.
 #
 #	required_files	n	If set, check for the readability of the given
-#				files before running the default (re)start
-#				command.
+#				files before running a (re)start command.
+#
+#	required_modules n	If set, ensure the given kernel modules are
+#				loaded before running a (re)start command.
+#				The check and possible loads are actually
+#				done after start_precmd so that the modules
+#				aren't loaded in vain, should the precmd
+#				return a non-zero status to indicate a error.
+#				If a word in the list looks like "foo:bar",
+#				"foo" is the KLD file name and "bar" is the
+#				module name.  If a word looks like "foo~bar",
+#				"foo" is the KLD file name and "bar" is a
+#				egrep(1) pattern matching the module name.
+#				Otherwise the module name is assumed to be
+#				the same as the KLD file name, which is most
+#				common.  See load_kld().
 #
 #	required_vars	n	If set, perform checkyesno on each of the
 #				listed variables before running the default
@@ -553,49 +600,31 @@
 		if [ "$_elem" != "$rc_arg" ]; then
 			continue
 		fi
-
 					# if there's a custom ${XXX_cmd},
 					# run that instead of the default
 					#
-		eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \
-		    _postcmd=\$${rc_arg}_postcmd
+		eval _cmd=\$${rc_arg}_cmd \
+		     _precmd=\$${rc_arg}_precmd \
+		     _postcmd=\$${rc_arg}_postcmd
+
 		if [ -n "$_cmd" ]; then
-					# if the precmd failed and force
-					# isn't set, exit
-					#
-			if [ -n "$_precmd" ]; then
-				debug "run_rc_command: evaluating ${_precmd}()."
-				eval $_precmd $rc_extra_args
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
-
-			if [ -n "$_cmd" ]; then
-				debug "run_rc_command: evaluating ${_cmd}()."
-				eval $_cmd $rc_extra_args
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
-
-			if [ -n "$_postcmd" ]; then
-				debug "run_rc_command: evaluating ${_postcmd}()."
-				 eval $_postcmd $rc_extra_args
-				_return=$?
-			fi
+			_run_rc_precmd || return 1
+			_run_rc_doit "$_cmd $rc_extra_args" || return 1
+			_run_rc_postcmd
 			return $_return
 		fi
 
 		case "$rc_arg" in	# default operations...
 
 		status)
+			_run_rc_precmd || return 1
 			if [ -n "$rc_pid" ]; then
 				echo "${name} is running as pid $rc_pid."
 			else
 				echo "${name} is not running."
 				return 1
 			fi
+			_run_rc_postcmd
 			;;
 
 		start)
@@ -604,51 +633,14 @@
 				return 1
 			fi
 
-			if [ ! -x ${_chroot}${command} ]; then
-				info "run_rc_command: cannot run ($command)."
+			if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
+				warn "run_rc_command: cannot run $command"
 				return 1
 			fi
 
-					# check for required variables,
-					# directories, and files
-					#
-			for _f in $required_vars; do
-				if ! checkyesno $_f; then
-					warn "\$${_f} is not enabled."
-					if [ -z "$rc_force" ]; then
-						return 1
-					fi
-				fi
-			done
-			for _f in $required_dirs; do
-				if [ ! -d "${_f}/." ]; then
-					warn "${_f} is not a directory."
-					if [ -z "$rc_force" ]; then
-						return 1
-					fi
-				fi
-			done
-			for _f in $required_files; do
-				if [ ! -r "${_f}" ]; then
-					warn "${_f} is not readable."
-					if [ -z "$rc_force" ]; then
-						return 1
-					fi
-				fi
-			done
-
-					# if the precmd failed and force
-					# isn't set, exit
-					#
-			if [ -n "${_precmd}" ]; then
-				debug "run_rc_command: evaluating ${_precmd}()."
-				eval $_precmd
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
+			_run_rc_precmd || return 1
 
-					# setup the command to run, and run it
+					# setup the full command to run
 					#
 			echo "Starting ${name}."
 			if [ -n "$_chroot" ]; then
@@ -671,105 +663,52 @@
 				fi
 			fi
 
-					# if the cmd failed and force
-					# isn't set, exit
+					# run the full command
 					#
-			debug "run_rc_command: _doit: $_doit"
-			eval $_doit
-			_return=$?
-			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
+			_run_rc_doit "$_doit" || return 1
 
 					# finally, run postcmd
 					#
-			if [ -n "${_postcmd}" ]; then
-				debug "run_rc_command: evaluating ${_postcmd}()."
-				eval $_postcmd
-			fi
+			_run_rc_postcmd
 			;;
 
 		stop)
 			if [ -z "$rc_pid" ]; then
 				[ -n "$rc_fast" ] && return 0
-				if [ -n "$pidfile" ]; then
-					echo 1>&2 \
-				    "${name} not running? (check $pidfile)."
-				else
-					echo 1>&2 "${name} not running?"
-				fi
+				_run_rc_notrunning
 				return 1
 			fi
 
-					# if the precmd failed and force
-					# isn't set, exit
-					#
-			if [ -n "$_precmd" ]; then
-				eval $_precmd
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
+			_run_rc_precmd || return 1
 
 					# send the signal to stop
 					#
 			echo "Stopping ${name}."
-			_doit="kill -${sig_stop:-TERM} $rc_pid"
-			if [ -n "$_user" ]; then
-				_doit="su -m $_user -c 'sh -c \"$_doit\"'"
-			fi
-
-					# if the stop cmd failed and force
-					# isn't set, exit
-					#
-			eval $_doit
-			_return=$?
-			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
+			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
+			_run_rc_doit "$_doit" || return 1
 
 					# wait for the command to exit,
 					# and run postcmd.
 			wait_for_pids $rc_pid
-			if [ -n "$_postcmd" ]; then
-				eval $_postcmd
-				_return=$?
-			fi
+
+			_run_rc_postcmd
 			;;
 
 		reload)
 			if [ -z "$rc_pid" ]; then
-				if [ -n "$pidfile" ]; then
-					echo 1>&2 \
-				    "${name} not running? (check $pidfile)."
-				else
-					echo 1>&2 "${name} not running?"
-				fi
+				_run_rc_notrunning
 				return 1
 			fi
-			echo "Reloading ${name} config files."
-			if [ -n "$_precmd" ]; then
-				eval $_precmd
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
-			_doit="kill -${sig_reload:-HUP} $rc_pid"
-			if [ -n "$_user" ]; then
-				_doit="su -m $_user -c 'sh -c \"$_doit\"'"
-			fi
-			eval $_doit
-			_return=$?
-			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
-			if [ -n "$_postcmd" ]; then
-				eval $_postcmd
-				_return=$?
-			fi
+
+			_run_rc_precmd || return 1
+
+			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
+			_run_rc_doit "$_doit" || return 1
+
+			_run_rc_postcmd
 			;;
 
 		restart)
-			if [ -n "$_precmd" ]; then
-				eval $_precmd $rc_extra_args
-				_return=$?
-				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
-				    return 1
-			fi
 					# prevent restart being called more
 					# than once by any given script
 					#
@@ -778,29 +717,32 @@
 			fi
 			_rc_restart_done=true
 
-			# run stop in a subshell to keep variables for start
+			_run_rc_precmd || return 1
+
+			# run those in a subshell to keep global variables
 			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
-			run_rc_command ${_rc_prefix}start $rc_extra_args
+			( run_rc_command ${_rc_prefix}start $rc_extra_args )
+			_return=$?
+			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
 
-			if [ -n "$_postcmd" ]; then
-				eval $_postcmd $rc_extra_args
-				_return=$?
-			fi
+			_run_rc_postcmd
 			;;
 
 		poll)
+			_run_rc_precmd || return 1
 			if [ -n "$rc_pid" ]; then
 				wait_for_pids $rc_pid
 			fi
+			_run_rc_postcmd
 			;;
 
 		rcvar)
 			echo "# $name"
 			if [ -n "$rcvar" ]; then
 				if checkyesno ${rcvar}; then
-					echo "\$${rcvar}=YES"
+					echo "${rcvar}=YES"
 				else
-					echo "\$${rcvar}=NO"
+					echo "${rcvar}=NO"
 				fi
 			fi
 			;;
@@ -819,6 +761,83 @@
 }
 
 #
+# Helper functions for run_rc_command: common code.
+# They use such global variables besides the exported rc_* ones:
+#
+#	name	       R/W
+#	------------------
+#	_precmd		R
+#	_postcmd	R
+#	_return		W
+#
+_run_rc_precmd()
+{
+	check_required_before "$rc_arg" || return 1
+
+	if [ -n "$_precmd" ]; then
+		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
+		eval "$_precmd $rc_extra_args"
+		_return=$?
+
+		# If precmd failed and force isn't set, request exit.
+		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
+			return 1
+		fi
+	fi
+
+	check_required_after "$rc_arg" || return 1
+
+	return 0
+}
+
+_run_rc_postcmd()
+{
+	if [ -n "$_postcmd" ]; then
+		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
+		eval "$_postcmd $rc_extra_args"
+		_return=$?
+	fi
+	return 0
+}
+
+_run_rc_doit()
+{
+	debug "run_rc_command: doit: $*"
+	eval "$@"
+	_return=$?
+
+	# If command failed and force isn't set, request exit.
+	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
+		return 1
+	fi
+
+	return 0
+}
+
+_run_rc_notrunning()
+{
+	local _pidmsg
+
+	if [ -n "$pidfile" ]; then
+		_pidmsg=" (check $pidfile)."
+	else
+		_pidmsg=
+	fi
+	echo 1>&2 "${name} not running?${_pidmsg}"
+}
+
+_run_rc_killcmd()
+{
+	local _cmd
+
+	_cmd="kill -$1 $rc_pid"
+	if [ -n "$_user" ]; then
+		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
+	fi
+	echo "$_cmd"
+}
+
+#
 # run_rc_script file arg
 #	Start the script `file' with `arg', and correctly handle the
 #	return value from the script.  If `file' ends with `.sh', it's
@@ -1094,7 +1113,7 @@
 		return 1
 	fi
 	if [ ! -d "$linkdir" ]; then
-		warn "$_me: the directory $linkdir does not exist"
+		warn "$_me: the directory $linkdir does not exist."
 		return 1
 	fi
 	if ! ln -sf $src $link; then
@@ -1309,6 +1328,53 @@
 	/sbin/mdmfs $flags -s $1 md $2
 }
 
+# Code common to scripts that need to load a kernel module
+# if it isn't in the kernel yet. Syntax:
+#   load_kld [-e regex] [-m module] file
+# where -e or -m chooses the way to check if the module
+# is already loaded:
+#   regex is egrep'd in the output from `kldstat -v',
+#   module is passed to `kldstat -m'.
+# The default way is as though `-m file' were specified.
+load_kld()
+{
+	local _loaded _mod _opt _re
+
+	while getopts "e:m:" _opt; do
+		case "$_opt" in
+		e) _re="$OPTARG" ;;
+		m) _mod="$OPTARG" ;;
+		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
+		esac
+	done
+	shift $(($OPTIND - 1))
+	if [ $# -ne 1 ]; then
+		err 3 'USAGE: load_kld [-e regex] [-m module] file'
+	fi
+	_mod=${_mod:-$1}
+	_loaded=false
+	if [ -n "$_re" ]; then
+		if kldstat -v | egrep -q -e "$_re"; then
+			_loaded=true
+		fi
+	else
+		if kldstat -q -m "$_mod"; then
+			_loaded=true
+		fi
+	fi
+	if ! $_loaded; then
+		if ! kldload "$1"; then
+			warn "Unable to load kernel module $1"
+			return 1
+		else
+			info "$1 kernel module loaded."
+		fi
+	else
+		debug "load_kld: $1 kernel module already loaded."
+	fi
+	return 0
+}
+
 # ltr str src dst
 #	Change every $src in $str to $dst.
 #	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
@@ -1413,6 +1479,74 @@
 	done
 }
 
+# check_required_{before|after} command
+#	Check for things required by the command before and after its precmd,
+#	respectively.  The two separate functions are needed because some
+#	conditions should prevent precmd from being run while other things
+#	depend on precmd having already been run.
+#
+check_required_before()
+{
+	local _f
+
+	case "$1" in
+	start)
+		for _f in $required_vars; do
+			if ! checkyesno $_f; then
+				warn "\$${_f} is not enabled."
+				if [ -z "$rc_force" ]; then
+					return 1
+				fi
+			fi
+		done
+
+		for _f in $required_dirs; do
+			if [ ! -d "${_f}/." ]; then
+				warn "${_f} is not a directory."
+				if [ -z "$rc_force" ]; then
+					return 1
+				fi
+			fi
+		done
+
+		for _f in $required_files; do
+			if [ ! -r "${_f}" ]; then
+				warn "${_f} is not readable."
+				if [ -z "$rc_force" ]; then
+					return 1
+				fi
+			fi
+		done
+		;;
+	esac
+
+	return 0
+}
+
+check_required_after()
+{
+	local _f _args
+
+	case "$1" in
+	start)
+		for _f in $required_modules; do
+			case "${_f}" in
+				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
+				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
+				*)	_args="${_f}" ;;
+			esac
+			if ! load_kld ${_args}; then
+				if [ -z "$rc_force" ]; then
+					return 1
+				fi
+			fi
+		done
+		;;
+	esac
+
+	return 0
+}
+
 fi
 
 _rc_subr_loaded=:


More information about the Midnightbsd-cvs mailing list