diff options
| author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-09-21 02:06:56 +0200 |
|---|---|---|
| committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2024-09-21 17:44:20 +0200 |
| commit | 1665840dd64cf5c1c2f44bbbe82794aa3b1b5577 (patch) | |
| tree | bc75b233b2b2fc0d0af63edfecd3b2f3c0274485 | |
| parent | 69011211757ad63c29a24442664d0c46bb9cc01e (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.c | 1 | ||||
| -rw-r--r-- | src/librc/librc.c | 48 | ||||
| -rw-r--r-- | src/librc/rc.h.in | 5 |
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 |
