Skip to content

Commit

Permalink
librc: Add initial support for dynamically multiplexed services.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
navi-desu committed Sep 21, 2024
1 parent 6901121 commit 1665840
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/librc/librc-depend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
48 changes: 46 additions & 2 deletions src/librc/librc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -933,6 +939,32 @@ rc_service_state(const char *service)
return state;
}

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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/librc/rc.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 1665840

Please sign in to comment.