diff --git a/doc/plugins.md b/doc/plugins.md index c2ee13a0..c7d09c67 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -112,6 +112,14 @@ at the below hook points. See [Run-parts Scripts](config.md#run-parts-scripts) for details on the requirements, possibilities, and *limitations* of hook scripts. +All hook scripts are called with at least one environment variable set, +the hook name, useful when reusing the same hook script for multiple +hook points: + + - `FINIT_HOOK_NAME`: set to the second label, e.g., `hook/net/up` + - `FINIT_SHUTDOWN`: set for `hook/sys/shutdown` and later to one + of `halt`, `poweroff`, or `reboot`. + **Example:** $ mkdir -p /libexec/finit/hook/sys/down @@ -119,6 +127,10 @@ requirements, possibilities, and *limitations* of hook scripts. #!/bin/sh echo 'I run just before the reboot() syscall at shutdown/reboot' echo 'I have access to /dev since devtmpfs is exempt from umount' + echo "FINIT_HOOK_NAME: $FINIT_HOOK_NAME" + if [ -n "$FINIT_SHUTDOWN" ]; then + echo "FINIT_SHUTDOWN: $FINIT_SHUTDOWN" + fi exit 0 EOF $ chmod +x /libexec/finit/hook/sys/foo.sh diff --git a/plugins/resolvconf.c b/plugins/resolvconf.c index 33f18f3c..82f3d782 100644 --- a/plugins/resolvconf.c +++ b/plugins/resolvconf.c @@ -45,7 +45,7 @@ static void setup(void *arg) touch("/etc/resolvconf/run/enable-updates"); chdir("/etc/resolvconf/run/interface"); - run_parts("/etc/resolvconf/update.d", "-i", 0); + run_parts("/etc/resolvconf/update.d", "-i", NULL, 0); chdir("/"); } diff --git a/src/exec.c b/src/exec.c index 4a16c7dd..83f8a7e9 100644 --- a/src/exec.c +++ b/src/exec.c @@ -441,7 +441,25 @@ pid_t run_sh(char *tty, int noclear, int nowait, struct rlimit rlimit[]) return rc; } -int run_parts(char *dir, char *cmd, int progress) +static void run_env(const char *env[]) +{ + size_t i = 0; + + if (!env) + return; + + while (env[i]) { + size_t j = i + 1; + + if (!env[j]) + break; + + setenv(env[i], env[j], 1); + i += 2; + } +} + +int run_parts(char *dir, char *cmd, const char *env[], int progress) { struct dirent **e; int i, num; @@ -495,6 +513,8 @@ int run_parts(char *dir, char *cmd, int progress) pid = fork(); if (!pid) { sig_unblock(); + run_env(env); + return execvp(_PATH_BSHELL, argv); } diff --git a/src/finit.c b/src/finit.c index 2451dd51..50534b4c 100644 --- a/src/finit.c +++ b/src/finit.c @@ -602,7 +602,7 @@ static void bootstrap_worker(void *work) * Run startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) - run_parts(runparts, NULL, 1); + run_parts(runparts, NULL, NULL, 1); /* diff --git a/src/helpers.h b/src/helpers.h index f3d9c010..4dfbb5af 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -86,7 +86,7 @@ int run_interactive (char *cmd, char *fmt, ...) __attribute__ ((format (prin int exec_runtask (char *cmd, char *args[]); pid_t run_getty (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]); pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimit[]); -int run_parts (char *dir, char *cmd, int progress); +int run_parts (char *dir, char *cmd, const char *env[], int progress); static inline int create(char *path, mode_t mode, uid_t uid, gid_t gid) { diff --git a/src/plugin.c b/src/plugin.c index 4fb4ddfa..370ccd69 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -42,6 +42,7 @@ #include "plugin.h" #include "private.h" #include "service.h" +#include "sig.h" #define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0) #define SEARCH_PLUGIN(str) \ @@ -203,12 +204,33 @@ static const char *hscript_paths[] = HOOK_TYPES; void plugin_script_run(hook_point_t no) { + const char *hook_name = hscript_paths[no]; + const char *env[] = { + "FINIT_HOOK_NAME", hook_name, + "FINIT_SHUTDOWN", NULL, + NULL, + }; char path[CMD_SIZE] = ""; strlcat(path, PLUGIN_HOOK_SCRIPTS_PATH, sizeof(path)); - strlcat(path, hscript_paths[no] + 4, sizeof(path)); + strlcat(path, hook_name + 4, sizeof(path)); - run_parts(path, NULL, 0); + if (no >= HOOK_SHUTDOWN) { + switch (halt) { + case SHUT_OFF: + env[3] = "poweroff"; + break; + case SHUT_HALT: + env[3] = "halt"; + break; + case SHUT_REBOOT: + env[3] = "reboot"; + break; + } + } else + env[2] = NULL; + + run_parts(path, NULL, env, 0); } #else void plugin_script_run(hook_point_t no) diff --git a/src/sig.c b/src/sig.c index b532fcf4..2da123fd 100644 --- a/src/sig.c +++ b/src/sig.c @@ -302,6 +302,7 @@ void do_shutdown(shutop_t op) sched_setscheduler(1, SCHED_RR, &sched_param); } + halt = op; if (sdown) run_interactive(sdown, "Calling shutdown hook: %s", sdown);