aboutsummaryrefslogtreecommitdiff
path: root/src/rc/rc-plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/rc-plugin.c')
-rw-r--r--src/rc/rc-plugin.c245
1 files changed, 0 insertions, 245 deletions
diff --git a/src/rc/rc-plugin.c b/src/rc/rc-plugin.c
deleted file mode 100644
index 76995866..00000000
--- a/src/rc/rc-plugin.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * rc-plugin.c
- * Simple plugin handler
- */
-
-/*
- * Copyright (c) 2007-2015 The OpenRC Authors.
- * See the Authors file at the top-level directory of this distribution and
- * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS
- *
- * This file is part of OpenRC. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file.
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <dirent.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "einfo.h"
-#include "queue.h"
-#include "rc.h"
-#include "rc-misc.h"
-#include "rc-plugin.h"
-
-#define RC_PLUGIN_HOOK "rc_plugin_hook"
-
-bool rc_in_plugin = false;
-
-typedef struct plugin
-{
- char *name;
- void *handle;
- int (*hook)(RC_HOOK, const char *);
- TAILQ_ENTRY(plugin) entries;
-} PLUGIN;
-TAILQ_HEAD(, plugin) plugins;
-
-#ifndef __FreeBSD__
-dlfunc_t
-dlfunc(void * __restrict handle, const char * __restrict symbol)
-{
- union {
- void *d;
- dlfunc_t f;
- } rv;
-
- rv.d = dlsym(handle, symbol);
- return rv.f;
-}
-#endif
-
-void
-rc_plugin_load(void)
-{
- DIR *dp;
- struct dirent *d;
- PLUGIN *plugin;
- char *file = NULL;
- void *h;
- int (*fptr)(RC_HOOK, const char *);
-
- /* Don't load plugins if we're in one */
- if (rc_in_plugin)
- return;
-
- TAILQ_INIT(&plugins);
-
- if (!(dp = opendir(RC_PLUGINDIR)))
- return;
-
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.')
- continue;
-
- xasprintf(&file, RC_PLUGINDIR "/%s", d->d_name);
- h = dlopen(file, RTLD_LAZY);
- free(file);
- if (h == NULL) {
- eerror("dlopen: %s", dlerror());
- continue;
- }
-
- fptr = (int (*)(RC_HOOK, const char *))
- dlfunc(h, RC_PLUGIN_HOOK);
- if (fptr == NULL) {
- eerror("%s: cannot find symbol `%s'",
- d->d_name, RC_PLUGIN_HOOK);
- dlclose(h);
- } else {
- plugin = xmalloc(sizeof(*plugin));
- plugin->name = xstrdup(d->d_name);
- plugin->handle = h;
- plugin->hook = fptr;
- TAILQ_INSERT_TAIL(&plugins, plugin, entries);
- }
- }
- closedir(dp);
-}
-
-int
-rc_waitpid(pid_t pid)
-{
- int status;
-
- while (waitpid(pid, &status, 0) == -1) {
- if (errno != EINTR) {
- status = -1;
- break;
- }
- }
- return status;
-}
-
-void
-rc_plugin_run(RC_HOOK hook, const char *value)
-{
- PLUGIN *plugin;
- struct sigaction sa;
- sigset_t empty;
- sigset_t full;
- sigset_t old;
- int i;
- int flags;
- int pfd[2];
- pid_t pid;
- char *buffer;
- char *token;
- char *p;
- ssize_t nr;
- int retval;
-
- /* Don't run plugins if we're in one */
- if (rc_in_plugin)
- return;
-
- /* We need to block signals until we have forked */
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SIG_DFL;
- sigemptyset(&sa.sa_mask);
- sigemptyset(&empty);
- sigfillset(&full);
-
- TAILQ_FOREACH(plugin, &plugins, entries) {
- /* 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));
-
- sigprocmask(SIG_SETMASK, &full, &old);
-
- /* 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));
- break;
- }
-
- if (pid == 0) {
- /* Restore default handlers */
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGQUIT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
- sigaction(SIGWINCH, &sa, NULL);
- sigprocmask(SIG_SETMASK, &old, NULL);
-
- rc_in_plugin = true;
- close(pfd[0]);
- rc_environ_fd = fdopen(pfd[1], "w");
- retval = plugin->hook(hook, value);
- fclose(rc_environ_fd);
- rc_environ_fd = NULL;
-
- /* Just in case the plugin sets this to false */
- rc_in_plugin = true;
- exit(retval);
- }
-
- sigprocmask(SIG_SETMASK, &old, NULL);
- close(pfd[1]);
- buffer = xmalloc(sizeof(char) * BUFSIZ);
- memset(buffer, 0, BUFSIZ);
-
- while ((nr = read(pfd[0], buffer, BUFSIZ)) > 0) {
- p = buffer;
- while (*p && p - buffer < nr) {
- token = strsep(&p, "=");
- if (token) {
- unsetenv(token);
- if (*p) {
- setenv(token, p, 1);
- p += strlen(p) + 1;
- } else
- p++;
- }
- }
- }
-
- free(buffer);
- close(pfd[0]);
-
- rc_waitpid(pid);
- }
-}
-
-void
-rc_plugin_unload(void)
-{
- PLUGIN *plugin = TAILQ_FIRST(&plugins);
- PLUGIN *next;
-
- while (plugin) {
- next = TAILQ_NEXT(plugin, entries);
- dlclose(plugin->handle);
- free(plugin->name);
- free(plugin);
- plugin = next;
- }
- TAILQ_INIT(&plugins);
-}