aboutsummaryrefslogtreecommitdiff
path: root/src/rc/rc-applets.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/rc-applets.c')
-rw-r--r--src/rc/rc-applets.c557
1 files changed, 0 insertions, 557 deletions
diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c
deleted file mode 100644
index ed86a4d8..00000000
--- a/src/rc/rc-applets.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * rc-applets.c
- *
- * Handle multicall applets for use in our init scripts.
- * Basically this makes us a lot faster for the most part, and removes
- * any shell incompatabilities we might otherwise encounter.
-*/
-
-/*
- * 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/master/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/master/LICENSE
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file.
- */
-
-#define SYSLOG_NAMES
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <errno.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "builtins.h"
-#include "einfo.h"
-#include "rc-misc.h"
-
-/* usecs to wait while we poll the file existance */
-#define WAIT_INTERVAL 20000000
-#define ONE_SECOND 690000000
-
-/* Applet is first parsed in rc.c - no point in doing it again */
-extern const char *applet;
-
-static int
-syslog_decode(char *name, CODE *codetab)
-{
- CODE *c;
-
- if (isdigit((unsigned char)*name))
- return atoi(name);
-
- for (c = codetab; c->c_name; c++)
- if (! strcasecmp(name, c->c_name))
- return c->c_val;
-
- return -1;
-}
-
-static int
-do_e(int argc, char **argv)
-{
- int retval = EXIT_SUCCESS;
- int i;
- size_t l = 0;
- char *message = NULL;
- char *p;
- int level = 0;
- struct timespec ts;
- struct timeval stop, now;
- int (*e) (const char *, ...) EINFO_PRINTF(1, 2) = NULL;
- int (*ee) (int, const char *, ...) EINFO_PRINTF(2, 3) = NULL;
-
- /* Punt applet */
- argc--;
- argv++;
-
- if (strcmp(applet, "eval_ecolors") == 0) {
- printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
- ecolor(ECOLOR_GOOD),
- ecolor(ECOLOR_WARN),
- ecolor(ECOLOR_BAD),
- ecolor(ECOLOR_HILITE),
- ecolor(ECOLOR_BRACKET),
- ecolor(ECOLOR_NORMAL));
- exit(EXIT_SUCCESS);
- }
-
- if (argc > 0) {
- if (strcmp(applet, "eend") == 0 ||
- strcmp(applet, "ewend") == 0 ||
- strcmp(applet, "veend") == 0 ||
- strcmp(applet, "vweend") == 0 ||
- strcmp(applet, "ewaitfile") == 0)
- {
- errno = 0;
- retval = (int)strtoimax(argv[0], &p, 0);
- if (!p || *p != '\0')
- errno = EINVAL;
- if (errno)
- retval = EXIT_FAILURE;
- else {
- argc--;
- argv++;
- }
- } else if (strcmp(applet, "esyslog") == 0 ||
- strcmp(applet, "elog") == 0) {
- p = strchr(argv[0], '.');
- if (!p ||
- (level = syslog_decode(p + 1, prioritynames)) == -1)
- eerrorx("%s: invalid log level `%s'", applet, argv[0]);
-
- if (argc < 3)
- eerrorx("%s: not enough arguments", applet);
-
- unsetenv("EINFO_LOG");
- setenv("EINFO_LOG", argv[1], 1);
-
- argc -= 2;
- argv += 2;
- }
- }
-
- if (strcmp(applet, "ewaitfile") == 0) {
- if (errno)
- eerrorx("%s: invalid timeout", applet);
- if (argc == 0)
- eerrorx("%s: not enough arguments", applet);
-
- gettimeofday(&stop, NULL);
- /* retval stores the timeout */
- stop.tv_sec += retval;
- ts.tv_sec = 0;
- ts.tv_nsec = WAIT_INTERVAL;
- for (i = 0; i < argc; i++) {
- ebeginv("Waiting for %s", argv[i]);
- for (;;) {
- if (exists(argv[i]))
- break;
- if (nanosleep(&ts, NULL) == -1)
- return EXIT_FAILURE;
- gettimeofday(&now, NULL);
- if (retval <= 0)
- continue;
- if (timercmp(&now, &stop, <))
- continue;
- eendv(EXIT_FAILURE,
- "timed out waiting for %s", argv[i]);
- return EXIT_FAILURE;
- }
- eendv(EXIT_SUCCESS, NULL);
- }
- return EXIT_SUCCESS;
- }
-
- if (argc > 0) {
- for (i = 0; i < argc; i++)
- l += strlen(argv[i]) + 1;
-
- message = xmalloc(l);
- p = message;
-
- for (i = 0; i < argc; i++) {
- if (i > 0)
- *p++ = ' ';
- l = strlen(argv[i]);
- memcpy(p, argv[i], l);
- p += l;
- }
- *p = 0;
- }
-
- if (strcmp(applet, "einfo") == 0)
- e = einfo;
- else if (strcmp(applet, "einfon") == 0)
- e = einfon;
- else if (strcmp(applet, "ewarn") == 0)
- e = ewarn;
- else if (strcmp(applet, "ewarnn") == 0)
- e = ewarnn;
- else if (strcmp(applet, "eerror") == 0) {
- e = eerror;
- retval = 1;
- } else if (strcmp(applet, "eerrorn") == 0) {
- e = eerrorn;
- retval = 1;
- } else if (strcmp(applet, "ebegin") == 0)
- e = ebegin;
- else if (strcmp(applet, "eend") == 0)
- ee = eend;
- else if (strcmp(applet, "ewend") == 0)
- ee = ewend;
- else if (strcmp(applet, "esyslog") == 0) {
- elog(retval, "%s", message);
- retval = 0;
- } else if (strcmp(applet, "veinfo") == 0)
- e = einfov;
- else if (strcmp(applet, "veinfon") == 0)
- e = einfovn;
- else if (strcmp(applet, "vewarn") == 0)
- e = ewarnv;
- else if (strcmp(applet, "vewarnn") == 0)
- e = ewarnvn;
- else if (strcmp(applet, "vebegin") == 0)
- e = ebeginv;
- else if (strcmp(applet, "veend") == 0)
- ee = eendv;
- else if (strcmp(applet, "vewend") == 0)
- ee = ewendv;
- else if (strcmp(applet, "eindent") == 0)
- eindent();
- else if (strcmp(applet, "eoutdent") == 0)
- eoutdent();
- else if (strcmp(applet, "veindent") == 0)
- eindentv();
- else if (strcmp(applet, "veoutdent") == 0)
- eoutdentv();
- else {
- eerror("%s: unknown applet", applet);
- retval = EXIT_FAILURE;
- }
-
- if (message) {
- if (e)
- e("%s", message);
- else if (ee)
- ee(retval, "%s", message);
- } else {
- if (e)
- e(NULL);
- else if (ee)
- ee(retval, NULL);
- }
-
- free(message);
- return retval;
-}
-
-static const struct {
- const char * const name;
- RC_SERVICE bit;
-} service_bits[] = {
- { "service_started", RC_SERVICE_STARTED, },
- { "service_stopped", RC_SERVICE_STOPPED, },
- { "service_inactive", RC_SERVICE_INACTIVE, },
- { "service_starting", RC_SERVICE_STARTING, },
- { "service_stopping", RC_SERVICE_STOPPING, },
- { "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
- { "service_wasinactive", RC_SERVICE_WASINACTIVE, },
- { "service_failed", RC_SERVICE_FAILED, },
-};
-
-static RC_SERVICE
-lookup_service_state(const char *service)
-{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(service_bits); ++i)
- if (!strcmp(service, service_bits[i].name))
- return service_bits[i].bit;
- return 0;
-}
-
-static int
-do_service(int argc, char **argv)
-{
- bool ok = false;
- char *service;
- char *exec;
- int idx;
- RC_SERVICE state, bit;
-
- if (argc > 1)
- service = argv[1];
- else
- service = getenv("RC_SVCNAME");
-
- if (service == NULL || *service == '\0')
- eerrorx("%s: no service specified", applet);
-
- state = rc_service_state(service);
- bit = lookup_service_state(applet);
- if (bit) {
- ok = (state & bit);
- } else if (strcmp(applet, "service_started_daemon") == 0) {
- service = getenv("RC_SVCNAME");
- exec = argv[1];
- if (argc > 3) {
- service = argv[1];
- exec = argv[2];
- sscanf(argv[3], "%d", &idx);
- } else if (argc == 3) {
- if (sscanf(argv[2], "%d", &idx) != 1) {
- service = argv[1];
- exec = argv[2];
- }
- }
- ok = rc_service_started_daemon(service, exec, NULL, idx);
-
- } else if (strcmp(applet, "service_crashed") == 0) {
- ok = (_rc_can_find_pids() &&
- rc_service_daemons_crashed(service) &&
- errno != EACCES);
- } else
- eerrorx("%s: unknown applet", applet);
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-do_mark_service(int argc, char **argv)
-{
- bool ok = false;
- char *svcname = getenv("RC_SVCNAME");
- char *service = NULL;
- char *openrc_pid;
- /* char *mtime; */
- pid_t pid;
- RC_SERVICE bit;
- /* size_t l; */
-
- if (argc > 1)
- service = argv[1];
- else
- service = svcname;
-
- if (service == NULL || *service == '\0')
- eerrorx("%s: no service specified", applet);
-
- if (!strncmp(applet, "mark_", 5) &&
- (bit = lookup_service_state(applet + 5)))
- ok = rc_service_mark(service, bit);
- else
- eerrorx("%s: unknown applet", applet);
-
- /* If we're marking ourselves then we need to inform our parent
- openrc-run process so they do not mark us based on our exit code */
- /*
- * FIXME: svcname and service are almost always equal except called from a
- * shell with just argv[1] - So that doesn't seem to do what Roy initially
- * expected.
- * See 20120424041423.GA23657@odin.qasl.de (Tue, 24 Apr 2012 06:14:23 +0200,
- * openrc@gentoo.org).
- */
- if (ok && svcname && strcmp(svcname, service) == 0) {
- openrc_pid = getenv("RC_OPENRC_PID");
- if (openrc_pid && sscanf(openrc_pid, "%d", &pid) == 1)
- if (kill(pid, SIGHUP) != 0)
- eerror("%s: failed to signal parent %d: %s",
- applet, pid, strerror(errno));
-
- /* Remove the exclusive time test. This ensures that it's not
- in control as well */
- /*
- l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
- strlen(openrc_pid) + 4;
- mtime = xmalloc(l);
- snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
- svcname, openrc_pid);
- if (exists(mtime) && unlink(mtime) != 0)
- eerror("%s: unlink: %s", applet, strerror(errno));
- free(mtime);
- */
- }
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-do_value(int argc, char **argv)
-{
- bool ok = false;
- char *service = getenv("RC_SVCNAME");
- char *option;
-
- if (service == NULL)
- eerrorx("%s: no service specified", applet);
-
- if (argc < 2 || ! argv[1] || *argv[1] == '\0')
- eerrorx("%s: no option specified", applet);
-
- if (strcmp(applet, "service_get_value") == 0 ||
- strcmp(applet, "get_options") == 0)
- {
- option = rc_service_value_get(service, argv[1]);
- if (option) {
- printf("%s", option);
- free(option);
- ok = true;
- }
- } else if (strcmp(applet, "service_set_value") == 0 ||
- strcmp(applet, "save_options") == 0)
- ok = rc_service_value_set(service, argv[1], argv[2]);
- else
- eerrorx("%s: unknown applet", applet);
-
- return ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static int
-shell_var(int argc, char **argv)
-{
- int i;
- char *p;
- int c;
-
- for (i = 1; i < argc; i++) {
- p = argv[i];
- if (i != 1)
- putchar(' ');
- while (*p) {
- c = (unsigned char)*p++;
- if (! isalnum(c))
- c = '_';
- putchar(c);
- }
- }
- putchar('\n');
- return EXIT_SUCCESS;
-}
-
-static int
-is_older_than(int argc, char **argv)
-{
- int i;
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- /* This test is perverted - historically the baselayout function
- * returns 0 on *failure*, which is plain wrong */
- for (i = 2; i < argc; ++i)
- if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
- return EXIT_SUCCESS;
-
- return EXIT_FAILURE;
-}
-
-static int
-is_newer_than(int argc, char **argv)
-{
- int i;
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- /* This test is correct as it's not present in baselayout */
- for (i = 2; i < argc; ++i)
- if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
-
-static int
-is_runlevel_start(_unused int argc, _unused char **argv)
-{
- return rc_runlevel_starting() ? 0 : 1;
-}
-
-static int
-is_runlevel_stop(_unused int argc, _unused char **argv)
-{
- return rc_runlevel_stopping() ? 0 : 1;
-}
-
-static int
-rc_abort(_unused int argc, _unused char **argv)
-{
- const char *p = getenv("RC_PID");
- int pid;
-
- if (p && sscanf(p, "%d", &pid) == 1) {
- if (kill(pid, SIGUSR1) != 0)
- eerrorx("rc-abort: failed to signal parent %d: %s",
- pid, strerror(errno));
- return EXIT_SUCCESS;
- }
-
- return EXIT_FAILURE;
-}
-
-static const struct {
- const char * const name;
- int (* const applet)(int argc, char **argv);
-} applets[] = {
-#define A(a) { #a, a }
- A(fstabinfo),
- A(mountinfo),
- { "openrc-run", openrc_run, },
- { "rc-depend", rc_depend, },
- { "rc-service", rc_service, },
- { "rc-status", rc_status, },
- { "rc-update", rc_update, },
- { "service", rc_service, },
- { "update-rc", rc_update, },
- A(runscript),
- { "start-stop-daemon", start_stop_daemon, },
- A(checkpath),
- A(swclock),
- A(shell_var),
- A(is_older_than),
- A(is_newer_than),
- A(is_runlevel_start),
- A(is_runlevel_stop),
- { "rc-abort", rc_abort, },
- /* These are purely for init scripts and do not make sense as
- * anything else */
- { "service_get_value", do_value, },
- { "service_set_value", do_value, },
- { "get_options", do_value, },
- { "save_options", do_value, },
-#undef A
-};
-
-void
-run_applets(int argc, char **argv)
-{
- size_t i;
-
- /*
- * The "rc" applet is deprecated and should be referred to as
- * "openrc", so output a warning.
- */
- if (strcmp(applet, "rc") == 0)
- ewarnv("The 'rc' applet is deprecated; please use 'openrc' instead.");
- /* Bug 351712: We need an extra way to explicitly select an applet OTHER
- * than trusting argv[0], as argv[0] is not going to be the applet value if
- * we are doing SELinux context switching. For this, we allow calls such as
- * 'rc --applet APPLET', and shift ALL of argv down by two array items. */
- if ((strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0) &&
- argc >= 3 &&
- (strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) {
- applet = argv[2];
- argv += 2;
- argc -= 2;
- }
-
- for (i = 0; i < ARRAY_SIZE(applets); ++i)
- if (!strcmp(applet, applets[i].name))
- exit(applets[i].applet(argc, argv));
-
- if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
- exit(do_e(argc, argv));
-
- if (strncmp(applet, "service_", strlen("service_")) == 0)
- exit(do_service(argc, argv));
-
- if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0)
- exit(do_mark_service(argc, argv));
-
- if (strcmp(applet, "rc") != 0 && strcmp(applet, "openrc") != 0)
- eerrorx("%s: unknown applet", applet);
-}