summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-09-21 02:06:56 +0200
committerAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-09-21 17:44:20 +0200
commit1665840dd64cf5c1c2f44bbbe82794aa3b1b5577 (patch)
treebc75b233b2b2fc0d0af63edfecd3b2f3c0274485
parent69011211757ad63c29a24442664d0c46bb9cc01e (diff)
librc: Add initial support for dynamically multiplexed services.origin/dynamic-multiplex
Generate a new directory on the service dir, "multiplexed", which will hold all the symlinks we generate at runtime, and a new librc function, "rc_service_multiplex", which takes a basename or service path, and a variant name, then generated a symlink to the base service from the multiplex dir. This allows multiplexing services at runtime, possibly using data acquired at runtime, such as the name of an user or interface.
-rw-r--r--src/librc/librc-depend.c1
-rw-r--r--src/librc/librc.c48
-rw-r--r--src/librc/rc.h.in5
3 files changed, 52 insertions, 2 deletions
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
index a48a2ada..8f569ae5 100644
--- a/src/librc/librc-depend.c
+++ b/src/librc/librc-depend.c
@@ -697,6 +697,7 @@ static const char *const depdirs[] =
RC_SVCDIR "/wasinactive",
RC_SVCDIR "/failed",
RC_SVCDIR "/hotplugged",
+ RC_SVCDIR "/multiplexed",
RC_SVCDIR "/daemons",
RC_SVCDIR "/options",
RC_SVCDIR "/exclusive",
diff --git a/src/librc/librc.c b/src/librc/librc.c
index b5449641..0d114214 100644
--- a/src/librc/librc.c
+++ b/src/librc/librc.c
@@ -636,6 +636,12 @@ rc_service_resolve(const char *service)
return file;
#endif
+ /* Check dynamically multiplexed services last */
+ free(file);
+ xasprintf(&file, "%s/multiplexed/%s", RC_SVCDIR, service);
+ if (stat(file, &buf) == 0)
+ return file;
+
free(file);
return NULL;
}
@@ -934,6 +940,32 @@ rc_service_state(const char *service)
}
char *
+rc_service_multiplex(const char *base, const char *variant)
+{
+ char *service = rc_service_resolve(base);
+ char *target;
+ char *name;
+
+ if (!service)
+ return NULL;
+
+ if (base[0] == '/')
+ base = basename_c(base);
+
+ xasprintf(&name, "%s.%s", base, variant);
+
+ xasprintf(&target, "%s/multiplexed/%s", RC_SVCDIR, name);
+ if (!exists(target) && symlink(service, target) == -1) {
+ free(target);
+ target = NULL;
+ }
+
+ free(name);
+ free(service);
+ return target;
+}
+
+char *
rc_service_value_get(const char *service, const char *option)
{
char *buffer = NULL;
@@ -1119,6 +1151,8 @@ rc_service_add(const char *runlevel, const char *service)
char *path;
char *binit = NULL;
char *i;
+ char *multiplex_dir;
+ int len;
if (!rc_runlevel_exists(runlevel)) {
errno = ENOENT;
@@ -1151,10 +1185,20 @@ rc_service_add(const char *runlevel, const char *service)
i = binit;
}
- xasprintf(&file, "%s/%s/%s", RC_RUNLEVELDIR, runlevel,
- basename_c(service));
+ /* We shouldn't add any dynamically multiplexed service to a runlevel */
+ len = xasprintf(&multiplex_dir, "%s/multiplexed", RC_SVCDIR);
+ if (strncmp(i, multiplex_dir, len) == 0) {
+ errno = ENOENT;
+ retval = false;
+ goto out;
+ }
+
+ xasprintf(&file, "%s/%s/%s", RC_RUNLEVELDIR, runlevel, basename_c(service));
retval = (symlink(i, file) == 0);
free(file);
+
+out:
+ free(multiplex_dir);
free(binit);
free(init);
return retval;
diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in
index d90943b6..4fdd3ef3 100644
--- a/src/librc/rc.h.in
+++ b/src/librc/rc.h.in
@@ -267,6 +267,11 @@ bool rc_service_schedule_clear(const char *);
* @return state of the service */
RC_SERVICE rc_service_state(const char *);
+/*! Dynamically multiplexes a base service into a variant as basename.variant
+ * @param basename or full path of service being multiplexed
+ * @param variant to dynamically multiplex */
+char *rc_service_multiplex(const char *, const char *);
+
/*! Check if the service started the daemon
* @param service to check
* @param exec to check