From 3d03791bb4b55788f1773fd4f06477ce6e5e8438 Mon Sep 17 00:00:00 2001 From: Mike Makonnen Date: Fri, 18 May 2007 12:04:41 +0000 Subject: [PATCH] o Implement the stop_boot subroutine [1]. This subroutine can be used by scripts in rc.d to stop rc(8) from booting into multi-user mode when a critical or severe error condition is encountered. o Modify scripts in etc/rc.d that already implemented this functionality independently. o Document it. [1] - This subroutine was implemented in FreeBSD in rc.d/fsck. I moved it to rc.subr(8). Our version differs slightly in that it takes an optional argument to stop the boot even if "autoboot" is not set. Obtained from: NetBSD MFC after: 2 weeks --- etc/rc.d/fsck | 11 ----------- etc/rc.d/ipsec | 10 +--------- etc/rc.d/mountcritlocal | 2 +- etc/rc.d/mountlate | 2 +- etc/rc.d/root | 2 +- etc/rc.subr | 22 ++++++++++++++++++++++ share/man/man8/rc.8 | 17 ++++++----------- share/man/man8/rc.subr.8 | 19 ++++++++++++++++++- 8 files changed, 50 insertions(+), 35 deletions(-) diff --git a/etc/rc.d/fsck b/etc/rc.d/fsck index 7d329d28c258..0bc7b084a1ef 100755 --- a/etc/rc.d/fsck +++ b/etc/rc.d/fsck @@ -14,17 +14,6 @@ name="fsck" start_cmd="fsck_start" stop_cmd=":" -stop_boot() -{ - # Terminate the process (which may include the parent /etc/rc) - # if booting directly to multiuser mode. - # - if [ "$autoboot" = yes ]; then - kill -TERM $$ - fi - exit 1 -} - fsck_start() { if [ "$autoboot" = no ]; then diff --git a/etc/rc.d/ipsec b/etc/rc.d/ipsec index 67b7e286b79e..223c204c8b6c 100755 --- a/etc/rc.d/ipsec +++ b/etc/rc.d/ipsec @@ -26,15 +26,7 @@ ipsec_prestart() { if [ ! -f "$ipsec_file" ]; then warn "$ipsec_file not readable; ipsec start aborted." - # - # If booting directly to multiuser, send SIGTERM to - # the parent (/etc/rc) to abort the boot - # - if [ "$autoboot" = yes ]; then - echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!" - kill -TERM $$ - exit 1 - fi + stop_boot return 1 fi return 0 diff --git a/etc/rc.d/mountcritlocal b/etc/rc.d/mountcritlocal index 20d247373c50..7bec007f8a4a 100755 --- a/etc/rc.d/mountcritlocal +++ b/etc/rc.d/mountcritlocal @@ -43,7 +43,7 @@ mountcritlocal_start() *) echo 'Mounting /etc/fstab filesystems failed,' \ ' startup aborted' - kill -QUIT $$ + stop_boot true ;; esac } diff --git a/etc/rc.d/mountlate b/etc/rc.d/mountlate index 1d4e33f401a1..6da5e7915281 100644 --- a/etc/rc.d/mountlate +++ b/etc/rc.d/mountlate @@ -27,7 +27,7 @@ mountlate_start() *) echo 'Mounting /etc/fstab filesystems failed,' \ ' startup aborted' - kill -QUIT $$ + stop_boot true ;; esac } diff --git a/etc/rc.d/root b/etc/rc.d/root index 35fd9bb619e7..9c20b7b32fd5 100755 --- a/etc/rc.d/root +++ b/etc/rc.d/root @@ -25,7 +25,7 @@ root_start() *) if ! mount -uw /; then echo 'Mounting root filesystem rw failed, startup aborted' - /bin/kill -QUIT $$ + stop_boot true fi ;; esac diff --git a/etc/rc.subr b/etc/rc.subr index 8cdb6e763521..061f0b9e210a 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -40,6 +40,7 @@ # : ${rcvar_manpage:='rc.conf(5)'} +: ${RC_PID:=$$}; export RC_PID # # Operating System dependent/independent variables @@ -161,6 +162,27 @@ reverse_list() 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 diff --git a/share/man/man8/rc.8 b/share/man/man8/rc.8 index 4f1f1ce82aba..7d3cfe5edb1b 100644 --- a/share/man/man8/rc.8 +++ b/share/man/man8/rc.8 @@ -35,7 +35,7 @@ .\" @(#)rc.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd December 19, 2005 +.Dd May 18, 2007 .Dt RC 8 .Os .Sh NAME @@ -249,16 +249,11 @@ Extreme care must be taken in using this, as the startup sequence will terminate if the script does. .It Pa bar Scripts that are sourced in a subshell. -These can stop the boot if necessary with the following shell -commands: -.Bd -literal -offset indent -if [ "$autoboot" = yes ]; then - kill -TERM $$ -fi -exit 1 -.Ed -.Pp -Note that this should be used extremely sparingly! +The boot does not stop if such a script terminates with a non-zero status, +but a script can stop the boot if necessary by invoking the +.Fn stop_boot +function (from +.Xr rc.subr 8 ). .El .Pp Each script should contain diff --git a/share/man/man8/rc.subr.8 b/share/man/man8/rc.subr.8 index abebb7665635..682acd92a3e7 100644 --- a/share/man/man8/rc.subr.8 +++ b/share/man/man8/rc.subr.8 @@ -36,7 +36,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 27, 2006 +.Dd May 18, 2007 .Dt RC.SUBR 8 .Os .Sh NAME @@ -833,6 +833,23 @@ otherwise source .Ar file into the current shell. .El +.It Ic stop_boot Op Ar always +Prevent booting to multiuser mode. +If the +.Sy autoboot +variable is +.Sq yes , +or +.Ar always +is +.Sq true , +then a +.Sy SIGTERM +signal is sent to the parent +process (which is assumed to be +.Xr rc 8 ). +Otherwise, the shell exits with status +.Li 1 . .It Ic set_rcvar Op Ar base Set the variable name required to start a service. In