The if: statement, introduced in v4.4, allows for discarding run/task/services
that depend on other services, based on that service's name, or condition.
Discarding in this context means unloading from the configuration.
At runtime, however, it has proven quite useful to be able to conditionally
qualify a run/task/service based on a condition. Consider this example from
the Infix operating system:
run name:startup log:prio:user.notice \
[S] <pid/sysrepo> confd -b --load startup-config -- Loading startup-config
run name:failure log:prio:user.critical if:<usr/fail-startup> \
[S] <pid/sysrepo> confd --load failure-config -- Loading failure-config
The two run statements reside in the same .conf file so Finit runs them in true
sequence. If loading the file `startup-config` fails confd sets the condition
usr/fail-startup, thus allowing the next run statement to load `failure-config`.
Notice the difference between <pid/sysrepo> condition and if:<usr/fail-startup>.
The former is a condition for starting and the latter is a condition to check if
a run/task/service is qualified to even be considerered. The best comparison is
with the [runlevel] option, it too is used to qualify.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Due to an old design decision runlevel S was encoded internally as '0',
meaning it was the same as halt/poweroff. If you want to run scripts at
system shutdown this was less then ideal since it meant your scripts
also ran at bootstrap.
This change is quite invasive. It introduces INIT_LEVEL (10) as the
value for runlevel S, meaning all code that parses and/or evaluates
anything for runlevel 0/S was affected and had to be reworked.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Post audit, concensus is to drop if: and always do post-eval of all
ifdef: statements. Also, rename ifdef: to if: for completeness.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Conditional loading of stanza depending on ident is already loaded. The
if: checks as in-band while ifdef: checks out-of-band, i.e., post eval.
The optional leading '!' negates the comparison, if NOT foo then ...
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In some conditions, typically when the same command is used for multiple
services, e.g. the modules-load plugin, the svc_find() function returned
an existing "similar" entry instead of NULL, causing loss of config.
When creating, and searching for, a run/task/service we must follow the
new name:id paradigm to the letter. Always create based on name:id and
always search for matching name:id. The name may be derived from the
command, but they cannot be used interchangably.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Drop the config.h include from helpers.h after a report from a colleague
trying to build an external plugin from the latest GIT sources.
Instead, make sure config.h is included, and properly commented, in all
.c files that have configure #ifdefs and other deps. Also, move more
ot the includes from helpers.h to their respective .c file instead to
reduce the amount of headers an external plugin pulls in.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When a SysV init script starts a daemon, Finit knows nothing of the PID
it should monitor. The PID is written, by start-stop-daemon or the
daemon itself, to the PID file. Finit monitors for new PID files and
can match the PID in such files with an svc_t.
For the regular use-case, we prefer first looking up the matching svc_t
based on the PID -- assuming we start and monitor the service. As a
fallback we resort to mathching the svc_t's declared PID file with the
new file we just discovered.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The implementation looks up the named service by using
`svc_parse_jobstr`. The callbacks for `svc_parse_jobstr` has been
augmented to accept a user data parameter. For this use case,
a carrier for the actual signal was needed. The address of the
signal parameter is taken and passed on as a `void *`. The
callback then simply deferences it as an int - the signal number.
Due to an unfortunate name clash with the DirectFB project LiTE, the
libite (-lite) project had to change its header namespace from
lite/*.h -> libite/*.h
This patch adds support for the new namepace in Finit, triggered by the
define _LIBITE_LITE, from the .pc file read by pkg-config. This should
only be needed on systems that install libite without the compatibility
symlink lite -> libite/ in the staging include directory.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Drop vhangup(), how did things ever work *with* this in?!
- setsid() + TIOCSCTTY are best buds, see notty code
- Allow storing any non-NULL string as tty->dev, expand in service_register()
- Reorder parse_cmdline_args(), we need to expand @console to current dev
- Fix tty arg parser, swapparoo for external getty
- Refactor tty_atcon(), iterated over by service_register()
- New arg format, need to translate for old run_getty2()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch re-enables the fallback shell handling after the big TTY
refactor. We do this by allowing the fallback shell to run as a
regular service.
Note: this also adds the "hidden" support for 'notty' option for
tty configurations stanzas. This is just to pick up from
where the kernel left us, reusing stdin + stdout.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Initial refactor of the tty implementation to use the service/run/task
general backend. This enables all the features of services also for
ttys, except logging because it makes no sense.
Work in progress:
- plugins/tty.c does not work anymore, could possibly be removed in
favor of usinga (a new) condition instead (if-tty-exists)
- fallback tty does not work anymore, should we remove it, or can we
handle it as an optional built-in with (a new) condition?
- @console does not work anymore, needs to generate N cloned services
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
By keeping track of when a full restart is needed, Finit can relieve
the user of having to track modifications to service configuration. This
also makes initctl reload easier to explain and reason about as the effect
of a reload should now be that any configuration updates to services will
be fully "commited" by initctl reload.
Signed-off-by: Jacques de Laval <Jacques.De.Laval@westermo.com>
Sneaky bug, when switching between different sets of configurations, a
new instance of a previously removed svc can have its condition removed
by svc_gc() of the old instance. This patch prevents such accidents.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Having removal status stored in the dirty status resulted in removal
status being forgotten when a service was marked as dirty, for instance
when a dependency was updated. This side effect of marke_dirty seems a bit
unexpected and instead of adding exceptions to the logic for when marking
a service dirty - let's separate the two things (dirty and removed) from each
other.
Signed-off-by: Jacques de Laval <Jacques.De.Laval@westermo.com>
The strlen() function can easiliy go out of bounds. Use memchr()
instead, we have the max buffer len as argument anyway.
Also fix call to sanitize() which used wrong length.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Services that create their own PID files usually don't declare one with
Finit. This patch adds support to track those PID files anywayt at
runtime for the purpose of identifying match svc_t when a PID file is
removed, i.e. when a service exits.
- On IN_CREATE the pidfile.so plugin saves the pid file name in svc_t
- On ON_DELETE the pidfile.so plugin finds svc_t based on pid file
Quicker tracking and less dead code, win-win.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When we try to start a service/run/task we call whichp() to see if the
binary exists, either tha absolute path given in the .conf file, or in
the $PATH we run with. If binary, or the env: file, doesn't exist we
now set svc_missing() state.
On `initctl reload` we unblock the service to be able to check again.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch fixes a few really hard problems wrt PID files:
1. Listening for IN_CREATE events means we get notified immediately by
the kernel when someone calls open()/fopen() on a PID file. Reading
the contents returns 0, thank you atoi() ... so we drop IN_CREATE
and instead look for IN_CLOSE_WRITE, there fixed it! Not quite ...
2. Some programs, like Zebra, and other Quagga/Frr daemons, don't
close() their PID files after creation. Instead they ftruncate()
and keep them open, and locked. Presumably to get a mechanism to
detect already running instances -- messes life up a bit for the
rest of us though. So we need to read files after IN_MODIFY too.
3. We also want to track IN_DELETE so we can deassert conditions when
services exit gracefully and clean up their PID files
The rest fo the commit is debug instrumentation changes.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
With the redesign from <svc/path/to/pidfile> to <pid/name:id> in d1fac6f
we moved to matching svc_t only against their PID, which could pop up in
any *.pid or */pid in /var/run. This patch drops the (hopefully) last
remnants of the old <svc/> legacy.
To ensure we don't try reading the PID value from socket files, like
/var/run/initctl, we add simple fnmatch() of the inotified file. Two
calls to fnmatch(), for portability reasons, not every system has GNU
libc extensions like FNM_EXTMATCH.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch removes the built-in inetd support from Finit. We recommend
using an external inetd instead, e.g. xinetd.
If you liked the feature set our inetd provided; filtering per interface
and port redirection, then please let us know or use the code in this
patch (MIT licensed) to recreate it. We are open to reintroducing it,
but then as a stand-alone daemon like the bundled watchdogd and getty.
So long for now, old friend.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The svc_find_by_pidfile() function is called async from the pidfile
plugin, so by the time the queue is processed the origin may have
moved or been removed even. Safe to ignore.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This patch makes the ':ID' field optional when registering non-inetd
run/taks/service etc. It has always been optional in the .conf files,
but internally we defaulted to ':1'.
To open up for more useful conditions we now default to zero/NULL :ID,
meaning the user now *must* keep track of the :ID field if they have
multiple services with the same name. This should already have been
an issue since such services would likely have conflicted with their
PID files (same name). So it's unlikely to affect any user severely.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>