aboutsummaryrefslogtreecommitdiff
path: root/src/rc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc')
-rw-r--r--src/rc/Makefile5
-rw-r--r--src/rc/builtins.h2
-rw-r--r--src/rc/rc-applets.c436
-rw-r--r--src/rc/rc.c380
4 files changed, 444 insertions, 379 deletions
diff --git a/src/rc/Makefile b/src/rc/Makefile
index eeb1c066..9d5f4b87 100644
--- a/src/rc/Makefile
+++ b/src/rc/Makefile
@@ -1,6 +1,7 @@
PROG= rc
-SRCS= checkpath.c fstabinfo.c mountinfo.c rc.c rc-depend.c \
- rc-logger.c rc-misc.c rc-plugin.c rc-status.c rc-update.c \
+SRCS= checkpath.c fstabinfo.c mountinfo.c \
+ rc-applets.c rc-depend.c rc-logger.c \
+ rc-misc.c rc-plugin.c rc-status.c rc-update.c rc.c \
runscript.c start-stop-daemon.c
CLEANFILES= version.h
diff --git a/src/rc/builtins.h b/src/rc/builtins.h
index 7d05fa76..61fe3713 100644
--- a/src/rc/builtins.h
+++ b/src/rc/builtins.h
@@ -35,5 +35,7 @@ int rc_update (int argc, char **argv);
int runscript (int argc, char **argv);
int start_stop_daemon (int argc, char **argv);
+void run_applets (int argc, char **argv);
+
/* Handy function so we can wrap einfo around our deptree */
rc_depinfo_t *_rc_deptree_load (int *regen);
diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c
new file mode 100644
index 00000000..59fff72b
--- /dev/null
+++ b/src/rc/rc-applets.c
@@ -0,0 +1,436 @@
+/*
+ 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 2007-2008 Roy Marples
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define SYSLOG_NAMES
+
+#include <sys/types.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "builtins.h"
+#include "einfo.h"
+#include "rc-misc.h"
+#include "strlist.h"
+
+/* 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 ((int) *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;
+ int l = 0;
+ char *message = NULL;
+ char *p;
+ int level = 0;
+
+ /* 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)
+ {
+ errno = 0;
+ retval = strtol (argv[0], NULL, 0);
+ if (errno != 0)
+ retval = EXIT_FAILURE;
+ else {
+ argc--;
+ argv++;
+ }
+ } else if (strcmp (applet, "esyslog") == 0 ||
+ strcmp (applet, "elog") == 0) {
+ char *dot = strchr (argv[0], '.');
+ if ((level = syslog_decode (dot + 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 (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++ = ' ';
+ memcpy (p, argv[i], strlen (argv[i]));
+ p += strlen (argv[i]);
+ }
+ *p = 0;
+ }
+
+ if (! message)
+ message = xstrdup ("");
+
+ if (strcmp (applet, "einfo") == 0)
+ einfo ("%s", message);
+ else if (strcmp (applet, "einfon") == 0)
+ einfon ("%s", message);
+ else if (strcmp (applet, "ewarn") == 0)
+ ewarn ("%s", message);
+ else if (strcmp (applet, "ewarnn") == 0)
+ ewarnn ("%s", message);
+ else if (strcmp (applet, "eerror") == 0) {
+ eerror ("%s", message);
+ retval = 1;
+ } else if (strcmp (applet, "eerrorn") == 0) {
+ eerrorn ("%s", message);
+ retval = 1;
+ } else if (strcmp (applet, "ebegin") == 0)
+ ebegin ("%s", message);
+ else if (strcmp (applet, "eend") == 0)
+ eend (retval, "%s", message);
+ else if (strcmp (applet, "ewend") == 0)
+ ewend (retval, "%s", message);
+ else if (strcmp (applet, "esyslog") == 0)
+ elog (level, "%s", message);
+ else if (strcmp (applet, "veinfo") == 0)
+ einfov ("%s", message);
+ else if (strcmp (applet, "veinfon") == 0)
+ einfovn ("%s", message);
+ else if (strcmp (applet, "vewarn") == 0)
+ ewarnv ("%s", message);
+ else if (strcmp (applet, "vewarnn") == 0)
+ ewarnvn ("%s", message);
+ else if (strcmp (applet, "vebegin") == 0)
+ ebeginv ("%s", message);
+ else if (strcmp (applet, "veend") == 0)
+ eendv (retval, "%s", message);
+ else if (strcmp (applet, "vewend") == 0)
+ ewendv (retval, "%s", message);
+ 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;
+ }
+
+ free (message);
+ return (retval);
+}
+
+static int do_service (int argc, char **argv)
+{
+ bool ok = false;
+ char *service = NULL;
+
+ if (argc > 1)
+ service = argv[1];
+ else
+ service = getenv ("SVCNAME");
+
+ if (! service || strlen (service) == 0)
+ eerrorx ("%s: no service specified", applet);
+
+ if (strcmp (applet, "service_started") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_STARTED);
+ else if (strcmp (applet, "service_stopped") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_STOPPED);
+ else if (strcmp (applet, "service_inactive") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_INACTIVE);
+ else if (strcmp (applet, "service_starting") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_STARTING);
+ else if (strcmp (applet, "service_stopping") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_STOPPING);
+ else if (strcmp (applet, "service_coldplugged") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_COLDPLUGGED);
+ else if (strcmp (applet, "service_wasinactive") == 0)
+ ok = (rc_service_state (service) & RC_SERVICE_WASINACTIVE);
+ else if (strcmp (applet, "service_started_daemon") == 0) {
+ int idx = 0;
+ char *d = argv[1];
+
+ service = getenv ("SVCNAME");
+ if (argc > 3) {
+ service = argv[0];
+ d = argv[2];
+ sscanf (argv[3], "%d", &idx);
+ } else if (argc == 3) {
+ sscanf (argv[2], "%d", &idx);
+ }
+ exit (rc_service_started_daemon (service, d, idx) ? 0 : 1);
+ } 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 ("SVCNAME");
+ char *service = NULL;
+
+ if (argc > 1)
+ service = argv[1];
+ else
+ service = getenv ("SVCNAME");
+
+ if (! service || strlen (service) == 0)
+ eerrorx ("%s: no service specified", applet);
+
+ if (strcmp (applet, "mark_service_started") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_STARTED);
+ else if (strcmp (applet, "mark_service_stopped") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_STOPPED);
+ else if (strcmp (applet, "mark_service_inactive") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_INACTIVE);
+ else if (strcmp (applet, "mark_service_starting") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_STARTING);
+ else if (strcmp (applet, "mark_service_stopping") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_STOPPING);
+ else if (strcmp (applet, "mark_service_coldplugged") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
+ else if (strcmp (applet, "mark_service_failed") == 0)
+ ok = rc_service_mark (service, RC_SERVICE_FAILED);
+ else
+ eerrorx ("%s: unknown applet", applet);
+
+ /* If we're marking ourselves then we need to inform our parent runscript
+ process so they do not mark us based on our exit code */
+ if (ok && svcname && strcmp (svcname, service) == 0) {
+ char *runscript_pid = getenv ("RC_RUNSCRIPT_PID");
+ char *mtime;
+ pid_t pid = 0;
+ int l;
+
+ if (runscript_pid && sscanf (runscript_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 (runscript_pid) +
+ 4;
+ mtime = xmalloc (l);
+ snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
+ svcname, runscript_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 ("SVCNAME");
+
+ if (! service)
+ eerrorx ("%s: no service specified", applet);
+
+ if (argc < 2 || ! argv[1] || strlen (argv[1]) == 0)
+ eerrorx ("%s: no option specified", applet);
+
+ if (strcmp (applet, "service_get_value") == 0 ||
+ strcmp (applet, "get_options") == 0)
+ {
+ char *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 do_shell_var (int argc, char **argv)
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ char *p = argv[i];
+
+ if (i != 0)
+ putchar (' ');
+
+ while (*p) {
+ char c = *p++;
+ if (! isalnum ((int) c))
+ c = '_';
+ putchar (c);
+ }
+ }
+ putchar ('\n');
+
+ return (EXIT_SUCCESS);
+}
+
+
+void run_applets (int argc, char **argv)
+{
+ /* These are designed to be applications in their own right */
+ if (strcmp (applet, "fstabinfo") == 0)
+ exit (fstabinfo (argc, argv));
+ else if (strcmp (applet, "mountinfo") == 0)
+ exit (mountinfo (argc, argv));
+ else if (strcmp (applet, "rc-depend") == 0)
+ exit (rc_depend (argc, argv));
+ else if (strcmp (applet, "rc-status") == 0)
+ exit (rc_status (argc, argv));
+ else if (strcmp (applet, "rc-update") == 0 ||
+ strcmp (applet, "update-rc") == 0)
+ exit (rc_update (argc, argv));
+ else if (strcmp (applet, "runscript") == 0)
+ exit (runscript (argc, argv));
+ else if (strcmp (applet, "start-stop-daemon") == 0)
+ exit (start_stop_daemon (argc, argv));
+ else if (strcmp (applet, "checkpath") == 0)
+ exit (checkpath (argc, argv));
+
+ /* These could also be applications in their own right */
+ if (strcmp (applet, "shell_var") == 0)
+ exit (do_shell_var (argc, argv));
+
+ if (strcmp (applet, "is_newer_than") == 0 ||
+ strcmp (applet, "is_older_than") == 0)
+ {
+ bool match = false;
+ int i = 1;
+
+ if (argc < 3)
+ exit (EXIT_FAILURE);
+ if (strcmp (applet, "is_newer_than") == 0)
+ match = true;
+ while (i < argc) {
+ if (rc_newer_than (argv[1], argv[i++]) != match)
+ exit (EXIT_FAILURE);
+ }
+ exit (EXIT_SUCCESS);
+ };
+
+ if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
+ exit (do_e (argc, argv));
+
+ /* These are purely for init scripts and do not make sense as
+ * anything else */
+ if (strcmp (applet, "service_get_value") == 0 ||
+ strcmp (applet, "service_set_value") == 0 ||
+ strcmp (applet, "get_options") == 0 ||
+ strcmp (applet, "save_options") == 0)
+ exit (do_value (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, "is_runlevel_start") == 0)
+ exit (rc_runlevel_starting () ? 0 : 1);
+ else if (strcmp (applet, "is_runlevel_stop") == 0)
+ exit (rc_runlevel_stopping () ? 0 : 1);
+
+ if (strcmp (applet, "rc-abort") == 0) {
+ char *p = getenv ("RC_PID");
+ pid_t pid = 0;
+
+ if (p && sscanf (p, "%d", &pid) == 1) {
+ if (kill (pid, SIGUSR1) != 0)
+ eerrorx ("rc-abort: failed to signal parent %d: %s",
+ pid, strerror (errno));
+ exit (EXIT_SUCCESS);
+ }
+ exit (EXIT_FAILURE);
+ }
+
+ if (strcmp (applet, "rc" ) != 0)
+ eerrorx ("%s: unknown applet", applet);
+}
diff --git a/src/rc/rc.c b/src/rc/rc.c
index 93be82d4..fba3cc09 100644
--- a/src/rc/rc.c
+++ b/src/rc/rc.c
@@ -36,8 +36,6 @@
const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
-#define SYSLOG_NAMES
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -54,7 +52,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <signal.h>
#include <string.h>
#include <strings.h>
-#include <syslog.h>
#include <termios.h>
#include <unistd.h>
@@ -90,7 +87,7 @@ extern char **environ;
static char *RUNLEVEL = NULL;
static char *PREVLEVEL = NULL;
-static const char *applet = NULL;
+const char *applet = NULL;
static char *runlevel = NULL;
static char **env = NULL;
static char **newenv = NULL;
@@ -179,302 +176,6 @@ static void cleanup (void)
}
}
-static int syslog_decode (char *name, CODE *codetab)
-{
- CODE *c;
-
- if (isdigit ((int) *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;
- int l = 0;
- char *message = NULL;
- char *p;
- int level = 0;
-
- 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)
- {
- errno = 0;
- retval = strtol (argv[0], NULL, 0);
- if (errno != 0)
- retval = EXIT_FAILURE;
- else {
- argc--;
- argv++;
- }
- } else if (strcmp (applet, "esyslog") == 0 ||
- strcmp (applet, "elog") == 0) {
- char *dot = strchr (argv[0], '.');
- if ((level = syslog_decode (dot + 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 (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++ = ' ';
- memcpy (p, argv[i], strlen (argv[i]));
- p += strlen (argv[i]);
- }
- *p = 0;
- }
-
- if (! message)
- message = xstrdup ("");
-
- if (strcmp (applet, "einfo") == 0)
- einfo ("%s", message);
- else if (strcmp (applet, "einfon") == 0)
- einfon ("%s", message);
- else if (strcmp (applet, "ewarn") == 0)
- ewarn ("%s", message);
- else if (strcmp (applet, "ewarnn") == 0)
- ewarnn ("%s", message);
- else if (strcmp (applet, "eerror") == 0) {
- eerror ("%s", message);
- retval = 1;
- } else if (strcmp (applet, "eerrorn") == 0) {
- eerrorn ("%s", message);
- retval = 1;
- } else if (strcmp (applet, "ebegin") == 0)
- ebegin ("%s", message);
- else if (strcmp (applet, "eend") == 0)
- eend (retval, "%s", message);
- else if (strcmp (applet, "ewend") == 0)
- ewend (retval, "%s", message);
- else if (strcmp (applet, "esyslog") == 0)
- elog (level, "%s", message);
- else if (strcmp (applet, "veinfo") == 0)
- einfov ("%s", message);
- else if (strcmp (applet, "veinfon") == 0)
- einfovn ("%s", message);
- else if (strcmp (applet, "vewarn") == 0)
- ewarnv ("%s", message);
- else if (strcmp (applet, "vewarnn") == 0)
- ewarnvn ("%s", message);
- else if (strcmp (applet, "vebegin") == 0)
- ebeginv ("%s", message);
- else if (strcmp (applet, "veend") == 0)
- eendv (retval, "%s", message);
- else if (strcmp (applet, "vewend") == 0)
- ewendv (retval, "%s", message);
- 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;
- }
-
- free (message);
- return (retval);
-}
-
-static int do_service (int argc, char **argv)
-{
- bool ok = false;
- char *service = NULL;
-
- if (argc > 0)
- service = argv[0];
- else
- service = getenv ("SVCNAME");
-
- if (! service || strlen (service) == 0)
- eerrorx ("%s: no service specified", applet);
-
- if (strcmp (applet, "service_started") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_STARTED);
- else if (strcmp (applet, "service_stopped") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_STOPPED);
- else if (strcmp (applet, "service_inactive") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_INACTIVE);
- else if (strcmp (applet, "service_starting") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_STARTING);
- else if (strcmp (applet, "service_stopping") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_STOPPING);
- else if (strcmp (applet, "service_coldplugged") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_COLDPLUGGED);
- else if (strcmp (applet, "service_wasinactive") == 0)
- ok = (rc_service_state (service) & RC_SERVICE_WASINACTIVE);
- else if (strcmp (applet, "service_started_daemon") == 0) {
- int idx = 0;
- char *d = argv[0];
-
- service = getenv ("SVCNAME");
- if (argc > 2) {
- service = argv[0];
- d = argv[1];
- sscanf (argv[2], "%d", &idx);
- } else if (argc == 2) {
- sscanf (argv[1], "%d", &idx);
- }
- exit (rc_service_started_daemon (service, d, idx) ? 0 : 1);
- } 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 ("SVCNAME");
- char *service = NULL;
-
- if (argc > 0)
- service = argv[0];
- else
- service = getenv ("SVCNAME");
-
- if (! service || strlen (service) == 0)
- eerrorx ("%s: no service specified", applet);
-
- if (strcmp (applet, "mark_service_started") == 0)
- ok = rc_service_mark (service, RC_SERVICE_STARTED);
- else if (strcmp (applet, "mark_service_stopped") == 0)
- ok = rc_service_mark (service, RC_SERVICE_STOPPED);
- else if (strcmp (applet, "mark_service_inactive") == 0)
- ok = rc_service_mark (service, RC_SERVICE_INACTIVE);
- else if (strcmp (applet, "mark_service_starting") == 0)
- ok = rc_service_mark (service, RC_SERVICE_STARTING);
- else if (strcmp (applet, "mark_service_stopping") == 0)
- ok = rc_service_mark (service, RC_SERVICE_STOPPING);
- else if (strcmp (applet, "mark_service_coldplugged") == 0)
- ok = rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
- else if (strcmp (applet, "mark_service_failed") == 0)
- ok = rc_service_mark (service, RC_SERVICE_FAILED);
- else
- eerrorx ("%s: unknown applet", applet);
-
- /* If we're marking ourselves then we need to inform our parent runscript
- process so they do not mark us based on our exit code */
- if (ok && svcname && strcmp (svcname, service) == 0) {
- char *runscript_pid = getenv ("RC_RUNSCRIPT_PID");
- char *mtime;
- pid_t pid = 0;
- int l;
-
- if (runscript_pid && sscanf (runscript_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 (runscript_pid) +
- 4;
- mtime = xmalloc (l);
- snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
- svcname, runscript_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 ("SVCNAME");
-
- if (! service)
- eerrorx ("%s: no service specified", applet);
-
- if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
- eerrorx ("%s: no option specified", applet);
-
- if (strcmp (applet, "service_get_value") == 0 ||
- strcmp (applet, "get_options") == 0)
- {
- char *option = rc_service_value_get (service, argv[0]);
- 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[0], argv[1]);
- else
- eerrorx ("%s: unknown applet", applet);
-
- return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static int do_shell_var (int argc, char **argv)
-{
- int i;
-
- for (i = 0; i < argc; i++) {
- char *p = argv[i];
-
- if (i != 0)
- putchar (' ');
-
- while (*p) {
- char c = *p++;
- if (! isalnum ((int) c))
- c = '_';
- putchar (c);
- }
- }
- putchar ('\n');
-
- return (EXIT_SUCCESS);
-}
-
#ifdef __linux__
static char *proc_getent (const char *ent)
{
@@ -874,83 +575,8 @@ int main (int argc, char **argv)
exit (EXIT_SUCCESS);
}
- /* These used to be programs in their own right, so we shouldn't
- * touch argc or argv for them */
- if (strcmp (applet, "fstabinfo") == 0)
- exit (fstabinfo (argc, argv));
- else if (strcmp (applet, "mountinfo") == 0)
- exit (mountinfo (argc, argv));
- else if (strcmp (applet, "rc-depend") == 0)
- exit (rc_depend (argc, argv));
- else if (strcmp (applet, "rc-status") == 0)
- exit (rc_status (argc, argv));
- else if (strcmp (applet, "rc-update") == 0 ||
- strcmp (applet, "update-rc") == 0)
- exit (rc_update (argc, argv));
- else if (strcmp (applet, "runscript") == 0)
- exit (runscript (argc, argv));
- else if (strcmp (applet, "start-stop-daemon") == 0)
- exit (start_stop_daemon (argc, argv));
- else if (strcmp (applet, "checkpath") == 0)
- exit (checkpath (argc, argv));
-
- argc--;
- argv++;
-
- /* Handle multicall stuff */
- if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
- exit (do_e (argc, argv));
-
- if (strcmp (applet, "service_get_value") == 0 ||
- strcmp (applet, "service_set_value") == 0 ||
- strcmp (applet, "get_options") == 0 ||
- strcmp (applet, "save_options") == 0)
- exit (do_value (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, "is_newer_than") == 0 ||
- strcmp (applet, "is_older_than") == 0)
- {
- bool match = false;
- if (argc < 2)
- exit (EXIT_FAILURE);
- if (strcmp (applet, "is_newer_than") == 0)
- match = true;
- while (optind < argc) {
- if (rc_newer_than (argv[0], argv[optind++]) != match)
- exit (EXIT_FAILURE);
- }
- exit (EXIT_SUCCESS);
- };
-
- if (strcmp (applet, "is_runlevel_start") == 0)
- exit (rc_runlevel_starting () ? 0 : 1);
- else if (strcmp (applet, "is_runlevel_stop") == 0)
- exit (rc_runlevel_stopping () ? 0 : 1);
-
- if (strcmp (applet, "shell_var") == 0)
- exit (do_shell_var (argc, argv));
-
- if (strcmp (applet, "rc-abort") == 0) {
- char *p = getenv ("RC_PID");
- pid_t pid = 0;
-
- if (p && sscanf (p, "%d", &pid) == 1) {
- if (kill (pid, SIGUSR1) != 0)
- eerrorx ("rc-abort: failed to signal parent %d: %s",
- pid, strerror (errno));
- exit (EXIT_SUCCESS);
- }
- exit (EXIT_FAILURE);
- }
-
- if (strcmp (applet, "rc" ) != 0)
- eerrorx ("%s: unknown applet", applet);
+ /* Run our built in applets. If we ran one, we don't return. */
+ run_applets (argc, argv);
/* Change dir to / to ensure all scripts don't use stuff in pwd */
chdir ("/");