summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-05-05 20:28:28 -0400
committerMike Frysinger <vapier@gentoo.org>2012-05-06 01:17:30 -0400
commit2486eb4989918ff5ef645f2a17fedbec559b9485 (patch)
treead9f625e5ca51b5f71108c7eb444fe2f1a98956b
parent0813a80223e40a5d122dfa86ea41e7b1c986f093 (diff)
downloadopenrc-2486eb4989918ff5ef645f2a17fedbec559b9485.tar.gz
openrc-2486eb4989918ff5ef645f2a17fedbec559b9485.tar.bz2
openrc-2486eb4989918ff5ef645f2a17fedbec559b9485.tar.xz
rc: collapse the applet if statements into a single array walk
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--src/rc/rc-applets.c240
1 files changed, 133 insertions, 107 deletions
diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c
index 5d02682..21562f0 100644
--- a/src/rc/rc-applets.c
+++ b/src/rc/rc-applets.c
@@ -253,13 +253,38 @@ do_e(int argc, char **argv)
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 = 0;
+ int idx;
+ RC_SERVICE state, bit;
if (argc > 1)
service = argv[1];
@@ -269,21 +294,11 @@ do_service(int argc, char **argv)
if (service == NULL || *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_hotplugged") == 0)
- ok = (rc_service_state(service) & RC_SERVICE_HOTPLUGGED);
- else if (strcmp(applet, "service_wasinactive") == 0)
- ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
- else if (strcmp(applet, "service_started_daemon") == 0) {
+ state = rc_service_state(service);
+ bit = lookup_service_state(service);
+ if (bit) {
+ ok = (state & bit);
+ } else if (strcmp(applet, "service_started_daemon") == 0) {
service = getenv("RC_SVCNAME");
exec = argv[1];
if (argc > 3) {
@@ -317,6 +332,7 @@ do_mark_service(int argc, char **argv)
char *runscript_pid;
/* char *mtime; */
pid_t pid;
+ RC_SERVICE bit;
/* size_t l; */
if (argc > 1)
@@ -327,20 +343,9 @@ do_mark_service(int argc, char **argv)
if (service == NULL || *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_hotplugged") == 0)
- ok = rc_service_mark(service, RC_SERVICE_HOTPLUGGED);
- else if (strcmp(applet, "mark_service_failed") == 0)
- ok = rc_service_mark(service, RC_SERVICE_FAILED);
+ if (strncmp(applet, "mark_", 5) &&
+ (bit = lookup_service_state(applet + 5)))
+ ok = rc_service_mark(service, bit);
else
eerrorx("%s: unknown applet", applet);
@@ -409,7 +414,7 @@ do_value(int argc, char **argv)
}
static int
-do_shell_var(int argc, char **argv)
+shell_var(int argc, char **argv)
{
int i;
char *p;
@@ -430,106 +435,127 @@ do_shell_var(int argc, char **argv)
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),
+ { "rc-depend", rc_depend, },
+ { "rc-service", rc_service, },
+ { "rc-status", rc_status, },
+ { "rc-update", rc_update, },
+ { "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)
{
- int i = 2;
- char *p;
- pid_t pid = 0;
+ size_t i;
/* 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 && argc >= 3 &&
- (strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) {
+ (strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) {
applet = argv[2];
argv += 2;
argc -= 2;
}
- /* 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-service") == 0)
- exit(rc_service(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));
- else if (strcmp(applet, "swclock") == 0)
- exit(swclock(argc, argv));
-
- /* These could also be applications in their own right */
- if (strcmp(applet, "shell_var") == 0)
- exit(do_shell_var(argc, argv));
-
- /* This test is perverted - historically the baselayout function
- * returns 0 on *failure*, which is plain wrong */
- if (strcmp(applet, "is_older_than") == 0) {
- if (argc < 3)
- exit (EXIT_FAILURE);
- while (i < argc) {
- if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
- exit(EXIT_SUCCESS);
- }
- exit(EXIT_FAILURE);
- };
- /* This test is correct as it's not present in baselayout */
- if (strcmp(applet, "is_newer_than") == 0) {
- if (argc < 3)
- exit (EXIT_FAILURE);
- while (i < argc) {
- if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- };
+ 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));
- /* 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) {
- p = getenv("RC_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));
- exit(EXIT_SUCCESS);
- }
- exit(EXIT_FAILURE);
- }
-
if (strcmp(applet, "rc") != 0)
eerrorx("%s: unknown applet", applet);
}