aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bächler <thomas@archlinux.org>2009-08-25 12:57:02 +0200
committerThomas Bächler <thomas@archlinux.org>2009-08-25 12:57:02 +0200
commitcfabb85924f35c636550609b332d088aaae9941f (patch)
treedb508828fde2166a8accfd3251da461642812057
parent76bb11cb8b5374ff2bba79afc80c408f61779f0c (diff)
downloadinitscripts-cfabb85924f35c636550609b332d088aaae9941f.tar.xz
Implement a hook-system that allows to add custom code to the initscripts at certain places
A function add_hook can be called from functions.d to register a hook function. The existing hooks are based on suggestions from Michael Towers (larch) and on the implementation of initscripts-extras-fbsplash which currently uses the strings passed to stat_busy and stat_done for this. More hooks can be added if requested. The implementation uses associative arrays and will thus only work with bash 4 or later
-rw-r--r--functions46
-rwxr-xr-xrc.multi4
-rwxr-xr-xrc.shutdown8
-rwxr-xr-xrc.single12
-rwxr-xr-xrc.sysinit9
5 files changed, 78 insertions, 1 deletions
diff --git a/functions b/functions
index 8745a38..56b78be 100644
--- a/functions
+++ b/functions
@@ -229,8 +229,52 @@ ck_status() {
fi
}
+###############################
+# Custom hooks in initscripts #
+###############################
+# Hooks can be used to include custom code in various places in the rc.* scripts
+#
+# Define a hook function in a functions.d file using:
+# function_name() {
+# ...
+# }
+# add_hook hook_name function_name
+# It's allowed to register several hook functions for the same hook
+#
+# The function takes the filename of the script that launched it as an argument
+#
+# Currently, the following hooks exist:
+# start: at the beginning of rc.{multi,shutdown,single,sysinit}
+# end: at the end of rc.{multi,single,sysinit}
+# udevlaunched: after udev has been launched in rc.sysinit and rc.single
+# udevsettled: after uevents have settled in rc.sysinit and rc.single
+# premount: before local filesystems are mounted, but after root is mounted read-write in rc.sysinit
+# prekillall: before all processes are being killed in rc.shutdown and rc.single
+# postkillall: after all processes have been killed in rc.shutdown and rc.single
+# poweroff: directly before powering off in rc.shutdown
+#
+# Make sure to never override the add_hook and run_hook functions via functions.d
+
+declare -A hook_funcs
+for hook in start end udevlaunched udevsettled premount prekillall postkillall poweroff; do
+ hook_funcs["${hook}"]=""
+done
+
+add_hook() {
+ [ -z "$1" -o -z "$2" ] && return 1
+ hook_funcs["$1"]="${hook_funcs["$1"]} $2"
+}
+
+run_hook() {
+ local func
+
+ [ -z "$1" ] && return 1
+ for func in ${hook_funcs["$1"]}; do
+ ${func} "$2"
+ done
+}
-#Source additional functions at the end to allow overrides
+# Source additional functions at the end to allow overrides
for f in /etc/rc.d/functions.d/*; do
if [ -e $f ]; then
. $f
diff --git a/rc.multi b/rc.multi
index 731e48e..0cddd1d 100755
--- a/rc.multi
+++ b/rc.multi
@@ -6,6 +6,8 @@
. /etc/rc.conf
. /etc/rc.d/functions
+run_hook start rc.multi
+
# Load sysctl variables if sysctl.conf is present
[ -r /etc/sysctl.conf ] && /sbin/sysctl -q -p &>/dev/null
@@ -24,4 +26,6 @@ if [ -x /etc/rc.local ]; then
/etc/rc.local
fi
+run_hook end rc.multi
+
# vim: set ts=2 noet:
diff --git a/rc.shutdown b/rc.shutdown
index e2a4a84..5921e1c 100755
--- a/rc.shutdown
+++ b/rc.shutdown
@@ -6,6 +6,8 @@
. /etc/rc.conf
. /etc/rc.d/functions
+run_hook start rc.shutdown
+
# avoid staircase effect
/bin/stty onlcr
@@ -41,6 +43,8 @@ if [ "$PREVLEVEL" = "3" -o "$PREVLEVEL" = "5" ]; then
done
fi
+run_hook prekillall rc.shutdown
+
# Terminate all processes
stat_busy "Sending SIGTERM To Processes"
/sbin/killall5 -15 &> /dev/null
@@ -52,6 +56,8 @@ stat_busy "Sending SIGKILL To Processes"
/bin/sleep 1
stat_done
+run_hook postkillall rc.shutdown
+
stat_busy "Saving Random Seed"
RANDOM_SEED=/var/lib/misc/random-seed
[ -d $(dirname $RANDOM_SEED) ] || mkdir -p $(dirname $RANDOM_SEED)
@@ -132,6 +138,8 @@ stat_busy "Remounting Root Filesystem Read-only"
/bin/mount -n -o remount,ro /
stat_done
+run_hook poweroff rc.shutdown
+
# Power off or reboot
if [ "$RUNLEVEL" = "0" ]; then
printsep
diff --git a/rc.single b/rc.single
index 50b7cfb..d72e95b 100755
--- a/rc.single
+++ b/rc.single
@@ -6,6 +6,8 @@
. /etc/rc.conf
. /etc/rc.d/functions
+run_hook start rc.single
+
if [ "$PREVLEVEL" = "3" -o "$PREVLEVEL" = "5" ]; then
# Find daemons NOT in the DAEMONS array. Shut these down first
if [ -d /var/run/daemons ]; then
@@ -26,6 +28,8 @@ if [ "$PREVLEVEL" = "3" -o "$PREVLEVEL" = "5" ]; then
fi
if [ "$PREVLEVEL" != "N" ]; then
+ run_hook prekillall rc.single
+
# Terminate all processes
stat_busy "Sending SIGTERM To Processes"
/sbin/killall5 -15 &> /dev/null
@@ -37,10 +41,14 @@ if [ "$PREVLEVEL" != "N" ]; then
/bin/sleep 1
stat_done
+ run_hook postkillall rc.single
+
stat_busy "Starting UDev Daemon"
/sbin/udevd --daemon
stat_done
+ run_hook udevlaunched rc.single
+
# Trigger udev uevents
if /bin/pidof -o %PPID /sbin/udevd >/dev/null; then
stat_busy "Triggering UDev uevents"
@@ -55,6 +63,8 @@ if [ "$PREVLEVEL" != "N" ]; then
stat_done
fi
+ run_hook udevsettled rc.single
+
# try syslog-NG first, then fall back to good ol' syslogd
if [ -x /etc/rc.d/syslog-ng ]; then
/etc/rc.d/syslog-ng start
@@ -64,6 +74,8 @@ if [ "$PREVLEVEL" != "N" ]; then
fi
fi
+run_hook end rc.single
+
if [ "$RUNLEVEL" = "1" ]; then
printsep
printhl "Entering single-user mode..."
diff --git a/rc.sysinit b/rc.sysinit
index f6463cc..60dcbef 100755
--- a/rc.sysinit
+++ b/rc.sysinit
@@ -14,6 +14,8 @@ printhl "Copyright 2007-2009 Aaron Griffin"
printhl "Distributed under the GNU General Public License (GPL)"
printsep
+run_hook start rc.sysinit
+
# mount /proc, /sys and our RAM /dev
/bin/mount -n -t tmpfs udev /dev -o mode=0755,size=10M,nosuid
/bin/mount -n -t proc none /proc
@@ -63,6 +65,8 @@ stat_busy "Starting UDev Daemon"
/sbin/udevd --daemon
stat_done
+run_hook udevlaunched rc.sysinit
+
# Trigger udev uevents
if /bin/pidof -o %PPID /sbin/udevd >/dev/null; then
stat_busy "Triggering UDev uevents"
@@ -108,6 +112,8 @@ if /bin/pidof -o %PPID /sbin/udevd >/dev/null; then
stat_done
fi
+run_hook udevsettled rc.sysinit
+
# bring up the loopback interface
if [ -d /sys/class/net/lo ]; then
stat_busy "Bringing up loopback interface"
@@ -282,6 +288,7 @@ stat_busy "Mounting Local Filesystems"
if [ -e /proc/mounts ]; then
/bin/grep -e "/proc " -e "/sys " -e "/dev " /proc/mounts >> /etc/mtab
fi
+run_hook premount rc.sysinit
# now mount all the local filesystems
/bin/mount -a -t $NETFS -O no_netdev
stat_done
@@ -412,5 +419,7 @@ fi
/bin/dmesg >| /var/log/dmesg.log
+run_hook end rc.sysinit
+
# End of file
# vim: set ts=2 noet: