summaryrefslogtreecommitdiff
path: root/src/librc
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
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')
-rw-r--r--src/librc/librc.c70
-rw-r--r--src/librc/librc.h4
-rw-r--r--src/librc/rc.h.in21
-rw-r--r--src/librc/rc.map4
4 files changed, 97 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;
diff --git a/src/librc/librc.h b/src/librc/librc.h
index ba7da31..d2501c0 100644
--- a/src/librc/librc.h
+++ b/src/librc/librc.h
@@ -91,8 +91,11 @@ librc_hidden_proto(rc_runlevel_exists)
librc_hidden_proto(rc_runlevel_get)
librc_hidden_proto(rc_runlevel_list)
librc_hidden_proto(rc_runlevel_set)
+librc_hidden_proto(rc_runlevel_stack)
+librc_hidden_proto(rc_runlevel_stacks)
librc_hidden_proto(rc_runlevel_starting)
librc_hidden_proto(rc_runlevel_stopping)
+librc_hidden_proto(rc_runlevel_unstack)
librc_hidden_proto(rc_service_add)
librc_hidden_proto(rc_service_daemons_crashed)
librc_hidden_proto(rc_service_daemon_set)
@@ -106,6 +109,7 @@ librc_hidden_proto(rc_service_resolve)
librc_hidden_proto(rc_service_schedule_clear)
librc_hidden_proto(rc_service_schedule_start)
librc_hidden_proto(rc_services_in_runlevel)
+librc_hidden_proto(rc_services_in_runlevel_stacked)
librc_hidden_proto(rc_services_in_state)
librc_hidden_proto(rc_services_scheduled)
librc_hidden_proto(rc_services_scheduled_by)
diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in
index 8287415..cb5258c 100644
--- a/src/librc/rc.h.in
+++ b/src/librc/rc.h.in
@@ -80,6 +80,22 @@ char *rc_runlevel_get(void);
* @return true if the runlevel exists, otherwise false */
bool rc_runlevel_exists(const char *);
+/*! Stack a runlevel onto another
+ * @param runlevel to stack onto
+ * @param runlevel being stacked
+ * @return true if successful, otherwise false */
+bool rc_runlevel_stack(const char *, const char *);
+
+/*! Unstack a runlevel from another
+ * @param runlevel to unstack from
+ * @param runlevel being unstacked
+ * @return true if successful, otherwise false */
+bool rc_runlevel_unstack(const char *, const char *);
+
+/*! Return a NULL terminated list of runlevel stacks in the runlevels
+ * @return a NULL terminated list of runlevels */
+RC_STRINGLIST *rc_runlevel_stacks(const char *);
+
/*! Return a NULL terminated list of runlevels
* @return a NULL terminated list of runlevels */
RC_STRINGLIST *rc_runlevel_list(void);
@@ -225,6 +241,11 @@ bool rc_service_value_set(const char *, const char *, const char *);
* @return NULL terminated list of services */
RC_STRINGLIST *rc_services_in_runlevel(const char *);
+/*! List the stacked services in a runlevel
+ * @param runlevel to list
+ * @return NULL terminated list of services */
+RC_STRINGLIST *rc_services_in_runlevel_stacked(const char *);
+
/*! List the services in a state
* @param state to list
* @return NULL terminated list of services */
diff --git a/src/librc/rc.map b/src/librc/rc.map
index e9fed69..7cfbfab 100644
--- a/src/librc/rc.map
+++ b/src/librc/rc.map
@@ -18,8 +18,11 @@ global:
rc_runlevel_get;
rc_runlevel_list;
rc_runlevel_set;
+ rc_runlevel_stack;
+ rc_runlevel_stacks;
rc_runlevel_starting;
rc_runlevel_stopping;
+ rc_runlevel_unstack;
rc_service_add;
rc_service_daemons_crashed;
rc_service_daemon_set;
@@ -34,6 +37,7 @@ global:
rc_service_schedule_clear;
rc_service_schedule_start;
rc_services_in_runlevel;
+ rc_services_in_runlevel_stacked;
rc_services_in_state;
rc_services_scheduled;
rc_services_scheduled_by;