Fix #315: add environment variables to hook scripts

All hook scripts are called with at least one environment variable set,
FINIT_HOOK_NAME, useful when reusing the same hook script for multiple
hook points.  It is set to the string name, also used by the path, e.g.,
hook/net/up.

For all hook points from hook/sys/shutdown and later, FINIT_SHUTDOWN is
also set, to one of:  halt, poweroff, reboot.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2022-11-23 22:51:40 +01:00
1 parent d4ee44e27f
commit 70c2939596
7 files changed
+61 -6

No files matched your search

+12
View File
@@ -112,6 +112,14 @@ at the below hook points.
See [Run-parts Scripts](config.md#run-parts-scripts) for details on the See [Run-parts Scripts](config.md#run-parts-scripts) for details on the
requirements, possibilities, and *limitations* of hook scripts. 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:** **Example:**
$ mkdir -p /libexec/finit/hook/sys/down $ mkdir -p /libexec/finit/hook/sys/down
@@ -119,6 +127,10 @@ requirements, possibilities, and *limitations* of hook scripts.
#!/bin/sh #!/bin/sh
echo 'I run just before the reboot() syscall at shutdown/reboot' echo 'I run just before the reboot() syscall at shutdown/reboot'
echo 'I have access to /dev since devtmpfs is exempt from umount' 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 exit 0
EOF EOF
$ chmod +x /libexec/finit/hook/sys/foo.sh $ chmod +x /libexec/finit/hook/sys/foo.sh
+1 -1
View File
@@ -45,7 +45,7 @@ static void setup(void *arg)
touch("/etc/resolvconf/run/enable-updates"); touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface"); chdir("/etc/resolvconf/run/interface");
run_parts("/etc/resolvconf/update.d", "-i", 0); run_parts("/etc/resolvconf/update.d", "-i", NULL, 0);
chdir("/"); chdir("/");
} }
+21 -1
View File
@@ -441,7 +441,25 @@ pid_t run_sh(char *tty, int noclear, int nowait, struct rlimit rlimit[])
return rc; 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; struct dirent **e;
int i, num; int i, num;
@@ -495,6 +513,8 @@ int run_parts(char *dir, char *cmd, int progress)
pid = fork(); pid = fork();
if (!pid) { if (!pid) {
sig_unblock(); sig_unblock();
run_env(env);
return execvp(_PATH_BSHELL, argv); return execvp(_PATH_BSHELL, argv);
} }
+1 -1
View File
@@ -602,7 +602,7 @@ static void bootstrap_worker(void *work)
* Run startup scripts in the runparts directory, if any. * Run startup scripts in the runparts directory, if any.
*/ */
if (runparts && fisdir(runparts) && !rescue) if (runparts && fisdir(runparts) && !rescue)
run_parts(runparts, NULL, 1); run_parts(runparts, NULL, NULL, 1);
/* /*
+1 -1
View File
@@ -86,7 +86,7 @@ int run_interactive (char *cmd, char *fmt, ...) __attribute__ ((format (prin
int exec_runtask (char *cmd, char *args[]); 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_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[]); 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) static inline int create(char *path, mode_t mode, uid_t uid, gid_t gid)
{ {
+24 -2
View File
@@ -42,6 +42,7 @@
#include "plugin.h" #include "plugin.h"
#include "private.h" #include "private.h"
#include "service.h" #include "service.h"
#include "sig.h"
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0) #define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0)
#define SEARCH_PLUGIN(str) \ #define SEARCH_PLUGIN(str) \
@@ -203,12 +204,33 @@ static const char *hscript_paths[] = HOOK_TYPES;
void plugin_script_run(hook_point_t no) 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] = ""; char path[CMD_SIZE] = "";
strlcat(path, PLUGIN_HOOK_SCRIPTS_PATH, sizeof(path)); 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 #else
void plugin_script_run(hook_point_t no) void plugin_script_run(hook_point_t no)
+1
View File
@@ -302,6 +302,7 @@ void do_shutdown(shutop_t op)
sched_setscheduler(1, SCHED_RR, &sched_param); sched_setscheduler(1, SCHED_RR, &sched_param);
} }
halt = op;
if (sdown) if (sdown)
run_interactive(sdown, "Calling shutdown hook: %s", sdown); run_interactive(sdown, "Calling shutdown hook: %s", sdown);