summaryrefslogtreecommitdiff
path: root/src/librc/librc.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2009-05-02 12:26:45 +0100
committerRoy Marples <roy@marples.name>2009-05-02 12:26:45 +0100
commit6615eb4b689d7aa1d047bd9ed75eca80beac9767 (patch)
treeefc5a4dee97fd4737599f1f4f71bad7a8ba7f470 /src/librc/librc.c
parente040bd77e983e609fea5a87549b58e81b96e4276 (diff)
downloadopenrc-6615eb4b689d7aa1d047bd9ed75eca80beac9767.tar.gz
openrc-6615eb4b689d7aa1d047bd9ed75eca80beac9767.tar.bz2
openrc-6615eb4b689d7aa1d047bd9ed75eca80beac9767.tar.xz
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/librc/librc.c')
-rw-r--r--src/librc/librc.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/src/librc/librc.c b/src/librc/librc.c
index 05c1c3d..f73936d 100644
--- a/src/librc/librc.c
+++ b/src/librc/librc.c
@@ -66,7 +66,7 @@ static const rc_service_state_name_t rc_service_state_names[] = {
};
#define LS_INITD 0x01
-#define LS_DIR 0x02
+#define LS_DIR 0x02
static RC_STRINGLIST *
ls_dir(const char *dir, int options)
{
@@ -102,7 +102,7 @@ ls_dir(const char *dir, int options)
}
if (options & LS_DIR) {
if (stat(d->d_name, &buf) == 0 &&
- ! S_ISDIR(buf.st_mode))
+ !S_ISDIR(buf.st_mode))
continue;
}
rc_stringlist_add(list, d->d_name);
@@ -330,6 +330,51 @@ rc_runlevel_exists(const char *runlevel)
}
librc_hidden_def(rc_runlevel_exists)
+bool
+rc_runlevel_stack(const char *dst, const char *src)
+{
+ char d[PATH_MAX], s[PATH_MAX];
+
+ if (!rc_runlevel_exists(dst) || !rc_runlevel_exists(src))
+ return false;
+ snprintf(s, sizeof(s), "../%s", src);
+ snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
+ return (symlink(s, d) == 0 ? true : false);
+}
+librc_hidden_def(rc_runlevel_stack)
+
+bool
+rc_runlevel_unstack(const char *dst, const char *src)
+{
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
+ return (unlink(path) == 0 ? true : false);
+}
+librc_hidden_def(rc_runlevel_unstack)
+
+RC_STRINGLIST *
+rc_runlevel_stacks(const char *runlevel)
+{
+ char path[PATH_MAX];
+ RC_STRINGLIST *dirs;
+ RC_STRING *d, *dn;
+
+ if (!runlevel)
+ return false;
+ snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
+ dirs = ls_dir(path, LS_DIR);
+ TAILQ_FOREACH_SAFE(d, dirs, entries, dn) {
+ if (!rc_runlevel_exists(d->value)) {
+ TAILQ_REMOVE(dirs, d, entries);
+ free(d->value);
+ free(d);
+ }
+ }
+ return dirs;
+}
+librc_hidden_def(rc_runlevel_stacks)
+
/* Resolve a service name to it's full path */
char *
rc_service_resolve(const char *service)
@@ -781,6 +826,27 @@ rc_services_in_runlevel(const char *runlevel)
librc_hidden_def(rc_services_in_runlevel)
RC_STRINGLIST *
+rc_services_in_runlevel_stacked(const char *runlevel)
+{
+ RC_STRINGLIST *list, *stacks, *sl;
+ RC_STRING *stack;
+
+ list = rc_services_in_runlevel(runlevel);
+ stacks = rc_runlevel_stacks(runlevel);
+ TAILQ_FOREACH (stack, stacks, entries) {
+ sl = rc_services_in_runlevel(stack->value);
+ if (list != NULL) {
+ TAILQ_CONCAT(list, sl, entries);
+ free(sl);
+ } else
+ list = sl;
+ }
+ return list;
+}
+librc_hidden_def(rc_services_in_runlevel_stacked)
+
+
+RC_STRINGLIST *
rc_services_in_state(RC_SERVICE state)
{
RC_STRINGLIST *services;