diff options
author | Roy Marples <roy@marples.name> | 2009-05-02 12:26:45 +0100 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2009-05-02 12:26:45 +0100 |
commit | 6615eb4b689d7aa1d047bd9ed75eca80beac9767 (patch) | |
tree | efc5a4dee97fd4737599f1f4f71bad7a8ba7f470 /src/rc | |
parent | e040bd77e983e609fea5a87549b58e81b96e4276 (diff) |
Add runlevel stacking, #88
This implementation has the limitation that you cannot have a stacked
runlevel and service of the same name in a runlevel.
Diffstat (limited to 'src/rc')
-rw-r--r-- | src/rc/rc-status.c | 24 | ||||
-rw-r--r-- | src/rc/rc-update.c | 83 | ||||
-rw-r--r-- | src/rc/rc.c | 2 |
3 files changed, 92 insertions, 17 deletions
diff --git a/src/rc/rc-status.c b/src/rc/rc-status.c index 4c6e5129..0a232777 100644 --- a/src/rc/rc-status.c +++ b/src/rc/rc-status.c @@ -78,8 +78,10 @@ _rc_can_find_pids(void) } static void -print_level(const char *level) +print_level(const char *prefix, const char *level) { + if (prefix) + printf("%s ", prefix); printf ("Runlevel: "); if (isatty(fileno(stdout))) printf("%s%s%s\n", @@ -274,16 +276,28 @@ rc_status(int argc, char **argv) deptree = _rc_deptree_load(0, NULL); TAILQ_FOREACH(l, levels, entries) { - print_level(l->value); + print_level(NULL, l->value); services = rc_services_in_runlevel(l->value); print_services(l->value, services); + nservices = rc_runlevel_stacks(l->value); + TAILQ_FOREACH(s, nservices, entries) { + if (rc_stringlist_find(levels, s->value) != NULL) + continue; + print_level("Stacked", s->value); + sservices = rc_services_in_runlevel(s->value); + print_services(s->value, sservices); + rc_stringlist_free(sservices); + } + sservices = NULL; + rc_stringlist_free(nservices); + nservices = NULL; rc_stringlist_free(services); services = NULL; } if (aflag || argc < 2) { /* Show hotplugged services */ - print_level("hotplugged"); + print_level("Dynamic", "hotplugged"); services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); print_services(NULL, services); rc_stringlist_free(services); @@ -336,9 +350,9 @@ rc_status(int argc, char **argv) rc_stringlist_free(tmp); } l->value = p; - print_level("needed"); + print_level("Dynamic", "needed"); print_services(NULL, nservices); - print_level("manual"); + print_level("Dynamic", "manual"); print_services(NULL, services); } diff --git a/src/rc/rc-update.c b/src/rc/rc-update.c index f37f6f02..46adc635 100644 --- a/src/rc/rc-update.c +++ b/src/rc/rc-update.c @@ -63,11 +63,11 @@ add(const char *runlevel, const char *service) eerror("%s: service `%s' does not exist", applet, service); } else if (rc_service_in_runlevel(service, runlevel)) { - ewarn ("%s: %s already installed in runlevel `%s'; skipping", + ewarn("%s: %s already installed in runlevel `%s'; skipping", applet, service, runlevel); retval = 0; } else if (rc_service_add(runlevel, service)) { - einfo ("%s added to runlevel %s", service, runlevel); + einfo("service %s added to runlevel %s", service, runlevel); retval = 1; } else eerror("%s: failed to add service `%s' to runlevel `%s': %s", @@ -83,20 +83,76 @@ delete(const char *runlevel, const char *service) errno = 0; if (rc_service_delete(runlevel, service)) { - einfo("%s removed from runlevel %s", service, runlevel); + einfo("service %s removed from runlevel %s", + service, runlevel); return 1; } if (errno == ENOENT) - eerror ("%s: service `%s' is not in the runlevel `%s'", + eerror("%s: service `%s' is not in the runlevel `%s'", applet, service, runlevel); else - eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", + eerror("%s: failed to remove service `%s' from runlevel `%s': %s", applet, service, runlevel, strerror (errno)); return retval; } +static int +addstack(const char *runlevel, const char *stack) +{ + if (!rc_runlevel_exists(runlevel)) { + eerror("%s: runlevel `%s' does not exist", applet, runlevel); + return -1; + } + if (!rc_runlevel_exists(stack)) { + eerror("%s: runlevel `%s' does not exist", applet, stack); + return -1; + } + if (strcmp(runlevel, stack) == 0) { + eerror("%s: cannot stack `%s' onto itself", applet, stack); + return -1; + } + if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 || + strcmp(stack, RC_LEVEL_SYSINIT) == 0 || + strcmp(runlevel, RC_LEVEL_BOOT) == 0 || + strcmp(stack, RC_LEVEL_BOOT) == 0 || + strcmp(runlevel, RC_LEVEL_SINGLE) == 0 || + strcmp(stack, RC_LEVEL_SINGLE) == 0 || + strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(stack, RC_LEVEL_SHUTDOWN) == 0) + { + eerror("%s: cannot stack the %s runlevel", + applet, RC_LEVEL_SYSINIT); + return -1; + } + if (!rc_runlevel_stack(runlevel, stack)) { + eerror("%s: failed to stack `%s' to `%s': %s", + applet, stack, runlevel, strerror(errno)); + return -1; + } + einfo("runlevel %s added to runlevel %s", stack, runlevel); + return 1; +} + +static int +delstack(const char *runlevel, const char *stack) +{ + if (rc_runlevel_unstack(runlevel, stack)) { + einfo("runlevel %s removed from runlevel %s", stack, runlevel); + return 1; + } + + if (errno == ENOENT) + eerror("%s: runlevel `%s' is not in the runlevel `%s'", + applet, stack, runlevel); + else + eerror("%s: failed to remove runlevel `%s' from runlevel `%s': %s", + applet, stack, runlevel, strerror (errno)); + + return -1; +} + static void show(RC_STRINGLIST *runlevels, bool verbose) { @@ -143,12 +199,14 @@ show(RC_STRINGLIST *runlevels, bool verbose) "Usage: rc-update [options] add service <runlevel>\n" \ " rc-update [options] del service <runlevel>\n" \ " rc-update [options] show" -#define getoptstring "u" getoptstring_COMMON +#define getoptstring "su" getoptstring_COMMON static const struct option longopts[] = { + { "stack", 0, NULL, 's' }, { "update", 0, NULL, 'u' }, longopts_COMMON }; static const char * const longopts_help[] = { + "Stack a runlevel instead of a service", "Force an update of the dependency tree", longopts_help_COMMON }; @@ -166,7 +224,7 @@ rc_update(int argc, char **argv) char *service = NULL; char *p; int action = 0; - bool verbose = false; + bool verbose = false, stack = false; int opt; int retval = EXIT_FAILURE; int num_updated = 0; @@ -176,11 +234,14 @@ rc_update(int argc, char **argv) while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *)0)) != -1) switch (opt) { + case 's': + stack = true; + break; case 'u': _rc_deptree_load(-1, &ret); return ret; - case_RC_COMMON_GETOPT - } + case_RC_COMMON_GETOPT; + } verbose = rc_yesno(getenv ("EINFO_VERBOSE")); @@ -241,9 +302,9 @@ rc_update(int argc, char **argv) eerror ("%s: no service specified", applet); else { if (action & DOADD) { - actfunc = add; + actfunc = stack ? addstack : add; } else if (action & DODELETE) { - actfunc = delete; + actfunc = stack ? delstack : delete; } else { rc_stringlist_free(runlevels); eerrorx("%s: invalid action", applet); diff --git a/src/rc/rc.c b/src/rc/rc.c index 78cfcae4..8e40e1d9 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -1037,7 +1037,7 @@ main(int argc, char **argv) /* Load our list of start services */ hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); - start_services = rc_services_in_runlevel(newlevel ? + start_services = rc_services_in_runlevel_stacked(newlevel ? newlevel : runlevel); if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) |