aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2007-04-20 09:39:47 +0000
committerRoy Marples <roy@marples.name>2007-04-20 09:39:47 +0000
commitf269f1961b0b4adc094093301f712294a45dccc8 (patch)
tree4a9777b44c61fd7d04658bed2e8544d584a61ce0
parent49b8b30ab7e35d8ad3cbe295eba3a93ba21a3509 (diff)
Plugins now run in a forked process for extra resliance.
-rw-r--r--ChangeLog4
-rw-r--r--src/librc.c3
-rw-r--r--src/rc-plugin.c73
-rw-r--r--src/rc.c3
-rw-r--r--src/rc.h4
5 files changed, 76 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 2a5a43b4..7b6300de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
# ChangeLog for Gentoo System Intialization ("rc") scripts
# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2
+ 20 Apr 2007; Roy Marples <uberlord@gentoo.org>:
+
+ Plugins now run in a forked process for extra resliance.
+
17 Apr 2007; Roy Marples <uberlord@gentoo.org>:
Fix bridge, vlan and bonding modules to work together, #174792.
diff --git a/src/librc.c b/src/librc.c
index a0d09c7d..9172ee7c 100644
--- a/src/librc.c
+++ b/src/librc.c
@@ -15,6 +15,9 @@
#define SOFTLEVEL RC_SVCDIR "softlevel"
+/* File stream used for plugins to write environ vars to */
+FILE *rc_environ_fd = NULL;
+
static const char *rc_service_state_names[] = {
"started",
"stopped",
diff --git a/src/rc-plugin.c b/src/rc-plugin.c
index 8a39e97d..aca20239 100644
--- a/src/rc-plugin.c
+++ b/src/rc-plugin.c
@@ -6,6 +6,8 @@
*/
#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -43,12 +45,7 @@ void rc_plugin_load (void)
files = rc_ls_dir (NULL, RC_PLUGINDIR, 0);
STRLIST_FOREACH (files, file, i) {
char *p = rc_strcatpaths (RC_PLUGINDIR, file, NULL);
- /*
- * We load the use RTLD_NOW so that we know it works
- * as if we have any unknown symbols when we run then the
- * program bails out in rc_plugin_run which is very very bad.
- */
- void *h = dlopen (p, RTLD_NOW);
+ void *h = dlopen (p, RTLD_LAZY);
char *func;
void *f;
int len;
@@ -94,9 +91,67 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
plugin_t *plugin = plugins;
while (plugin) {
- if (plugin->hook)
- plugin->hook (hook, value);
-
+ if (plugin->hook) {
+ int i;
+ int flags;
+ int pfd[2];
+ pid_t pid;
+
+ /* We create a pipe so that plugins can affect our environment
+ * vars, which in turn influence our scripts. */
+ if (pipe (pfd) == -1) {
+ eerror ("pipe: %s", strerror (errno));
+ return;
+ }
+
+ /* Stop any scripts from inheriting us.
+ * This is actually quite important as without this, the splash
+ * plugin will probably hang when running in silent mode. */
+ for (i = 0; i < 2; i++)
+ if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 0 ||
+ fcntl (pfd[i], F_SETFD, flags | FD_CLOEXEC) < 0)
+ eerror ("fcntl: %s", strerror (errno));
+
+ /* We run the plugin in a new process so we never crash
+ * or otherwise affected by it */
+ if ((pid = fork ()) == -1) {
+ eerror ("fork: %s", strerror (errno));
+ return;
+ }
+
+ if (pid == 0) {
+ int retval;
+
+ close (pfd[0]);
+ rc_environ_fd = fdopen (pfd[1], "w");
+ retval = plugin->hook (hook, value);
+ fclose (rc_environ_fd);
+ rc_environ_fd = NULL;
+ _exit (retval);
+ } else {
+ char buffer[RC_LINEBUFFER];
+ char *token;
+ char *p;
+
+ close (pfd[1]);
+ memset (buffer, 0, sizeof (buffer));
+
+ /* Not the best implementation in the world.
+ * We should be able to handle >1 env var.
+ * Maybe split the strings with a NULL character? */
+ while (read (pfd[0], buffer, sizeof (buffer)) > 0) {
+ p = buffer;
+ token = strsep (&p, "=");
+ if (token) {
+ unsetenv (token);
+ if (p)
+ setenv (token, p, 1);
+ }
+ }
+
+ close (pfd[0]);
+ }
+ }
plugin = plugin->next;
}
}
diff --git a/src/rc.c b/src/rc.c
index d2468dc2..d5482d15 100644
--- a/src/rc.c
+++ b/src/rc.c
@@ -1120,8 +1120,7 @@ interactive_option:
}
/* Wait for our services to finish */
- if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
- wait_for_services ();
+ wait_for_services ();
rc_plugin_run (rc_hook_runlevel_start_out, runlevel);
diff --git a/src/rc.h b/src/rc.h
index dbe7147b..56d92eaf 100644
--- a/src/rc.h
+++ b/src/rc.h
@@ -149,6 +149,10 @@ typedef enum
rc_hook_service_start_out
} rc_hook_t;
+/* Plugins should write FOO=BAR to this fd to set any environment variables
+ * they wish. At this time we only support the setting of one env var. */
+extern FILE *rc_environ_fd;
+
/* RC utility functions.
Although not directly related to RC in general, they are used by RC
itself and the supporting applications. */