Fix #186: allow continuation character in .conf files

This change makes it possible to use the standard continuation character
in .conf files.  For example:

    service [23456]     \
         log:stderr     \
         <!pid/foo>     \
         bar            \
         -- This is the bar service, it depends on foo # comment that's dropped

Notice the additional support for comments on .conf lines.  If you use
the comment character today you must change to escape it.  Like this:

    service :2 foo -- Foo \#2

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2022-11-19 10:11:11 +01:00
1 parent f217794773
commit 9046b6fe2b
7 files changed
+85 -30

No files matched your search

+19 -1
View File
@@ -4,6 +4,24 @@ Change Log
All relevant changes are documented in this file. All relevant changes are documented in this file.
[4.4][UNRELEASED]
-----------------
> **Note:** this release contains changes to the `.conf` parser. If you
> have .conf file statements with comment character (`#`) in the command
> options or description, you must now escape them (`\#`).
### Changes
* Support for line continuation character `\` in .conf files, issue #186
service name:sysklogd [S123456789] \
env:-/etc/default/sysklogd \
syslogd -F $SYSLOGD_ARGS \
-- System log daemon
### Fixes
[4.3][] - 2022-05-15 [4.3][] - 2022-05-15
-------------------- --------------------
@@ -1152,7 +1170,7 @@ Major bug fix release.
* Initial release * Initial release
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.2...HEAD [UNRELEASED]: https://github.com/troglobit/finit/compare/4.3...HEAD
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3 [4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2 [4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1 [4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
+6
View File
@@ -74,6 +74,12 @@ files in `/etc/finit.d`. Available, but not yet enabled, services can
be placed in `/etc/finit.d/available` and enabled by an operator using be placed in `/etc/finit.d/available` and enabled by an operator using
the [initctl](#commands--status) tool. the [initctl](#commands--status) tool.
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
> standard UNIX continuation character (`\`), also trailing comments are
> now supported. The latter means you need to escape any hashes used in
> directives and descriptions (`\#`). For more on this and examples,
> see the finit.conf(5) manual or [doc/config.md](doc/config.md).
```ApacheConf ```ApacheConf
# Fallback if /etc/hostname is missing # Fallback if /etc/hostname is missing
host default host default
+21 -2
View File
@@ -1,5 +1,5 @@
Configuration Finit Configuration
============= ===================
* [Introduction](#introduction) * [Introduction](#introduction)
* [Environment Variables](#environment-variables) * [Environment Variables](#environment-variables)
@@ -297,6 +297,25 @@ Linux kernel, or the name is misspelled.
Configuration File Syntax Configuration File Syntax
------------------------- -------------------------
The file format is line based, empty lines and comments, lines starting
with `#`, are ignored. A configuration directive starts with a keyword
followed by a space and the rest of the line is treated as the value.
As of Finit v4.4, configuration directives can be broken up in multiple
lines using the continuation character `\`, and trailing comments are
also allowed. Example:
```aconf
# Escape \# chars if you want them literal in, e.g., descriptions
service name:sysklogd [S123456789] \
env:-/etc/default/sysklogd \
syslogd -F $SYSLOGD_ARGS \
-- System log daemon \# 1 # Comments allowed now
```
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
following directives:
### Hostname ### Hostname
**Syntax:** `host <NAME>`, or `hostname <NAME>` **Syntax:** `host <NAME>`, or `hostname <NAME>`
+13 -6
View File
@@ -47,13 +47,20 @@ Available services
Enabled services, symlinks from available Enabled services, symlinks from available
.El .El
.Sh FILE FORMAT .Sh FILE FORMAT
Lines starting with `#' are ignored. Note that end-of-line comments are The file format is line based, empty lines and comments, lines starting
NOT supported, comments must be on a line of their own. with `#', are ignored. A configuration directive starts with a keyword
followed by a space and the rest of the line is treated as the value.
.Pp .Pp
A configuration stanza must be on a single (long) line and As of Finit v4.4, configuration directives can be broken up in multiple
.Em cannot lines using the continuation character `\\', and trailing comments are
be broken up in multiple lines by use of a backslash as the last also allowed. Example:
character. .Bd -unfilled -offset indent
# Escape \\# chars if you want them literal in, e.g., descriptions
service name:sysklogd [S123456789] \\
env:-/etc/default/sysklogd \\
syslogd -F $SYSLOGD_ARGS \\
-- System log daemon \\# 1 # Comments allowed now
.Ed
.Sh DIRECTIVES .Sh DIRECTIVES
This section lists all supported configuration directives. There also exist This section lists all supported configuration directives. There also exist
deprecated directives, see the Markdown documentation for details on these. deprecated directives, see the Markdown documentation for details on these.
+12 -14
View File
@@ -841,7 +841,6 @@ static int parse_dynamic(char *line, struct rlimit rlimit[], char *file)
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 line[LINE_SIZE] = "";
FILE *fp; FILE *fp;
fp = fopen(file, "r"); fp = fopen(file, "r");
@@ -856,26 +855,25 @@ static int parse_conf(char *file, int is_rcsd)
dbg("*** Parsing %s", file); dbg("*** Parsing %s", file);
while (!feof(fp)) { while (!feof(fp)) {
char *x; char *line;
if (!fgets(line, sizeof(line), fp)) line = fparseln(fp, NULL, NULL, NULL, FPARSELN_UNESCCOMM);
if (!line) {
warn("Reading %s", file);
continue; continue;
}
chomp(line);
tabstospaces(line); tabstospaces(line);
//DEV dbg("%s", line); dbg("%s", line);
/* Skip comments, i.e. lines beginning with # */
if (MATCH_CMD(line, "#", x))
continue;
if (!parse_static(line, is_rcsd)) if (!parse_static(line, is_rcsd))
continue; ;
if (!parse_dynamic(line, is_rcsd ? rlimit : global_rlimit, file)) else if (!parse_dynamic(line, is_rcsd ? rlimit : global_rlimit, file))
continue; ;
else
parse_env(line);
/* Not static or dynamic conf, check if it is a global env. */ free(line);
parse_env(line);
} }
fclose(fp); fclose(fp);
+3 -3
View File
@@ -37,9 +37,9 @@ test_add_one()
test_init test_init
test_add_one "task manual:yes name:foo :1 serv -- Foo #1" test_add_one "task manual:yes name:foo :1 serv -- Foo \#1"
test_add_one "task manual:yes name:foo :2 serv -- Foo #2" test_add_one "task manual:yes name:foo :2 serv -- Foo \#2"
test_add_one "task manual:yes name:foo :3 serv -- Foo #3" test_add_one "task manual:yes name:foo :3 serv -- Foo \#3"
test_add_one "task manual:yes name:foobar serv -- Foobar" test_add_one "task manual:yes name:foobar serv -- Foobar"
say 'Reload Finit' say 'Reload Finit'
+11 -4
View File
@@ -19,16 +19,23 @@ test_teardown()
say "Test start $(date)" say "Test start $(date)"
say 'Ensure file system is cleared' say 'Ensure file system is cleared'
texec rm -f /tmp/usr1.log run "rm -f /tmp/usr1.log"
# Verifies line continuation as well
say "Add service stanza in $FINIT_CONF" say "Add service stanza in $FINIT_CONF"
texec sh -c "echo 'service [2345] kill:20 log service.sh -- Test service' > $FINIT_CONF" run "echo 'service [2345] kill:20 \\
log service.sh \\
-- Test service' > $FINIT_CONF"
run "cat $FINIT_CONF"
#run "initctl debug"
say 'Reload Finit' say 'Reload Finit'
texec sh -c "initctl reload" run "initctl reload"
#run "initctl status service.sh"
say 'Send SIGUSR1 to service...' say 'Send SIGUSR1 to service...'
texec sh -c "initctl signal service.sh SIGUSR1" run "initctl signal service.sh SIGUSR1"
# shellcheck disable=SC2016 # shellcheck disable=SC2016
retry 'assert "service.sh received SIGUSR" "$(texec cat /tmp/usr1.log)" = "USR1"' 10 1 retry 'assert "service.sh received SIGUSR" "$(texec cat /tmp/usr1.log)" = "USR1"' 10 1