Initial support for templating and instantiating services

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2023-04-24 20:14:30 +02:00
1 parent 334d4a708a
commit 700c32fd73
5 files changed
+137 -11

No files matched your search

+1
View File
@@ -41,6 +41,7 @@ Features include:
startup, support for systemd [sd_notify()][], or [s6 style][] too startup, support for systemd [sd_notify()][], or [s6 style][] too
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes) * Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
* Pre/Post script actions * Pre/Post script actions
* Rudimentary [templating support](doc/config.md#templating)
* Tooling to enable/disable services * Tooling to enable/disable services
* Built-in getty * Built-in getty
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html) * Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
+21
View File
@@ -9,6 +9,7 @@ Finit Configuration
* [Service Environment](#service-environment) * [Service Environment](#service-environment)
* [Service Synchronization](#service-synchronization) * [Service Synchronization](#service-synchronization)
* [Service Wrapper Scripts](#service-wrapper-scripts) * [Service Wrapper Scripts](#service-wrapper-scripts)
* [Templating](#templating)
* [Cgroups](#cgroups) * [Cgroups](#cgroups)
* [Configuration File Syntax](#configuration-file-syntax) * [Configuration File Syntax](#configuration-file-syntax)
* [Hostname](#hostname) * [Hostname](#hostname)
@@ -353,6 +354,26 @@ example employs a wrapper script in `/etc/start.d`.
> instead of sending SIGHUP at restart/reload events. > instead of sending SIGHUP at restart/reload events.
Templating
----------
Finit comes with rudimentary support for templating, similar to that of
systemd. Best illustrated with an example:
$ initctl show avahi-autoipd@
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
To enable ZeroConf for, e.g., eth0, use
$ initctl enable avahi-autoipd@eth0.conf
The enabled symlink will be set up to avahi-autoipd@.conf and every in‐
stance of %i will in the instantiated directive be replaced with eth0.
Inspect the result with:
$ initctl status avahi-autoipd:eth0
Cgroups Cgroups
------- -------
+28 -2
View File
@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps .\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1) .\" other parameters are allowed: see man(7), man(1)
.Dd Apr 22, 2023 .Dd Apr 24, 2023
.Dt FINIT.CONF 5 SMM .Dt FINIT.CONF 5 SMM
.Os Linux .Os Linux
.Sh NAME .Sh NAME
@@ -325,9 +325,10 @@ service notify:s6 mdevd -C -O 4 -D %n
When a service is ready, either by Finit detecting its PID file, or When a service is ready, either by Finit detecting its PID file, or
their respective readiness mechanism has been triggered, Finit creates their respective readiness mechanism has been triggered, Finit creates
then service's ready condition which other services can depend on: then service's ready condition which other services can depend on:
.Bd -unfilled -offset indent
$ initctl -v cond get service/mdevd/ready $ initctl -v cond get service/mdevd/ready
on on
.Ed
.El .El
.Pp .Pp
If a service should not be automatically started, it can be configured If a service should not be automatically started, it can be configured
@@ -818,6 +819,31 @@ the example sets
to denote that it doesn't support SIGHUP. That way Finit will to denote that it doesn't support SIGHUP. That way Finit will
stop/start the service instead of sending SIGHUP at restart/reload stop/start the service instead of sending SIGHUP at restart/reload
events. events.
.Sh TEMPLATING
Finit comes with rudimentary support for templating, similar to that of
systemd. Best illustrated with an example:
.Bd -unfilled -offset indent
$ initctl show avahi-autoipd@
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
.Ed
.Pp
To enable ZeroConf for, e.g.,
.Cm eth0 ,
use
.Bd -unfilled -offset indent
$ initctl enable avahi-autoipd@eth0.conf
.Ed
.Pp
The enabled symlink will be set up to
.Cm avahi-autoipd@.conf
and every instance of
.Cm %i
will in the instantiated directive be replaced with
.Cm eth0 .
Inspect the result with:
.Bd -unfilled -offset indent
$ initctl status avahi-autoipd:eth0
.Ed
.Sh CGROUPS .Sh CGROUPS
There are three major cgroup configuration directives: There are three major cgroup configuration directives:
.Pp .Pp
+71 -1
View File
@@ -914,11 +914,79 @@ static int parse_dynamic(char *line, struct rlimit rlimit[], char *file)
return 1; return 1;
} }
/*
* Very simple and crude implementation, only supports '%i'
*/
static char *instantiate(char *line, char *name)
{
char *ptr, *end = strchr(line, 0);
char *pos = line;
size_t num = 0;
if (!name[0] || !end)
return line;
while ((ptr = strchr(pos, '%'))) {
num++;
pos++;
}
ptr = realloc(line, strlen(line) + num * strlen(name) + 1);
if (!ptr)
return line;
pos = line = ptr;
while ((ptr = strchr(pos, '%'))) {
if (!strncmp(ptr, "%i", 2)) {
char *rest = &ptr[2];
char *next = ptr + strlen(name);
memmove(next, rest, strlen(rest) + 1);
memcpy(ptr, name, strlen(name));
pos += strlen(name);
} else
pos++;
}
return line;
}
static int is_template(const char *file, char *name, size_t len)
{
char *ptr, *nm;
size_t i = 0;
ptr = strchr(file, '@');
if (!ptr)
return 0; /* not a template */
nm = ptr + 1;
ptr = strstr(nm, ".conf");
if (!strcmp(nm, ".conf") || !ptr)
return 1; /* template itself or invalid */
while (nm < ptr && i < len - 1)
name[i++] = *nm++;
name[i] = 0;
return 1; /* instantiated template */
}
static int parse_conf(char *file, int is_rcsd) static int parse_conf(char *file, int is_rcsd)
{ {
struct rlimit rlimit[RLIMIT_NLIMITS]; struct rlimit rlimit[RLIMIT_NLIMITS];
char name[65] = { 0 };
FILE *fp; FILE *fp;
if (is_template(file, name, sizeof(name))) {
if (!name[0]) {
dbg("*** Skipping template file %s", file);
return 0;
}
dbg("*** instantiating %s from %s ...", name, file);
}
fp = fopen(file, "r"); fp = fopen(file, "r");
if (!fp) if (!fp)
return 1; return 1;
@@ -938,7 +1006,9 @@ static int parse_conf(char *file, int is_rcsd)
continue; continue;
tabstospaces(line); tabstospaces(line);
// dbg("%s", line); // dbg("raw: %s", line);
line = instantiate(line, name);
// dbg("ins: %s", line);
if (!parse_static(line, is_rcsd)) if (!parse_static(line, is_rcsd))
; ;
+16 -8
View File
@@ -253,18 +253,18 @@ static char *conf(char *path, size_t len, char *name, int creat)
int serv_enable(char *arg) int serv_enable(char *arg)
{ {
char src[strlen(arg) + 6];
size_t arglen, len; size_t arglen, len;
char corr[40]; char *ptr;
if (!arg || !arg[0]) { if (!arg || !arg[0]) {
WARNX("missing argument to enable, may be one of:"); WARNX("missing argument to enable, may be one of:");
return serv_list("available"); return serv_list("available");
} }
if (!strstr(arg, ".conf")) { strlcpy(src, arg, sizeof(src));
snprintf(corr, sizeof(corr), "%s.conf", arg); if (!strstr(src, ".conf"))
arg = corr; strlcat(src, ".conf", sizeof(src));
}
if (chdir(finit_rcsd)) if (chdir(finit_rcsd))
ERR(72, "failed cd %s", finit_rcsd); ERR(72, "failed cd %s", finit_rcsd);
@@ -272,13 +272,21 @@ int serv_enable(char *arg)
if (icreate && mkdir("enabled", 0755) && EEXIST != errno) if (icreate && mkdir("enabled", 0755) && EEXIST != errno)
ERR(73, "failed creating %s/enabled directory", finit_rcsd); ERR(73, "failed creating %s/enabled directory", finit_rcsd);
len = snprintf(NULL, 0, "%s/available/%s", finit_rcsd, arg); len = snprintf(NULL, 0, "%s/available/%s", finit_rcsd, src);
arglen = snprintf(NULL, 0, "%s/enabled/%s", finit_rcsd, arg); arglen = snprintf(NULL, 0, "%s/enabled/%s", finit_rcsd, arg);
char argpath[arglen + 1], path[len + 1]; char argpath[arglen + 1], path[len + 1];
snprintf(path, sizeof(path), "%s/available/%s", finit_rcsd, arg); snprintf(path, sizeof(path), "%s/available/%s", finit_rcsd, src);
/* check for template instatiation */
ptr = strchr(path, '@');
if (ptr++) {
*ptr = 0;
strlcat(path, ".conf", sizeof(path));
}
if (!fexist(path)) if (!fexist(path))
ERRX(72, "cannot find %s", path); ERRX(72, "cannot find %s%s", ptr ? "template ": "", path);
snprintf(argpath, sizeof(argpath), "%s/enabled/%s", finit_rcsd, arg); snprintf(argpath, sizeof(argpath), "%s/enabled/%s", finit_rcsd, arg);
if (fexist(argpath)) if (fexist(argpath))