Port-sparc archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: 8.2 fails suddenly to boot - /etc/rc issues
Hello Robert,
sorry for the delay...
Before replacing rc.subr with the one from etc
> | no, I did not change rc.subr
>
> Good. Most people don't - it is one of the trickier parts of
> the system.
>
I try not to touch things without knowing... if not desperate :)
> | Perhaps some files corrupted in my filesystem?
>
> That's certainly a possibility - and could be caused by lots of
> thing, anything from a bug, to failing disk, RAM problems, or even
> power fluctuations.
given the diff, appears strange.
>
> | extract ./etc/rc.subr
> | and comare it to my local one. It looks full of differences!
>
> Differences as in some parts the same, but with changes, but still
> looking like sh code, or differences more like "these two things are
> nothing alike at all"?
To me it looks very different, but with the same file but in different time!
Especially the beninning is telling:
-# $NetBSD: rc.subr,v 1.18 2021/08/30 21:45:02 khorben Exp $
+# $NetBSD: rc.subr,v 1.100.4.1 2018/04/04 16:07:33 martin Exp $
#
-# Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
+# Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
# All rights reserved.
Do you recognize something?
Riccardo
--- /etc/rc.subr.bak 2023-03-09 21:21:56.000000000 +0100
+++ /etc/rc.subr 2020-03-31 07:08:40.000000000 +0200
@@ -1,6 +1,6 @@
-# $NetBSD: rc.subr,v 1.18 2021/08/30 21:45:02 khorben Exp $
+# $NetBSD: rc.subr,v 1.100.4.1 2018/04/04 16:07:33 martin Exp $
#
-# Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
+# Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
@@ -31,122 +31,19 @@
# functions used by various rc scripts
#
-# global variables
-# ----------------
-
-sysconfbase=/etc
-_RCCMD_chown="/usr/sbin/chown"
-_RCCMD_chroot="/usr/sbin/chroot"
-_RCCMD_ci="/usr/bin/ci"
-_RCCMD_co="/usr/bin/co"
-_RCCMD_cp="/bin/cp"
-_RCCMD_echo="echo" # use sh builtin
-_RCCMD_kill="/bin/kill"
-_RCCMD_logger="/usr/bin/logger"
-_RCCMD_mount="/sbin/mount"
-_RCCMD_mv="/bin/mv"
-_RCCMD_nice="/usr/bin/nice"
-_RCCMD_ps="/bin/ps"
-_RCCMD_rcs="/usr/bin/rcs"
-_RCCMD_rm="/bin/rm"
-_RCCMD_sh="/bin/sh"
-_RCCMD_su="/usr/bin/su"
-_RCCMD_systrace="/bin/systrace"
-_RCCMD_whoami="/usr/bin/whoami"
-
-_RCARG_psformat="-o pid,command"
-_RCARG_ps="-ax"
-_RCARG_su="-m"
-
-_osname=$(uname -s)
-_osrelease=$(uname -r)
-case $_osname in
- Darwin)
- _RCCMD_echo="/bin/echo"
- ;;
- SunOS)
- _RCCMD_chown="/bin/chown"
-# _RCCMD_ci="/usr/bin/ci" # not in Solaris 9
-# _RCCMD_co="/usr/bin/co" # not in Solaris 9
-# _RCCMD_systrace="/bin/systrace" # not in Solaris 9
- _RCARG_psformat="-o pid,comm"
- _RCARG_ps="-ef"
- _RCARG_su=""
- if [ "$_osrelease" = "5.11" ]; then
- bsd_echo () {
- if [ "$1" = "-n" ]; then
- shift; echo "$@\c"
- else
- echo "$@"
- fi
- }
- _RCCMD_echo="bsd_echo"
- else
- _RCCMD_echo="/usr/ucb/echo" # not in Solaris 11
- _RCCMD_whoami="/usr/ucb/whoami" # not in Solaris 11
- fi
- ;;
- Interix)
- bsd_echo () {
- if [ "$1" = "-n" ]; then
- shift; echo "$@\c"
- else
- echo "$@"
- fi
- }
- _RCCMD_chown="/usr/bin/chown"
- _RCCMD_ci="/usr/contrib/bin/ci"
- _RCCMD_co="/usr/contrib/bin/co"
- _RCCMD_echo="bsd_echo"
- _RCCMD_rcs="/usr/contrib/bin/rcs"
- _RCARG_psformat="-wwo pid,comm"
- ;;
- IRIX*)
- _RCCMD_chown="/sbin/chown"
- _RCCMD_ci="/usr/sbin/ci"
- _RCCMD_co="/usr/sbin/co"
- _RCCMD_cp="/sbin/cp"
- _RCCMD_kill="kill" # use sh builtin
-# _RCCMD_logger="/usr/bin/logger" # not in IRIX
- _RCCMD_mv="/sbin/mv"
- _RCCMD_nice="/sbin/nice"
- _RCCMD_ps="/sbin/ps"
- _RCCMD_rcs="/usr/sbin/rcs"
- _RCCMD_rm="/sbin/rm"
- _RCCMD_sh="/sbin/sh"
- _RCCMD_su="/sbin/su"
-# _RCCMD_systrace="/bin/systrace" # not in IRIX
- _RCCMD_whoami="/bin/whoami"
- _RCARG_psformat="-o pid,comm=12345678901234567890"
- # widen column to try to get full command-name
- _RCARG_ps="-ef"
- _RCARG_su=""
- ;;
- Linux)
- _RCCMD_chown="/bin/chown"
-# _RCCMD_ci="/usr/bin/ci" # not in Slackware 8.1
-# _RCCMD_co="/usr/bin/co" # not in Slackware 8.1
- if [ ! -f /etc/arch-release ] ; then # which not in Arch
- _RCCMD_nice=$(which nice)
- fi
-# _RCCMD_rcs="/usr/bin/rcs" # not in Slackware 8.1
-# _RCCMD_systrace="/bin/systrace" # not in Slackware 8.1
- _RCARG_ps="ax"
- if [ -e /etc/redhat-release ]; then
- _RCCMD_su="/bin/su" # for CentOS/RHEL
- fi
- ;;
- QNX)
- _RCCMD_chown="/bin/chown"
-# _RCCMD_ci="/usr/bin/ci" # not in QNX
-# _RCCMD_co="/usr/bin/co" # not in QNX
-# _RCCMD_systrace="/bin/systrace" # not in QNX
- _RCCMD_whoami="/usr/bin/id -un"
- _RCARG_psformat="-o pid,comm"
- _RCARG_ps="-ef"
- _RCARG_su=""
- ;;
-esac
+: ${rcvar_manpage:='rc.conf(5)'}
+: ${RC_PID:=$$} ; export RC_PID
+nl='
+' # a literal newline
+
+# RC variables to clear on start.
+_env_clear_rc_vars="
+RC_PID=
+_rc_pid=
+_rc_original_stdout_fd=
+_rc_original_stderr_fd=
+_rc_postprocessor_fd=
+"
#
# functions
@@ -154,10 +51,10 @@
#
# checkyesno var
-# Test $1 variable, and warn if not set to YES or NO.
-# Return 0 if it's "yes" (et al), nonzero otherwise.
+# Test $1 variable.
+# Return 0 if it's "yes" (et al), 1 if it's "no" (et al), 2 otherwise.
#
-checkyesno()
+checkyesnox()
{
eval _value=\$${1}
case $_value in
@@ -172,12 +69,45 @@
return 1
;;
*)
- warn "\$${1} is not set properly - see rc.conf(5)."
- return 1
+ return 2
;;
esac
}
+#
+# checkyesno var
+# Test $1 variable, and warn if not set to YES or NO.
+# Return 0 if it's "yes" (et al), nonzero otherwise.
+#
+checkyesno()
+{
+ local var
+
+ checkyesnox $1
+ var=$?
+ [ $var = 0 -o $var = 1 ] && return $var
+ warn "\$${1} is not set properly - see ${rcvar_manpage}."
+ return 1
+}
+
+#
+# yesno_to_truefalse var
+# Convert the value of a variable from any of the values
+# understood by checkyesno() to "true" or "false".
+#
+yesno_to_truefalse()
+{
+ local var=$1
+ if checkyesno $var; then
+ eval $var=true
+ return 0
+ else
+ eval $var=false
+ return 1
+ fi
+}
+
+#
# reverse_list list
# print the list in reverse order
#
@@ -187,33 +117,84 @@
for _revfile; do
_revlist="$_revfile $_revlist"
done
- ${_RCCMD_echo} $_revlist
+ echo $_revlist
+}
+
+#
+# If booting directly to multiuser, send SIGTERM to
+# the parent (/etc/rc) to abort the boot.
+# Otherwise just exit.
+#
+stop_boot()
+{
+ if [ "$autoboot" = yes ]; 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
+# Go through the list of critical file systems as provided in
# the rc.conf(5) variable $critical_filesystems_${type}, checking
# each one to see if it is mounted, and if it is not, mounting it.
+# It's not an error if file systems prefixed with "OPTIONAL:"
+# are not mentioned in /etc/fstab.
#
mount_critical_filesystems()
{
eval _fslist=\$critical_filesystems_${1}
+ _mountcrit_es=0
for _fs in $_fslist; do
- ${_RCCMD_mount} | (
- _ismounted=false
- while read what _on on _type type; do
- if [ $on = $_fs ]; then
- _ismounted=true
+ _optional=false
+ case "$_fs" in
+ OPTIONAL:*)
+ _optional=true
+ _fs="${_fs#*:}"
+ ;;
+ esac
+ _ismounted=false
+ # look for a line like "${fs} on * type *"
+ # or "* on ${fs} type *" in the output from mount.
+ case "${nl}$( mount )${nl}" in
+ *" on ${_fs} type "*)
+ _ismounted=true
+ ;;
+ *"${nl}${_fs} on "*)
+ _ismounted=true
+ ;;
+ esac
+ if $_ismounted; then
+ print_rc_metadata \
+ "note:File system ${_fs} was already mounted"
+ else
+ _mount_output=$( mount $_fs 2>&1 )
+ _mount_es=$?
+ case "$_mount_output" in
+ *"${nl}"*)
+ # multiple lines can't be good,
+ # not even if $_optional is true
+ ;;
+ *[uU]'nknown special file or file system'*)
+ if $_optional; then
+ # ignore this error
+ print_rc_metadata \
+ "note:Optional file system ${_fs} is not present"
+ _mount_es=0
+ _mount_output=""
fi
- done
- if $_ismounted; then
- :
- else
- ${_RCCMD_mount} $_fs >/dev/null 2>&1
+ ;;
+ esac
+ if [ -n "$_mount_output" ]; then
+ printf >&2 "%s\n" "$_mount_output"
+ fi
+ if [ "$_mount_es" != 0 ]; then
+ _mountcrit_es="$_mount_es"
fi
- )
+ fi
done
+ return $_mountcrit_es
}
#
@@ -254,7 +235,7 @@
if [ -z "$_procname" ]; then
err 3 'USAGE: check_process procname [interpreter]'
fi
- _find_processes $_procname ${_interpreter:-.} ${_RCARG_ps}
+ _find_processes $_procname ${_interpreter:-.} '-A'
}
#
@@ -272,7 +253,9 @@
# If interpreter != ".", read the first line of procname, remove the
# leading #!, normalise whitespace, append procname, and attempt to
# match that against each command, either as is, or with extra words
-# at the end.
+# at the end. As an alternative, to deal with interpreted daemons
+# using perl, the basename of the interpreter plus a colon is also
+# tried as the prefix to procname.
#
_find_processes()
{
@@ -284,37 +267,46 @@
_psargs=$3
_pref=
+ _procnamebn=${_procname##*/}
if [ $_interpreter != "." ]; then # an interpreted script
- read _interp < $_procname # read interpreter name
+ read _interp < ${_chroot:-}/$_procname # read interpreter name
_interp=${_interp#\#!} # strip #!
set -- $_interp
+ if [ $1 = "/usr/bin/env" ]; then
+ shift
+ set -- $(type $1)
+ shift $(($# - 1))
+ _interp="${1##*/} $_procname"
+ else
+ _interp="$* $_procname"
+ fi
if [ $_interpreter != $1 ]; then
warn "\$command_interpreter $_interpreter != $1"
fi
- _interp="$* $_procname" # cleanup spaces, add _procname
+ _interpbn=${1##*/}
_fp_args='_argv'
_fp_match='case "$_argv" in
- ${_interp}|"${_interp} "*)'
+ ${_interp}|"${_interp} "*|"${_interpbn}: "*${_procnamebn}*)'
else # a normal daemon
- _procnamebn=${_procname##*/}
_fp_args='_arg0 _argv'
_fp_match='case "$_arg0" in
- $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
+ $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")'
fi
_proccheck='
- ${_RCCMD_ps} ${_RCARG_psformat} '"$_psargs"' |
+ ps -o "pid,args" '"$_psargs"' |
while read _npid '"$_fp_args"'; do
case "$_npid" in
PID)
continue ;;
esac ; '"$_fp_match"'
- ${_RCCMD_echo} -n "$_pref$_npid" ;
+ echo -n "$_pref$_npid" ;
_pref=" "
;;
esac
done'
+#echo 1>&2 "proccheck is :$_proccheck:"
eval $_proccheck
}
@@ -332,35 +324,39 @@
while true; do
_nlist="";
for _j in $_list; do
- if ${_RCCMD_kill} -0 $_j 2>/dev/null; then
+ if kill -0 $_j 2>/dev/null; then
_nlist="${_nlist}${_nlist:+ }$_j"
fi
done
if [ -z "$_nlist" ]; then
break
fi
- _list=$_nlist
- ${_RCCMD_echo} -n ${_prefix:-"Waiting for PIDS: "}$_list
- _prefix=", "
- sleep 2
+ if [ "$_list" != "$_nlist" ]; then
+ _list=$_nlist
+ echo -n ${_prefix:-"Waiting for PIDS: "}$_list
+ _prefix=", "
+ fi
+ # We want this to be a tight loop for a fast exit
+ sleep 0.05
done
if [ -n "$_prefix" ]; then
- ${_RCCMD_echo} "."
+ echo "."
fi
}
#
-# run_rc_command argument
+# run_rc_command argument [parameters]
# Search for argument in the list of supported commands, which is:
# "start stop restart rcvar status poll ${extra_commands}"
# If there's a match, run ${argument}_cmd or the default method
-# (see below).
+# (see below), and pass the optional list of parameters to it.
#
# If argument has a given prefix, then change the operation as follows:
# Prefix Operation
# ------ ---------
# fast Skip the pid check, and set rc_fast=yes
# force Set ${rcvar} to YES, and set rc_force=yes
+# one Set ${rcvar} to YES
#
# The following globals are used:
#
@@ -398,6 +394,9 @@
# NOTE: $flags from the parent environment
# can be used to override this.
#
+# ${name}_env n Additional environment variable settings
+# for running ${command}
+#
# ${name}_nice n Nice level to run ${command} at.
#
# ${name}_user n User to run ${command} as, using su(1) if not
@@ -411,13 +410,6 @@
# to run the chrooted ${command} with.
# Requires /usr to be mounted.
#
-# ${name}_systrace n Flags passed to systrace(1) if it is used.
-# Setting this variable enables systracing
-# of the given program. The use of "-a" is
-# recommended so that the boot process is not
-# stalled. In order to pass no flags to
-# systrace, set this variable to "--".
-#
# ${rc_arg}_cmd n If set, use this as the method when invoked;
# Otherwise, use default command (see below)
#
@@ -477,7 +469,7 @@
#
# Variable Purpose
# -------- -------
-# rc_arg Argument to command, after fast/force processing
+# rc_arg Argument to command, after fast/force/one processing
# performed
#
# rc_flags Flags to start the default command with.
@@ -499,21 +491,33 @@
err 3 'run_rc_command: $name is not set.'
fi
+ _rc_prefix=
case "$rc_arg" in
fast*) # "fast" prefix; don't check pid
rc_arg=${rc_arg#fast}
rc_fast=yes
;;
- force*) # "force prefix; always start
- rc_arg=${rc_arg#force}
+ force*) # "force" prefix; always run
rc_force=yes
+ _rc_prefix=force
+ rc_arg=${rc_arg#${_rc_prefix}}
+ if [ -n "${rcvar}" ]; then
+ eval ${rcvar}=YES
+ fi
+ ;;
+ one*) # "one" prefix; set ${rcvar}=yes
+ _rc_prefix=one
+ rc_arg=${rc_arg#${_rc_prefix}}
if [ -n "${rcvar}" ]; then
eval ${rcvar}=YES
fi
;;
esac
- _keywords="start stop restart rcvar $extra_commands"
+ _keywords="start stop restart rcvar"
+ if [ -n "$extra_commands" ]; then
+ _keywords="${_keywords} ${extra_commands}"
+ fi
rc_pid=
_pidcmd=
_procname=${procname:-${command}}
@@ -533,6 +537,7 @@
if [ -z "$rc_arg" ]; then
rc_usage "$_keywords"
fi
+ shift # remove $rc_arg from the positional parameters
if [ -n "$flags" ]; then # allow override from environment
rc_flags=$flags
@@ -542,10 +547,10 @@
eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \
_nice=\$${name}_nice _user=\$${name}_user \
_group=\$${name}_group _groups=\$${name}_groups \
- _systrace=\$${name}_systrace
+ _env=\"\$${name}_env\"
if [ -n "$_user" ]; then # unset $_user if running as that user
- if [ "$_user" = "$($_RCCMD_whoami)" ]; then
+ if [ "$_user" = "$(id -un)" ]; then
unset _user
fi
fi
@@ -553,11 +558,27 @@
# if ${rcvar} is set, and $1 is not
# "rcvar", then run
# checkyesno ${rcvar}
- # and return if that failed
+ # and return if that failed or warn
+ # user and exit when interactive
#
if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
if ! checkyesno ${rcvar}; then
- return 0
+ # check whether interactive or not
+ if [ -n "$_run_rc_script" ]; then
+ return 0
+ fi
+ for _elem in $_keywords; do
+ if [ "$_elem" = "$rc_arg" ]; then
+ cat 1>&2 <<EOF
+\$${rcvar} is not enabled - see ${rcvar_manpage}.
+Use the following if you wish to perform the operation:
+ $0 one${rc_arg}
+EOF
+ exit 1
+ fi
+ done
+ echo 1>&2 "$0: unknown directive '$rc_arg'."
+ rc_usage "$_keywords"
fi
fi
@@ -581,29 +602,31 @@
return 1
fi
- if ! eval $_cmd && [ -z "$rc_force" ]; then
+ if ! eval $_cmd \"\${@}\" && [ -z "$rc_force" ]; then
return 1
fi
eval $_postcmd
return 0
fi
+ if [ ${#} -gt 0 ]; then
+ err 1 "the $rc_arg command does not take any parameters"
+ fi
+
case "$rc_arg" in # default operations...
status)
if [ -n "$rc_pid" ]; then
- ${_RCCMD_echo} \
- "${name} is running as pid $rc_pid."
+ echo "${name} is running as pid $rc_pid."
else
- ${_RCCMD_echo} "${name} is not running."
+ echo "${name} is not running."
return 1
fi
;;
start)
if [ -n "$rc_pid" ]; then
- ${_RCCMD_echo} \
- "${name} already running? (pid=$rc_pid)."
+ echo 1>&2 "${name} already running? (pid=$rc_pid)."
exit 1
fi
@@ -616,7 +639,7 @@
#
for _f in $required_vars; do
if ! checkyesno $_f; then
- warn "\$${_f} is not set."
+ warn "\$${_f} is not enabled."
if [ -z "$rc_force" ]; then
return 1
fi
@@ -648,35 +671,21 @@
# setup the command to run, and run it
#
- ${_RCCMD_echo} "Starting ${name}."
+ echo "Starting ${name}."
if [ -n "$_chroot" ]; then
- if [ "$_osname" = "SunOS" ]; then
- _doit="\
-${_nice:+${_RCCMD_nice} -n $_nice }\
-${_RCCMD_chroot} $_chroot"
- if [ -n "$_user" ]; then
- _doit="\
-$_doit ${_RCCMD_su} ${_RCARG_su} $_user \
--c '${_RCCMD_sh} -c'"
- fi
- _doit="\
-$_doit $command $rc_flags $command_args"
- else
- _doit="\
-${_nice:+${_RCCMD_nice} -n $_nice }\
-${_systrace:+${_RCCMD_systrace} $_systrace }\
-${_RCCMD_chroot} ${_user:+-u $_user }${_group:+-g $_group }\
-${_groups:+-G $_groups } $_chroot $command $rc_flags $command_args"
- fi
+ _doit="\
+$_env_clear_rc_vars $_env \
+${_nice:+nice -n $_nice }\
+chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
+$_chroot $command $rc_flags $command_args"
else
_doit="\
${_chdir:+cd $_chdir; }\
-${_nice:+${_RCCMD_nice} -n $_nice }\
-${_systrace:+${_RCCMD_systrace} $_systrace }\
+$_env_clear_rc_vars $_env \
+${_nice:+nice -n $_nice }\
$command $rc_flags $command_args"
if [ -n "$_user" ]; then
- _doit="${_RCCMD_su} ${_RCARG_su} $_user \
- -c '${_RCCMD_sh} -c \"$_doit\"'"
+ _doit="su -m $_user -c 'sh -c \"$_doit\"'"
fi
fi
@@ -695,10 +704,10 @@
stop)
if [ -z "$rc_pid" ]; then
if [ -n "$pidfile" ]; then
- ${_RCCMD_echo} \
+ echo 1>&2 \
"${name} not running? (check $pidfile)."
else
- ${_RCCMD_echo} "${name} not running?"
+ echo 1>&2 "${name} not running?"
fi
exit 1
fi
@@ -712,11 +721,10 @@
# send the signal to stop
#
- ${_RCCMD_echo} "Stopping ${name}."
- _doit="${_RCCMD_kill} -${sig_stop:-TERM} $rc_pid"
+ echo "Stopping ${name}."
+ _doit="kill -${sig_stop:-TERM} $rc_pid"
if [ -n "$_user" ]; then
- _doit="${_RCCMD_su} ${_RCARG_su} $_user \
- -c '${_RCCMD_sh} -c \"$_doit\"'"
+ _doit="su -m $_user -c 'sh -c \"$_doit\"'"
fi
# if the stop cmd failed and force
@@ -735,20 +743,20 @@
reload)
if [ -z "$rc_pid" ]; then
if [ -n "$pidfile" ]; then
- ${_RCCMD_echo} \
+ echo 1>&2 \
"${name} not running? (check $pidfile)."
else
- ${_RCCMD_echo} "${name} not running?"
+ echo 1>&2 "${name} not running?"
fi
exit 1
fi
- ${_RCCMD_echo} "Reloading ${name} config files."
+ echo "Reloading ${name} config files."
if ! eval $_precmd && [ -z "$rc_force" ]; then
return 1
fi
- _doit="${_RCCMD_kill} -${sig_reload:-HUP} $rc_pid"
+ _doit="kill -${sig_reload:-HUP} $rc_pid"
if [ -n "$_user" ]; then
- _doit="${_RCCMD_su} ${_RCARG_su} $_user -c '${_RCCMD_sh} -c \"$_doit\"'"
+ _doit="su -m $_user -c 'sh -c \"$_doit\"'"
fi
if ! eval $_doit && [ -z "$rc_force" ]; then
return 1
@@ -768,8 +776,8 @@
fi
_rc_restart_done=true
- ( $0 ${rc_force:+force}stop )
- $0 ${rc_force:+force}start
+ ( $0 ${_rc_prefix}stop )
+ $0 ${_rc_prefix}start
eval $_postcmd
;;
@@ -781,12 +789,12 @@
;;
rcvar)
- ${_RCCMD_echo} "# $name"
+ echo "# $name"
if [ -n "$rcvar" ]; then
if checkyesno ${rcvar}; then
- ${_RCCMD_echo} "\$${rcvar}=YES"
+ echo "\$${rcvar}=YES"
else
- ${_RCCMD_echo} "\$${rcvar}=NO"
+ echo "\$${rcvar}=NO"
fi
fi
;;
@@ -799,12 +807,31 @@
return 0
done
- ${_RCCMD_echo} 1>&2 "$0: unknown directive '$rc_arg'."
+ echo 1>&2 "$0: unknown directive '$rc_arg'."
rc_usage "$_keywords"
exit 1
}
#
+# _have_rc_postprocessor
+# Test whether the current script is running in a context that
+# was invoked from /etc/rc with a postprocessor.
+#
+# If the test fails, some variables may be unset to make
+# such tests more efficient in future.
+#
+_have_rc_postprocessor()
+{
+ # Cheap tests that fd and pid are set, fd is writable.
+ [ -n "${_rc_pid}" ] || { unset _rc_pid; return 1; }
+ [ -n "${_rc_postprocessor_fd}" ] || { unset _rc_pid; return 1; }
+ eval ": >&${_rc_postprocessor_fd}" 2>/dev/null \
+ || { unset _rc_pid; return 1; }
+
+ return 0
+}
+
+#
# 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
@@ -812,6 +839,12 @@
# a backup or scratch file, ignore it. Otherwise if it's
# executable run as a child process.
#
+# If `file' contains "KEYWORD: interactive" and if we are
+# running inside /etc/rc with postprocessing, then the script's
+# stdout and stderr are redirected to $_rc_original_stdout_fd and
+# $_rc_original_stderr_fd, so the output will be displayed on the
+# console but not intercepted by /etc/rc's postprocessor.
+#
run_rc_script()
{
_file=$1
@@ -820,32 +853,60 @@
err 3 'USAGE: run_rc_script file arg'
fi
+ _run_rc_script=true
+
unset name command command_args command_interpreter \
extra_commands pidfile procname \
rcvar required_dirs required_files required_vars
eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
+ _must_redirect=false
+ if _have_rc_postprocessor \
+ && _has_rcorder_keyword interactive $_file
+ then
+ _must_redirect=true
+ fi
+
case "$_file" in
*.sh) # run in current shell
- set $_arg ; . $_file
+ if $_must_redirect; then
+ print_rc_metadata \
+ "note:Output from ${_file} is not logged"
+ no_rc_postprocess eval \
+ 'set $_arg ; . $_file'
+ else
+ set $_arg ; . $_file
+ fi
;;
- *[~#]|*.OLD|*.orig) # scratch file; skip
+ *[~#]|*.OLD|*.orig|*,v) # scratch file; skip
warn "Ignoring scratch file $_file"
;;
*) # run in subshell
- if [ -x $_file ]; then
+ if [ -x $_file ] && $_must_redirect; then
+ print_rc_metadata \
+ "note:Output from ${_file} is not logged"
+ if [ -n "$rc_fast_and_loose" ]; then
+ no_rc_postprocess eval \
+ 'set $_arg ; . $_file'
+ else
+ no_rc_postprocess eval \
+ '( set $_arg ; . $_file )'
+ fi
+ elif [ -x $_file ]; then
if [ -n "$rc_fast_and_loose" ]; then
set $_arg ; . $_file
else
( set $_arg ; . $_file )
fi
+ else
+ warn "Ignoring non-executable file $_file"
fi
;;
esac
}
#
-# load_rc_config
+# load_rc_config command
# Source in the configuration file for a given command.
#
load_rc_config()
@@ -858,14 +919,11 @@
if ${_rc_conf_loaded:-false}; then
:
else
- . ${sysconfbase}/rc.conf
+ . /etc/rc.conf
_rc_conf_loaded=true
fi
- if [ "$_osname" = "OpenBSD" ] && [ -f ${sysconfbase}/rc.conf.local ]; then
- . ${sysconfbase}/rc.conf.local
- fi
- if [ -f ${sysconfbase}/rc.conf.d/"$_command" ]; then
- . ${sysconfbase}/rc.conf.d/"$_command"
+ if [ -f /etc/rc.conf.d/"$_command" ]; then
+ . /etc/rc.conf.d/"$_command"
fi
}
@@ -882,13 +940,12 @@
fi
eval $(eval '(
load_rc_config '$1' >/dev/null;
- if [ -n "${'$2'}" ] || [ "${'$2'-UNSET}" != "UNSET" ]; then
+ if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
echo '$2'=\'\''${'$2'}\'\'';
fi
)' )
}
-
#
# rc_usage commands
# Print a usage string for $0, with `commands' being a list of
@@ -896,14 +953,14 @@
#
rc_usage()
{
- ${_RCCMD_echo} -n 1>&2 "Usage: $0 [fast|force]("
+ echo -n 1>&2 "Usage: $0 [fast|force|one]("
_sep=
for _elem; do
- ${_RCCMD_echo} -n 1>&2 "$_sep$_elem"
+ echo -n 1>&2 "$_sep$_elem"
_sep="|"
done
- ${_RCCMD_echo} 1>&2 ")"
+ echo 1>&2 ")"
exit 1
}
@@ -916,10 +973,10 @@
exitval=$1
shift
- if [ -x ${_RCCMD_logger} ]; then
- ${_RCCMD_logger} "$0: ERROR: $*"
+ if [ -x /usr/bin/logger ]; then
+ logger "$0: ERROR: $*"
fi
- ${_RCCMD_echo} 1>&2 "$0: ERROR: $*"
+ echo 1>&2 "$0: ERROR: $*"
exit $exitval
}
@@ -929,10 +986,10 @@
#
warn()
{
- if [ -x ${_RCCMD_logger} ]; then
- ${_RCCMD_logger} "$0: WARNING: $*"
+ if [ -x /usr/bin/logger ]; then
+ logger "$0: WARNING: $*"
fi
- ${_RCCMD_echo} 1>&2 "$0: WARNING: $*"
+ echo 1>&2 "$0: WARNING: $*"
}
#
@@ -975,7 +1032,7 @@
# ensure that history file is not locked
if [ -f $_cur,v ]; then
- ${_RCCMD_rcs} -q -u -U -M $_cur
+ rcs -q -u -U -M $_cur
fi
# ensure after switching to rcs that the
@@ -983,41 +1040,333 @@
if [ -f $_cur ]; then
# no archive, or current newer than archive
if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
- ${_RCCMD_ci} -q -f -u -t-"$_msg0" \
- -m"$_msg1" $_cur
- ${_RCCMD_rcs} -q -kb -U $_cur
- ${_RCCMD_co} -q -f -u $_cur
+ ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
+ rcs -q -kb -U $_cur
+ co -q -f -u $_cur
fi
fi
case $_action in
add|update)
- ${_RCCMD_cp} -p $_file $_cur
- ${_RCCMD_ci} -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
- ${_RCCMD_rcs} -q -kb -U $_cur
- ${_RCCMD_co} -q -f -u $_cur
- ${_RCCMD_chown} root:wheel $_cur $_cur,v
+ cp -p $_file $_cur
+ ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
+ rcs -q -kb -U $_cur
+ co -q -f -u $_cur
+ chown root:wheel $_cur $_cur,v
;;
remove)
- ${_RCCMD_cp} /dev/null $_cur
- ${_RCCMD_ci} -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
- ${_RCCMD_rcs} -q -kb -U $_cur
- ${_RCCMD_chown} root:wheel $_cur $_cur,v
- ${_RCCMD_rm} $_cur
+ cp /dev/null $_cur
+ ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
+ rcs -q -kb -U $_cur
+ chown root:wheel $_cur $_cur,v
+ rm $_cur
;;
esac
else
case $_action in
add|update)
if [ -f $_cur ]; then
- ${_RCCMD_cp} -p $_cur $_back
+ cp -p $_cur $_back
fi
- ${_RCCMD_cp} -p $_file $_cur
- ${_RCCMD_chown} root:wheel $_cur
+ cp -p $_file $_cur
+ chown root:wheel $_cur
;;
remove)
- ${_RCCMD_mv} -f $_cur $_back
+ mv -f $_cur $_back
;;
esac
fi
}
+
+#
+# handle_fsck_error fsck_exit_code
+# Take action depending on the return code from fsck.
+#
+handle_fsck_error()
+{
+ case $1 in
+ 0) # OK
+ return
+ ;;
+ 2) # Needs re-run, still fs errors
+ echo "File system still has errors; re-run fsck manually!"
+ ;;
+ 4) # Root modified
+ echo "Root file system was modified, rebooting ..."
+ reboot -n
+ echo "Reboot failed; help!"
+ ;;
+ 8) # Check failed
+ echo "Automatic file system check failed; help!"
+ ;;
+ 12) # Got signal
+ echo "Boot interrupted."
+ ;;
+ *)
+ echo "Unknown error $1; help!"
+ ;;
+ esac
+ stop_boot
+}
+
+#
+# _has_rcorder_keyword word file
+# Check whether a file contains a "# KEYWORD:" comment with a
+# specified keyword in the style used by rcorder(8).
+#
+_has_rcorder_keyword()
+{
+ local word="$1"
+ local file="$2"
+ local line
+
+ [ -r "$file" ] || return 1
+ while read line; do
+ case "${line} " in
+ "# KEYWORD:"*[\ \ ]"${word}"[\ \ ]*)
+ return 0
+ ;;
+ "#"*)
+ continue
+ ;;
+ *[A-Za-z0-9]*)
+ # give up at the first non-empty non-comment line
+ return 1
+ ;;
+ esac
+ done <"$file"
+ return 1
+}
+
+#
+# print_rc_metadata string
+# Print the specified string in such a way that the post-processor
+# inside /etc/rc will treat it as meta-data.
+#
+# If we are not running inside /etc/rc, do nothing.
+#
+# For public use by any rc.d script, the string must begin with
+# "note:", followed by arbitrary text. The intent is that the text
+# will appear in a log file but not on the console.
+#
+# For private use within /etc/rc, the string must contain a
+# keyword recognised by the rc_postprocess_metadata() function
+# defined in /etc/rc, followed by a colon, followed by one or more
+# colon-separated arguments associated with the keyword.
+#
+print_rc_metadata()
+{
+ # _rc_postprocessor fd, if defined, is the fd to which we must
+ # print, prefixing the output with $_rc_metadata_prefix.
+ #
+ if _have_rc_postprocessor; then
+ command printf "%s%s\n" "$rc_metadata_prefix" "$1" \
+ >&${_rc_postprocessor_fd}
+ fi
+}
+
+#
+# _flush_rc_output
+# Arrange for output to be flushed, if we are running
+# inside /etc/rc with postprocessing.
+#
+_flush_rc_output()
+{
+ print_rc_metadata "nop"
+}
+
+#
+# print_rc_normal [-n] string
+# Print the specified string in such way that it is treated as
+# normal output, regardless of whether or not we are running
+# inside /etc/rc with post-processing.
+#
+# If "-n" is specified in $1, then the string in $2 is printed
+# without a newline; otherwise, the string in $1 is printed
+# with a newline.
+#
+# Intended use cases include:
+#
+# o An rc.d script can use ``print_rc_normal -n'' to print a
+# partial line in such a way that it appears immediately
+# instead of being buffered by rc(8)'s post-processor.
+#
+# o An rc.d script that is run via the no_rc_postprocess
+# function (so most of its output is invisible to rc(8)'s
+# post-processor) can use print_rc_normal to force some of its
+# output to be seen by the post-processor.
+#
+#
+print_rc_normal()
+{
+ # print to stdout or _rc_postprocessor_fd, depending on
+ # whether not we have an rc postprocessor.
+ #
+ local fd=1
+ _have_rc_postprocessor && fd="${_rc_postprocessor_fd}"
+ case "$1" in
+ "-n")
+ command printf "%s" "$2" >&${fd}
+ _flush_rc_output
+ ;;
+ *)
+ command printf "%s\n" "$1" >&${fd}
+ ;;
+ esac
+}
+
+#
+# no_rc_postprocess cmd...
+# Execute the specified command in such a way that its output
+# bypasses the post-processor that handles the output from
+# most commands that are run inside /etc/rc. If we are not
+# inside /etc/rc, then just execute the command without special
+# treatment.
+#
+# The intent is that interactive commands can be run via
+# no_rc_postprocess(), and their output will apear immediately
+# on the console instead of being hidden or delayed by the
+# post-processor. An unfortunate consequence of the output
+# bypassing the post-processor is that the output will not be
+# logged.
+#
+no_rc_postprocess()
+{
+ if _have_rc_postprocessor; then
+ "$@" >&${_rc_original_stdout_fd} 2>&${_rc_original_stderr_fd}
+ else
+ "$@"
+ fi
+}
+
+#
+# twiddle
+# On each call, print a different one of "/", "-", "\\", "|",
+# followed by a backspace. The most recently printed value is
+# saved in $_twiddle_state.
+#
+# Output is to /dev/tty, so this function may be useful even inside
+# a script whose output is redirected.
+#
+twiddle()
+{
+ case "$_twiddle_state" in
+ '/') _next='-' ;;
+ '-') _next='\' ;;
+ '\') _next='|' ;;
+ *) _next='/' ;;
+ esac
+ command printf "%s\b" "$_next" >/dev/tty
+ _twiddle_state="$_next"
+}
+
+#
+# human_exit_code
+# Print the a human version of the exit code.
+#
+human_exit_code()
+{
+ if [ "$1" -lt 127 ]
+ then
+ echo "exited with code $1"
+ elif [ "$(expr $1 % 256)" -eq 127 ]
+ then
+ # This cannot really happen because the shell will not
+ # pass stopped job status out and the exit code is limited
+ # to 8 bits. This code is here just for completeness.
+ echo "stopped with signal $(expr $1 / 256)"
+ else
+ echo "terminated with signal $(expr $1 - 128)"
+ fi
+}
+
+#
+# collapse_backslash_newline
+# Copy input to output, collapsing <backslash><newline>
+# to nothing, but leaving other backslashes alone.
+#
+collapse_backslash_newline()
+{
+ local line
+ while read -r line ; do
+ case "$line" in
+ *\\)
+ # print it, without the backslash or newline
+ command printf "%s" "${line%?}"
+ ;;
+ *)
+ # print it, with a newline
+ command printf "%s\n" "${line}"
+ ;;
+ esac
+ done
+}
+
+# Shell implementations of basename and dirname, usable before
+# the /usr file system is mounted.
+#
+basename()
+{
+ local file="$1"
+ local suffix="$2"
+ local base
+
+ base="${file##*/}" # remove up to and including last '/'
+ base="${base%${suffix}}" # remove suffix, if any
+ command printf "%s\n" "${base}"
+}
+
+dirname()
+{
+ local file="$1"
+ local dir
+
+ case "$file" in
+ /*/*) dir="${file%/*}" ;; # common case: absolute path
+ /*) dir="/" ;; # special case: name in root dir
+ */*) dir="${file%/*}" ;; # common case: relative path with '/'
+ *) dir="." ;; # special case: name without '/'
+ esac
+ command printf "%s\n" "${dir}"
+}
+
+# Override the normal "echo" and "printf" commands, so that
+# partial lines printed by rc.d scripts appear immediately,
+# instead of being buffered by rc(8)'s post-processor.
+#
+# Naive use of the echo or printf commands from rc.d scripts,
+# elsewhere in rc.subr, or anything else that sources rc.subr,
+# will call these functions. To call the real echo and printf
+# commands, use "command echo" or "command printf".
+#
+echo()
+{
+ command echo "$@"
+ case "$1" in
+ '-n') _flush_rc_output ;;
+ esac
+}
+printf()
+{
+ command printf "$@"
+ case "$1" in
+ *'\n') : ;;
+ *) _flush_rc_output ;;
+ esac
+}
+
+kat() {
+ local i
+ local v
+ for i; do
+ while read -r v; do
+ v="${v%%#*}"
+ if [ -z "$v" ]; then
+ continue
+ fi
+ echo "$v"
+ done < "$i"
+ done
+}
+
+_rc_subr_loaded=:
Home |
Main Index |
Thread Index |
Old Index