ZyklonB: run plugins in a special work directory
Also small refactoring.
This commit is contained in:
parent
a275f9636c
commit
ed20322e5e
82
zyklonb.c
82
zyklonb.c
|
@ -1021,16 +1021,12 @@ is_valid_plugin_name (const char *name)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static struct plugin *
|
||||||
plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
plugin_launch (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
{
|
{
|
||||||
const char *plugin_dir = str_map_find (&ctx->config, "plugin_dir");
|
const char *plugin_dir = str_map_find (&ctx->config, "plugin_dir");
|
||||||
if (!plugin_dir)
|
if (!plugin_dir)
|
||||||
FAIL ("plugin directory not set");
|
FAIL ("plugin directory not set");
|
||||||
if (!is_valid_plugin_name (name))
|
|
||||||
FAIL ("invalid plugin name");
|
|
||||||
if (str_map_find (&ctx->plugins_by_name, name))
|
|
||||||
FAIL ("the plugin has already been loaded");
|
|
||||||
|
|
||||||
int stdin_pipe[2];
|
int stdin_pipe[2];
|
||||||
if (pipe (stdin_pipe) == -1)
|
if (pipe (stdin_pipe) == -1)
|
||||||
|
@ -1043,6 +1039,14 @@ plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
goto fail_1;
|
goto fail_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct str work_dir;
|
||||||
|
str_init (&work_dir);
|
||||||
|
get_xdg_home_dir (&work_dir, "XDG_DATA_HOME", ".local/share");
|
||||||
|
str_append_printf (&work_dir, "/%s", PROGRAM_NAME);
|
||||||
|
|
||||||
|
if (!mkdir_with_parents (work_dir.str, e))
|
||||||
|
goto fail_2;
|
||||||
|
|
||||||
set_cloexec (stdin_pipe[1]);
|
set_cloexec (stdin_pipe[1]);
|
||||||
set_cloexec (stdout_pipe[0]);
|
set_cloexec (stdout_pipe[0]);
|
||||||
|
|
||||||
|
@ -1056,36 +1060,40 @@ plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
// Redirect the child's stdin and stdout to the pipes
|
// Redirect the child's stdin and stdout to the pipes
|
||||||
hard_assert (dup2 (stdin_pipe[0], STDIN_FILENO) != -1);
|
if (dup2 (stdin_pipe[0], STDIN_FILENO) == -1
|
||||||
hard_assert (dup2 (stdout_pipe[1], STDOUT_FILENO) != -1);
|
|| dup2 (stdout_pipe[1], STDOUT_FILENO) == -1)
|
||||||
|
{
|
||||||
|
print_error ("%s: %s: %s", "failed to load the plugin",
|
||||||
|
"dup2", strerror (errno));
|
||||||
|
_exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (chdir (work_dir.str))
|
||||||
|
{
|
||||||
|
print_error ("%s: %s: %s", "failed to load the plugin",
|
||||||
|
"chdir", strerror (errno));
|
||||||
|
_exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
xclose (stdin_pipe[0]);
|
xclose (stdin_pipe[0]);
|
||||||
xclose (stdout_pipe[1]);
|
xclose (stdout_pipe[1]);
|
||||||
|
|
||||||
struct str pathname;
|
|
||||||
str_init (&pathname);
|
|
||||||
str_append (&pathname, plugin_dir);
|
|
||||||
str_append_c (&pathname, '/');
|
|
||||||
str_append (&pathname, name);
|
|
||||||
|
|
||||||
// Restore some of the signal handling
|
// Restore some of the signal handling
|
||||||
signal (SIGPIPE, SIG_DFL);
|
signal (SIGPIPE, SIG_DFL);
|
||||||
|
|
||||||
char *const argv[] = { pathname.str, NULL };
|
char *argv[] = { xstrdup_printf ("%s/%s", plugin_dir, name), NULL };
|
||||||
execve (argv[0], argv, environ);
|
execve (argv[0], argv, environ);
|
||||||
|
|
||||||
// We will collect the failure later via SIGCHLD
|
// We will collect the failure later via SIGCHLD
|
||||||
print_error ("%s: %s: %s",
|
print_error ("%s: %s: %s", "failed to load the plugin",
|
||||||
"failed to load the plugin", "exec", strerror (errno));
|
"exec", strerror (errno));
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
str_free (&work_dir);
|
||||||
|
|
||||||
xclose (stdin_pipe[0]);
|
xclose (stdin_pipe[0]);
|
||||||
xclose (stdout_pipe[1]);
|
xclose (stdout_pipe[1]);
|
||||||
|
|
||||||
set_blocking (stdout_pipe[0], false);
|
|
||||||
set_blocking (stdin_pipe[1], false);
|
|
||||||
|
|
||||||
struct plugin *plugin = xmalloc (sizeof *plugin);
|
struct plugin *plugin = xmalloc (sizeof *plugin);
|
||||||
plugin_init (plugin);
|
plugin_init (plugin);
|
||||||
plugin->ctx = ctx;
|
plugin->ctx = ctx;
|
||||||
|
@ -1093,6 +1101,32 @@ plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
plugin->name = xstrdup (name);
|
plugin->name = xstrdup (name);
|
||||||
plugin->read_fd = stdout_pipe[0];
|
plugin->read_fd = stdout_pipe[0];
|
||||||
plugin->write_fd = stdin_pipe[1];
|
plugin->write_fd = stdin_pipe[1];
|
||||||
|
return plugin;
|
||||||
|
|
||||||
|
fail_2:
|
||||||
|
str_free (&work_dir);
|
||||||
|
xclose (stdout_pipe[0]);
|
||||||
|
xclose (stdout_pipe[1]);
|
||||||
|
fail_1:
|
||||||
|
xclose (stdin_pipe[0]);
|
||||||
|
xclose (stdin_pipe[1]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
|
{
|
||||||
|
if (!is_valid_plugin_name (name))
|
||||||
|
FAIL ("invalid plugin name");
|
||||||
|
if (str_map_find (&ctx->plugins_by_name, name))
|
||||||
|
FAIL ("the plugin has already been loaded");
|
||||||
|
|
||||||
|
struct plugin *plugin;
|
||||||
|
if (!(plugin = plugin_launch (ctx, name, e)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
set_blocking (plugin->read_fd, false);
|
||||||
|
set_blocking (plugin->write_fd, false);
|
||||||
|
|
||||||
poller_fd_init (&plugin->read_event, &ctx->poller, plugin->read_fd);
|
poller_fd_init (&plugin->read_event, &ctx->poller, plugin->read_fd);
|
||||||
plugin->read_event.dispatcher = (poller_fd_fn) on_plugin_readable;
|
plugin->read_event.dispatcher = (poller_fd_fn) on_plugin_readable;
|
||||||
|
@ -1107,14 +1141,6 @@ plugin_load (struct bot_context *ctx, const char *name, struct error **e)
|
||||||
|
|
||||||
poller_fd_set (&plugin->read_event, POLLIN);
|
poller_fd_set (&plugin->read_event, POLLIN);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail_2:
|
|
||||||
xclose (stdout_pipe[0]);
|
|
||||||
xclose (stdout_pipe[1]);
|
|
||||||
fail_1:
|
|
||||||
xclose (stdin_pipe[0]);
|
|
||||||
xclose (stdin_pipe[1]);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
Loading…
Reference in New Issue