conf: instantiate %i templates for the block format

A template in the block format registered garbage.  conf_parse_file()
routed every file with an '@' in its name straight to the legacy
parser, which read the block line by line: the section header became a
service whose command was the section title, and each key = value line
below it became an environment variable.

    service serv:%i { ... }   ->  service 'serv:eth0' with argument '{'

Substitute %i over the whole file before parsing instead, so format
detection and both parsers see finished text.  A bare name@.conf is
still skipped, it is the template rather than an instance of one.

The legacy parser no longer opens the file or substitutes per line, it
is handed the instantiated buffer, so the template convention now has
one implementation instead of two.  conf_is_template() applies
basenm(), a directory with an '@' in its name is not a template.

libconfuse cannot name a buffer it parses before 3.4, so a typo in a
template would be reported against "[buf]".  Parse through fmemopen()
with the file name preset until the floor moves.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2026-07-30 15:21:26 +02:00
1 parent 47a18140c1
commit f1393ff8a1
7 files changed
+269 -94

No files matched your search

+8 -71
View File
@@ -319,79 +319,19 @@ static int parse_dynamic(char *line, struct rlimit rlimit[], char *file)
}
/*
* Very simple and crude implementation, only supports '%i'
* Parse FILE, or BUF when the frontend has already read and
* instantiated it, i.e. for a template. Either way the text arriving
* here is final, no %i is left to substitute.
*/
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 */
}
int legacy_parse_conf(char *file, int is_rcsd)
int legacy_parse_conf(char *file, char *buf, int is_rcsd)
{
struct rlimit rlimit[RLIMIT_NLIMITS];
char name[65] = { 0 };
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");
if (buf)
fp = fmemopen(buf, strlen(buf), "r");
else
fp = fopen(file, "r");
if (!fp)
return 1;
@@ -410,9 +350,6 @@ int legacy_parse_conf(char *file, int is_rcsd)
continue;
tabstospaces(line);
// dbg("raw: %s", line);
line = instantiate(line, name);
// dbg("ins: %s", line);
if (!parse_static(line, is_rcsd))
;