Compare commits

..
224 Commits
Author SHA1 Message Date
Joachim Wiberg e3bcf9bf16 Update ChangeLog and bump version for v4.11 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-27 10:28:39 +01:00
Joachim Wiberg 84fd3196b0 doc: clarify what is required for moving from runlevel S to 2
All run/tasks must complete before Finit moves to runlevel 2.  This
critical piece of information has mysteriously been missing from the
documentation since the start.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-27 10:23:11 +01:00
Joachim Wiberg 994e51e34f Convert **Note:** et al to GitHub Markdown alerts
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-27 10:23:10 +01:00
Joachim Wiberg 0a7814b391 Merge commit from fork
Improve argument handling when launching login
2025-03-27 07:00:54 +01:00
Joachim Wiberg 73f72b39cf Merge pull request #433 from aanderse/patch-1 2025-03-22 19:27:41 +01:00
Aaron Andersen 02e0aa7383 fixup: links in config.md 2025-03-22 18:06:05 +00:00
Joachim Wiberg 6528628b5c getty: improve argument handling when launching login
Add explicit argument separator before username to ensure correct
parsing of the login command regardless of username format.  This
follows best practices for command execution and prevents unexpected
behavior when processing special characters in usernames.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 13:18:10 +01:00
Joachim Wiberg 1480657982 Update ChangeLog, serious issues with stopping services
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 07:27:00 +01:00
Joachim Wiberg 33e378a345 Fix #432: allow services in 'setup' to be stopped
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 07:21:44 +01:00
Joachim Wiberg b695b46a9d Revert last part of 91a9c83, fallback SIGKILL when stopping services
When a service is stopped, but does not respond to the default SIGTERM,
a fallback kicks in after 3 seconds (default) to send SIGKILL.  Since
91a9c83 (v3.2-rc2) this has however not worked since the signal was
only sent to the process group.

It is the job of service_monitor(), when it reaps the process leader,
to forward the signal to the process group.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 07:18:16 +01:00
Joachim Wiberg 0e61ed727f Add helper function, svc_is_stopped() when stopped by user
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 07:17:37 +01:00
Joachim Wiberg e9d60a6c04 Minor, coding style
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-18 07:17:23 +01:00
Joachim Wiberg 5e9edf9deb Update ChangeLog and bump version for 4.11 release cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-17 18:43:04 +01:00
Joachim Wiberg 8ed2751ae1 Fix pre/post/ready/cleanup script execution if env:file is missing
Don't try to source an optional env:file if it is missing.  Otherwise
execution of pre/post/ready/cleanup script will fail.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-17 18:39:05 +01:00
Joachim Wiberg 7fec66dc09 Simplify, svc_checkenv() already checks if optional
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-17 18:38:31 +01:00
Joachim Wiberg 75fa868a4b Fix various typos found by codepsell
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-17 16:46:28 +01:00
Joachim Wiberg 7b321de339 Update ChangeLog and bump version for v4.10 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-03 03:46:21 +01:00
Joachim Wiberg 1691ebb292 logit(): RFC3164 conformance for /dev/kmsg fallback
RFC3164 section 5.3 states; "a colon and a space character usually
follow the TAG".  This is also the reference format in the kernel:
https://www.kernel.org/doc/Documentation/ABI/testing/dev-kmsg

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-03-03 03:39:55 +01:00
Joachim Wiberg c371c10455 Update ChangeLog and bump version for 4.10-rc2
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-28 12:11:06 +01:00
Joachim Wiberg a23e152f6b plugins: rtc: follow-up to bc8118d, stop timer at shutdown
Introduced to work-around systems with broken RTCs, it also introduced a
dormant bug in Finit, triggered at shutdown on some systems.  The call
to dlclose() removed the memory to the rtc_timer which libuev later then
referenced.

Fixes #429

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-28 11:17:01 +01:00
Joachim Wiberg 9210f2851e Skip killing initctl on shutdown/reboot
Initiating a shutdown/reboot from `initctl` should not cause `initctl`
to be killed in do_shutdown().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-25 08:37:27 +01:00
Joachim Wiberg 617609cbc5 .github: allow running coverity scan on workflow dispatch
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 12:35:48 +01:00
Joachim Wiberg b022916758 doc: update svc_t state machine, drop transparent background
The transparent png is completely illegible in dark mode.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 12:34:02 +01:00
Joachim Wiberg 9a357b7aab Fix possible NULL pointer dereference
When a user sets up a TTY without a device, triggering the tty->notty
code path, the tty->dev will be NULL and tty_parse_args() still return
OK result.

Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 10:30:16 +01:00
Joachim Wiberg ffd01b0276 Update ChangeLog and bump version for v4.10-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 05:43:14 +01:00
Joachim Wiberg 2c95f091ee Sync documentation and manual page
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 05:35:00 +01:00
Joachim Wiberg b75b107d6d plugins: urandom: improve entropy gathering in fallback path
Enhance fallback entropy generation by mixing in multiple sources:
runtime statistics, PID, and high-resolution timestamps.

This provides better initialization for the PRNG when neither saved
entropy nor hardware RNG are available during early boot.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:51:04 +01:00
Joachim Wiberg 1f2c1d2109 Minor, staticify
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:46:43 +01:00
Joachim Wiberg f328d24d01 Fix possible overflow in return value
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:29:56 +01:00
Joachim Wiberg 211293a83d Fix possible overflow in return value
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:28:26 +01:00
Joachim Wiberg 446f5bc8b8 Fix possible memory leak in sourcing of environment file
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:26:54 +01:00
Joachim Wiberg 0c6f748f2c Fix invalid pointer use in log message
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:23:22 +01:00
Joachim Wiberg a677b94ad9 Minor, coding style fixes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:05:55 +01:00
Joachim Wiberg 6552cda605 Fix #427: make sure first found binary is used as external getty
When using Finit with an external getty that supports alternative login
program argument, the tty_parse_args() function did not check if a getty
command had already been registered:

    tty [12345] /sbin/agetty -L -l /bin/login console noclear

This caused Finit to try /bin/login as the getty program.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 04:02:00 +01:00
Joachim Wiberg 3add682be3 Wait for post:script and cleanup:script before returning OK
This change introduces two new states for the big Finit state machine:
runlevel-clean and reload-clean.  Here Finit now waits for any post or
cleanup script to finish before returning OK to the initctl command.

Additionally, the service state machine has been updated to ensure a
run/task/sysv/service calls any post or cleanup script before they are
removed.  A new 'dead' state for svc_t is introduced which any removed
svc_t ends up in now instead of becing collected from 'halted' state.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>

Add cleanup:script support, runs at service removal

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 02:36:34 +01:00
Joachim Wiberg abac31682d Handle UEV_ERROR properly in all libuev callbacks
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 02:34:31 +01:00
Joachim Wiberg cfe915e6d5 Reclassify sysv, more like service than run/task
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-23 02:34:30 +01:00
Joachim Wiberg ecf65ce44b Merge pull request #428 from aanderse/path/sysctl 2025-02-21 04:27:14 +01:00
Aaron Andersen 0d742d6ae8 allow sysctl path to be configured at build time 2025-02-19 15:31:09 -05:00
Joachim Wiberg cf201a43df Add cleanup:script support, runs at service removal
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-17 05:16:28 +01:00
Joachim Wiberg 9245869e18 Update ChangeLog and bump version for v4.9 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-15 07:09:58 +01:00
Joachim Wiberg 0f4a487328 .github: tests share same sysroot, must run in sequence
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-14 10:28:16 +01:00
Joachim Wiberg f1b5b42919 test: enable debug logs for global-envs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-14 10:25:30 +01:00
Joachim Wiberg f546129baf test: debug sysvparts
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-14 10:25:30 +01:00
Joachim Wiberg 27451ac3f2 Update ChangeLog and bump version for v4.9-rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-14 06:26:27 +01:00
Joachim Wiberg 0a8f3a6250 Fix #425: flush .conf file events before reload and runlevel change
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-13 07:06:13 +01:00
Joachim Wiberg 70c4e7d774 iwatch: ensure adding a new watcher is idempotent
Some subsystems call iwatch_add() without first calling iwatch_del() on
the same path.  E.g., cgroup_config().

Issue #417 but unclear atm. if this is the root cause.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-13 05:53:24 +01:00
Joachim Wiberg 5265eee25d test: slightly more robust checkself.sh
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:35 +01:00
Joachim Wiberg 4b06e1a49f Silence overly verbose debug messages in cond_set/clear/update
These functions call other functions that log more detailed information.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:35 +01:00
Joachim Wiberg 6b9aa21509 Minor cleanup, code (style) and comments
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:35 +01:00
Joachim Wiberg 990307fbc9 Fix kill() on timeout of pre:/post:/ready:scripts
A long running pre/post/ready script must be killed properly, not by
targeting its process group.  Process group cleanup is handled by the
service_monitor() when reaping the script's PID.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:34 +01:00
Joachim Wiberg 9d8a9b7fba Check for pre:- and post:scripts in $PATH
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:34 +01:00
Joachim Wiberg bbc83eaa64 test: new test
New test adds /bin/fail.sh to verify that a failing pre:script (that
also takes too long to run) is detected: exit code and timeout.

Ensure existing test pass full path to /sbin/fail.sh script.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 10:17:33 +01:00
Joachim Wiberg 23d034f521 Prevent main process from starting if pre: script fails
Check exit status of `pre:` scripts, on failure drive service/sysv to
`crashed` state.  The exit code of `post:` scripts remain ignored for
now.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-11 09:39:40 +01:00
Joachim Wiberg 9a3148a49d Bump version to v4.9-beta1 and update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-10 10:43:38 +01:00
Joachim Wiberg 8560103a24 Add individual timeout support for pre/post/ready scripts
Syntax:
    [pre|post|ready]:[0-3600,]/path/to/script

Description:
    Before this patch all pre/post/ready scripts used the global kill
    delay as timeout.  After this patch it is possible to disable the
    timeout as well as set a timeout >60, which is max kill delay.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-10 10:43:37 +01:00
Joachim Wiberg 7a75e34808 Fix initctl touch of template services
Follow-up to 465bc17, which addressed unintended restart of siblings.
This patch fixes a problem where template instantiated services are not
properly reloaded/restarted when marked as "dirty" with `initctl touch`.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-10 10:43:37 +01:00
Joachim Wiberg 4d4fc10d57 plugins: rtc: follow-up to bc8118d
In save() RTC, ensure the RTC_FILE option is actually enabled.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-10 10:43:29 +01:00
Joachim Wiberg 003faae9e9 .github: disable apparmarmor to allow testing in unshare
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-03 10:23:45 +01:00
Joachim Wiberg 01a01d65c0 Merge pull request #424 from aanderse/container/systemd-nspawn
Add systemd-nspawn to the list of container types

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-02-03 07:13:33 +01:00
Aaron Andersen 048302f06a add systemd-nspawn to the list of container types 2025-02-02 08:58:36 -05:00
Joachim Wiberg 74f0fcfccd Merge pull request #422 from az143/fstab-nofail 2024-12-20 02:18:09 +01:00
az 3cfe0a33b8 fstab with UUID/LABEL: nofail handling for fsck
add support for 'nofail' fstab option. if present, finit's fsck invocation ignores errors for this device.

this is useful if you have an fstab entry for a device with UUID= or LABEL= which isn't always present and which you'd like to not
bail on (so you set nofail). in this case finit leaves the presence-or-not decision to fsck, which exits nonzero.

for block devices that are directly listed in fstab this change isn't important, because for such finit looks for the blockdev's existence and skips the fsck if n/a.
2024-12-20 09:09:24 +10:00
Joachim Wiberg 465bc17ca4 Fix unintended restart of template siblings
Consider the case where container@.conf is an available template.  When
creating a container@foo.conf it will share the same base .conf as an
existing container@bar.conf, but we do not expect to restart bar just
because foo is instantiated.

Up until this change, all template siblings were considered "dirty" if a
new one was created or updated.  Skipping realpath() for all files that
have a '@' works around the problem.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-28 11:13:44 +01:00
Joachim Wiberg d4889b435d Merge pull request #419 from troglobit/rtc
RTC plugin fixes and extension

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-04 10:48:26 +01:00
Joachim Wiberg 49c0557ced plugins: reduce log level LOG_ERR -> LOG_WARNING
These plugins signal success and failure directly to the console, the
user should inspect syslog for more information.

This change is a follow-up to 340cae4, where kernel logs of LOG_ERR and
higher are allowed to log directly to the console.  Since syslogd has
not been started before these plugins, the log messages would otherwise
leak to the console.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-04 10:42:45 +01:00
Joachim Wiberg 6be16f2f6d Fix buggy --with-rtc-date=DATE, introduced in Finit v4.4
In 42ef3d3c, for v4.4-rc1, support for setting a custom RTC restore date
was introduced.  Unfortunately the configure script was wrong and caused
config.h to contain

    #define RTC_TIMESTAMP_CUSTOM "$rtc_date"

instead of

    #define RTC_TIMESTAMP_CUSTOM "2023-04-10 14:35:42"

Furthermore, the error handling for strptime() was wrong, so the restore
date was always reverted to the default.

This patch fixes both issues and extends the DATE of --with-rtc-date to
also include seconds.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-04 10:42:45 +01:00
Joachim Wiberg bc8118d515 Fix #418: support systems with a broken RTC
This patch introduces a new configure option --with-rtc-file=FILE.  When
enabled the RTC plugin detects missing RTC device and falls back to save
and restore system time from a file instead.  When --with-rtc-file is
used without an argument the default file is /var/lib/misc/rtc, but the
feature itself is disabled by default.

The usefulness of this feature may not be obvious at first, but some
systems are equipped with an RTC that resets to a random date at power
on.  This can be really bad in the case the date is far in the future,
because an NTP sync would then cause time skips backwards, which shows
up in logs and causes a whole lot of pain in alarm systems.

The solution is to disable the RTC driver or device tree node, and when
Finit starts up, the RTC plugin detects a the device node and instead
restores time from the last save game.  Meaning time will always only
move forwards.

NOTE: when Finit is built --with-rtc-file we always save to disk, but
      only restore from the "save game" if restoring from RTC fails.
      If the system has no RTC we always restore from disk.

      As an added bonus, this change also makes sure to periodically
      sync also the RTC with the system clock.  Useful for systems
      that do not run an NTP client.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-04 10:40:35 +01:00
Joachim Wiberg 0c0e880f3f plugins: refactor rtc.so
Factor out time_set() and time_get() for readability and reuse.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-03 09:45:27 +01:00
Joachim Wiberg 119e66a7e9 Reset color attributes and clear screen when starting up
Some boot loaders, like GRUB, leave background color artifacts from
their boot menu.  This patch resets the foreground and background
color attributes, and then clears the screen, without clearing the
scrollback buffer.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-28 10:58:04 +01:00
Joachim Wiberg 46ffa81f5c Only mark rdeps dirty if main service is nohup
This patch changes a behavior that's been default since Finit 4.0,
introduced in 4d05bf9 with 4.0-rc2.

If service B depends on A and A needs to be reloaded, then B may be
affected.  If A is declared as NOHUP <!>, then A will be stopped and
restarted, during which time the condition it provides is removed,
and B will also be stopped.

However, and as of this patch, if A is declared supporting HUP, then the
condition A provides will only go into flux, during which time B will be
SIGSTOPed instead of needing to be reloaded.

Fix #415

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-17 14:33:30 +02:00
Joachim Wiberg 54701422a5 Bump version for v4.8 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-13 19:42:44 +02:00
Joachim Wiberg 9d463e3823 Update ChangeLog, added fistmpfs() check and zebra stop fix
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-13 19:42:44 +02:00
Joachim Wiberg 56e558c960 initctl: add support for showing template@foo.conf
Fixes #411

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-13 19:40:21 +02:00
Joachim Wiberg dfaf351da1 Fix #414: zebra immediately restarts if manually stopped
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-13 19:40:21 +02:00
Joachim Wiberg a8433fcb7f test: ignore unreachable shellcheck warning
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-10-12 08:39:30 +02:00
Joachim Wiberg 2daa953bee Merge pull request #409 from liuming50/prevent-nftw-follow-symbolic-links 2024-08-24 14:56:28 +02:00
Ming Liu 3e3e9aadf5 tmpfiles.c: prevent nftw follow symbolic links
When dealing with "L+" and "R", the function call 'nftw' should not
follow symbolic links, otherwise, it would also delete the targets
which is wrong.

For instance, if there is already a symbolic link:
```
/path/to/the/link -> /path/to/some/folder
```

if we set the following in a tmpfile conf:

```
L+ /path/to/the/link -    -    -     - /path/to/the/target
```

the result would be /path/to/some/folder also get deleted, which it
should not.

it could be even worse, when the symbolic link already is pointing to:
/path/to/the/target, the whole /path/to/the/target would be deleted on
next system boot.

Signed-off-by: Mathias Thore <mathias.thore@atlascopco.com>
Signed-off-by: Ming Liu <liu.ming50@gmail.com>
2024-08-24 13:29:10 +02:00
Joachim Wiberg dc873c6548 Show expanded prefix and libdir in summary
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-08-19 08:02:12 +02:00
Joachim Wiberg 29bd7a504e Merge pull request #408 from mandelmassa/master
Avoid remounting already mounted /run and /tmp directories

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-08-06 13:13:49 +02:00
Mathias Thore a0685219cf Avoid remounting already mounted /run and /tmp directories
Adds the function fistmpfs to determine if a new tmpfs mount should be
performed on /run and /tmp. The function supports cases where more
complex mount hierarchies are in use, including overlayfs backed mounts.

Signed-off-by: Mathias Thore <mathias.thore@atlascopco.com>
2024-08-05 14:33:43 +02:00
Joachim Wiberg 13b107b7b1 Fix #407: extend initctl poll timeout
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-06-22 09:23:14 +02:00
Joachim Wiberg 409d68d05b Update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-06-22 09:20:28 +02:00
Joachim Wiberg ab62b5282b runparts: add -b (batch) mode for syslog output
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-06-19 09:20:03 +02:00
Joachim Wiberg d02d65feeb .github: minor, bump action version
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-06-19 09:20:03 +02:00
Ming 9a0dea6aef configure.ac: make cgroup2 configurable (#406) 2024-05-11 14:06:01 +02:00
Joachim Wiberg 7481505b1a plugins: minor refactor
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 19:38:03 +02:00
Joachim Wiberg 8251f1a422 Fix derefernce before NULL check
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 14:40:05 +02:00
Joachim Wiberg e269176a79 plugins: fix possible use of unitialized variable
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 14:39:30 +02:00
Joachim Wiberg 612f5a9385 Allow building Finit --without-rc-local support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 14:25:53 +02:00
Joachim Wiberg 4a2381eb6f Fix #404: possible undefined behavior --without-fstab
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 14:22:57 +02:00
Joachim Wiberg 0cae7d44dd Follow-up to 6a89e60, len may be used unitialized
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-28 14:21:22 +02:00
Joachim Wiberg 340cae4afd Change default behavior, allow kernel logs to console
A Linux system booted with the kernel command line option 'quiet' only
logs error (and above) severity messages to the console.  For embedded
systems, which is the primary target for Finit, this is what you want
to see.

Hence, and after careful consideration, this patch changes the default
behavior of Finit to allow kernel logs to the console.  A build-time
configure flags, --disable-kernel-logging, has been added to restore
legacy behavior.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-24 12:46:59 +02:00
Joachim Wiberg 6a89e60fc8 Fix #405: parsing >1 active consoles in tty @console setups
Systems that have the following tty setup and multiple consoles listed
in /sys/class/tty/console/active misbehave:

    tty [12345789] @console 0 xterm noclear passenv

Only the first listed console is started properly, the remaining ones
were registered using the wrong :ID and no arguments to getty.

This patch fixes the parsing and re-use of the base paramenters for
all consoles listed in the active file.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-24 11:33:35 +02:00
Joachim Wiberg 840d612fc2 plugins: minor, show skipped path in debug
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-03 08:11:50 +02:00
Joachim Wiberg 60c676ab2d test: minor, spelling in comment
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-03 08:11:41 +02:00
Joachim Wiberg deada0fa89 initctl: refactor to use new suffix() function
Reduce code duplication and use suffix() function to check and append a
suffix to a path.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-03 08:10:35 +02:00
Joachim Wiberg 7b501f255b initctl: touch does not support template services
Fixes #403

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-03 07:47:23 +02:00
Joachim Wiberg 052136cb99 initctl: touch does not respect -n switch
Fixes #402

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-04-02 16:07:01 +02:00
Joachim Wiberg 742b8b72cc Update ChangeLog for v4.8-beta1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-30 12:39:06 +01:00
Joachim Wiberg c37037c015 system: allow udevd to read its arguments from /etc/default/udevd
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-30 12:38:50 +01:00
Joachim Wiberg c32b5a749a Refactor popen()/pclose() logic in ifupdown calls
Currently no code checks the return code of ifupdown at runlevel
changes, but for future reference this code has been refactored
to match the changes made in cbdb949 to fix issue #400.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-30 12:38:50 +01:00
Joachim Wiberg 7701718d7b Fix #400: resolve exit code from pclose() by calling WEXITSTATUS()
This problem affects all calls to run_interactive() that check the
return value of the command.  Causing HOOK_MOUNT_ERROR to *not* run
on mount failure, and sulogin() to *not* be started on fsck error.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-30 12:38:50 +01:00
Joachim Wiberg eb4eca9607 test: verify pre:/post:scripts also for configlets
For a background, see issue #399

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-23 08:55:42 +01:00
Joachim Wiberg cab94b81e8 Bump version for start of 4.8 release cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-23 08:31:53 +01:00
Joachim Wiberg 5913217808 test: add finit.d/available and finit.d/enabled/ dirs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-23 08:17:03 +01:00
Joachim Wiberg b49f55ab3d tmpfiles.d: ignore x/X command, no cleanup at runtime with Finit
Silence log warnings for command x/X (ignore clean for path), because
Finit does not do tmpfiles cleaning at runtime.

x /tmp/podman-run-*
x /tmp/containers-user-*
x /tmp/run-*/libpod
D! /var/lib/containers/storage/tmp 0700 root root
D! /run/podman 0700 root root
D! /var/lib/cni/networks

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 12:06:39 +01:00
Joachim Wiberg bf4a584e2e plugins: add support for hwrng and check if seed file is empty
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-13 12:06:32 +01:00
Joachim Wiberg 90a4df8d12 plugins: on error-retry, don't print "Restoring RTC" twice
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-11 18:53:22 +01:00
Joachim Wiberg 146bf55122 Fix #398: display unsupported initctl command (number) in log
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-11 16:01:30 +01:00
Joachim Wiberg c1ed373398 Fix #397: drop ttinit() for PID 1
After reports from the field, see issue #397, of lockups at reboot,
we've decided to drop this code from PID 1.  It was added before the 4.x
series, when the current progress output was introduced.  For the older
style progress it served a purpose since the placement of [OK]/[FAIL]
was on the right hand side.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-03-11 15:46:38 +01:00
Joachim Wiberg 5998342b3e system: drop debug mode from udevd
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-02-26 08:41:14 +01:00
Joachim Wiberg 9dc7b8a6b0 tmpfiles.d: skip x11.conf unless --enable-x11-common-plugin
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-02-04 15:27:27 +01:00
Joachim Wiberg c221823654 shutdown: use cond_clear_noupdate() to prevent nested service_stop()
When the system shuts down, or user changes runlevels, we don't have to
call cond_clear_update(), because this can lead to nested service_stop()
calls, which in turn lead to out of sync progress updates:

[ .. ] Stopping Foo
[ OK ] Stopping Bar
[ OK ]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-02-03 17:31:37 +01:00
Joachim Wiberg 248f7d3110 Merge pull request #393 from solt87/patch-1
Improve wording.
2024-01-16 08:04:36 +01:00
Solt Budavári fe90ba5781 Improve wording. 2024-01-15 20:56:16 +01:00
Joachim Wiberg 71c87734b7 Add missing ChangeLog for critical issue triggering v4.7 release cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-08 16:46:56 +01:00
Joachim Wiberg cd060e8af3 getty: trigger /etc/issue compat mode for Alpine Linux
The /etc/issue file on Alpine Linux says "Kernel \r on an \m (\l)", so
\r needs to return the uts release rather than os-release VERSION.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 21:18:58 +01:00
Joachim Wiberg 33a7f123d7 contrib/alpine: link to blog post that goes more in-depth
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 21:07:48 +01:00
Joachim Wiberg d15e28ea6b Update ChangeLog and bump version for v4.7 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 19:48:31 +01:00
Joachim Wiberg 836bfff08b .github: update actions
... and try to fix weekly trigger

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 19:47:12 +01:00
Joachim Wiberg 59152b557c keventd: remove runlevels 0 and 6
The responsibility of the kernel event daemon is to relay kernel events
to Finit.  At shutdown and reboot it is too late for more events and the
daemon should just shut down with other services.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 15:18:52 +01:00
Joachim Wiberg 293b0ffa79 tmpfiles.d/var.conf: fix ordering and add legacy /run/lock/subsys
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 13:59:49 +01:00
Joachim Wiberg d5d9cd5645 tmpfiles: fix error message and ignore unremovable dirs (EBUSY)
Fix copy-paste of error message from cond-w.c

A read-only root filesystem may have /var/lock, while we want to remove
it and add a symlink to ../run/lock.  Ignore errors from this since we
cannot do anything about it.  It is up to the user to fix their skeleton
or use an overlay.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 13:56:31 +01:00
Joachim Wiberg 2f281665af Simplify and add links to Infix, br2-finit-demo, and Buildroot
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 02:00:47 +01:00
Joachim Wiberg b00e7394f8 Update ChangeLog and bump version for v4.7-rc1
No more changes or fixes expected.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:51:15 +01:00
Joachim Wiberg d5a5fffa52 Update copyright years
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:50:50 +01:00
Joachim Wiberg 4d24c34b28 Update screenshot URL to point to HowTo
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:39:30 +01:00
Joachim Wiberg 355265651e Retake new screenshot, fix resolution
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:32:52 +01:00
Joachim Wiberg 41093df2a9 Attempt 2, scaled
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:27:03 +01:00
Joachim Wiberg 0a816d1fa4 Test bump Alpine screenshot
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 01:23:03 +01:00
Joachim Wiberg 3bfc0f0fca contrib/alpine: drop softdog, we are not built with finit-watchdogd
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 00:59:27 +01:00
Joachim Wiberg 0aa6ee895c contrib/alpine: follow-up to 2c340f83
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 00:59:18 +01:00
Joachim Wiberg b1526fb2d6 contrib/alpine: bump version
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 00:56:41 +01:00
Joachim Wiberg b2624ac160 contrib/alpine: fix install script, grep for contrib/alpine
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 00:56:11 +01:00
Joachim Wiberg 2c340f83ce contrib/alpine: fix syslog.conf vs syslogd.conf
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-07 00:26:19 +01:00
Joachim Wiberg 337ee003bb Mount /dev/mqueue if missing and set sticky bit to /dev/shm
Inspired by Alpine Linux, add /dev/mqueue if missing.  We should check
the /proc/filesystems first, but this is quicker.

The sticky bit ensures only the owner of files in /dev/shm can delete or
rename files.  This is also what Alpine Linux use.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 23:50:30 +01:00
Joachim Wiberg 791df0c986 Refactor, ensure basenm() returns a const char pointer of its arg.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 23:46:17 +01:00
Joachim Wiberg f29e92be21 Minor, update
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 20:02:45 +01:00
Joachim Wiberg 379a63fce4 .github: adjust path for cov-build
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 19:55:55 +01:00
Joachim Wiberg b1f9a11809 .github: update actions, sync coverity with latest
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 19:51:37 +01:00
Joachim Wiberg 2d9c63e48e test: actually verify the service asserts ready before continuing
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 16:31:45 +01:00
Joachim Wiberg d66455496a Fix #392: ensure 'ready' condition is cleared on pidfile removal
A service with notify:pid is 'ready' when the pidfile has been created,
the converse also holds true -- when a pidfile is removed the service is
no longer 'ready'.

The state transition for the service has probably already been done, in
svc_set_state(), clearing all <service/foo/*> conditions when the PID
was collected.  The pidfile event may arrive later, so for completeness
we make sure the 'ready' condition is not recreated at least.

Problem introduced in 912a281 with the original supoport for service
readiness notification.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 12:25:41 +01:00
Joachim Wiberg 77cf72cb40 test: regression test to reproduce issue #392
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 12:03:33 +01:00
Joachim Wiberg 6cc587068b Log service identifier, not process name, in debug message
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 11:59:46 +01:00
Joachim Wiberg cc96e8908a Open v4.7 release cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 11:59:33 +01:00
Joachim Wiberg adb25d52cd test: minor, rename test case native -> pid
We now support notify:pid, so let's use it, even though it's the default.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-06 10:13:13 +01:00
Joachim Wiberg 7d09567ec8 Mention cgroup.root workaround to Linux SCHED_RR limitation
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-01-05 10:27:03 +01:00
Joachim Wiberg 9130af1c77 Merge pull request #390 from Stargirl-chan/master
Fix compilation on musl by implementing a custom basename

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-12-29 14:57:10 +01:00
Stargirl-chan cbea83b369 Simplified function comment and follow coding style 2023-12-29 13:37:08 +01:00
Stargirl-chan 42cd8d284b Implement custom basename function (basenm)
There exist two possible basename functions, a xpg compliant one in libgen.h
and a GLIBC exclusive one declared in string.h, that was previously also declared by musl libc.
Both implementations are expecting different parameter types (`const char *` for GLIBC and `char *` for xpg)

With the removal of the basename function from string.h in musl libc, we could only rely on the xpg implementation.

Unfortunately, the xpg implementation of basename does modify the contents of whatever you put in it,
even though that there really is no need for it.

This is an issue in some cases, where we might want to get the basename of a read-only variable, e.g. a `const char *`,
as trying to modify something read-only is undefined behavior.

So in order to keep things consistent for us, we implement our own version of basename called `basenm`,
that does not modify the passed argument.
2023-12-29 10:44:40 +01:00
Stargirl-chan 72ebc92622 Fix compilation on musl by using posix basename 2023-12-28 03:41:00 +01:00
Joachim Wiberg 06adecaaea Merge pull request #388 from soggyfries/soggyfries-log-fix
Fix log child exiting with debug disabled
2023-12-19 06:43:24 +01:00
Ryan Rorison efc0592961 Fix log child exiting with debug disabled 2023-12-18 21:00:45 -08:00
Joachim Wiberg ed88469276 Actually silence the log message, missing hunk for previous change
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-12-10 17:32:19 +01:00
Joachim Wiberg cbf96a1de0 Silence 'not available' log messages for nowarn run/task/service
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-12-10 16:42:29 +01:00
Joachim Wiberg cc979f27f1 tmpfiles.d: add missing /var/tmp and /var/lock -> /run/lock
- /var/tmp  https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html
 - /run/lock std Debian

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-22 08:08:24 +01:00
Joachim Wiberg fca5ce57ea Bump version for v4.6 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 07:03:30 +01:00
Joachim Wiberg 53aa195ad5 test: update, pid/B is no longer assert by Finit if notify != pid
As of Finit v4.6 we no longer assert the PID condition for services
declaring themselves as notify != pid.  We replace D with a forking
service to catch any future regressions in the pidfile plugin.

No need to check reload PID of D, it is enough to check PID of C.

Also, reduce the number of retries at startup.  If we haven't gone
up within 10 sec with this tiny config something is really wrong.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 06:09:35 +01:00
Joachim Wiberg e60211168e Fix type:forking regression in 66020f4, caught by tests
Premise, a service declaring itself 'notify:none' should never assert a
pid condition.  However, forking services still need to be supported and
the only way to do that is if they create a pid file.  Hence, instead of
skipping pidfile_update_conds() completely we need to filter the type.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 06:06:58 +01:00
Joachim Wiberg dc3ee9e467 Handle rare warning when registering configuration changes
2023-11-13T04:02:23 [WRN]: conf_change_act():failed registering /etc/finit.conf/ event mask 00000004: Not a directory

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 05:05:07 +01:00
Joachim Wiberg 6918f3b711 Update ChangeLog for v4.6
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 04:39:08 +01:00
Joachim Wiberg 66020f48ea Do not create PID conditions for services that do not support it
Follow-up to issue #386

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 04:37:03 +01:00
Joachim Wiberg 47b0d4cccf Reassert both PID and ready conditions when leaving paused state
Follow-up to issue #386

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 04:35:31 +01:00
Joachim Wiberg 92c2efa655 Minor, use svc_ident() instead of incomplete svc->name in debug logs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-13 04:32:30 +01:00
Joachim Wiberg b69aa8a8bd Bump version for 4.6 bug fix release, rc1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 19:08:40 +01:00
Joachim Wiberg ca90bbfb04 Fix #387: sanity check environment variables before sourcing
This fixes an issue when finding a global environment variable with
spaces in the variable name:

    set COLORTERM=yes

Literally, 'set COLORTERM' was the name of the variable.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 19:07:54 +01:00
Joachim Wiberg 0b5c555c7f Add 'notify:pid' style readiness notifaction and 'readiness none'
This change expands the readiness notification system in Finit with the
native 'pid' style, which will remain the default readiness in Finit 4.x

For systems that want to transition to Finit 5.x early, a global option
to set 'readiness none' in /etc/finit.conf, has been added.  This change
the service default notification mode to 'notify:none', which can also
be set by Finit 4.x ('readiness pid') for select services.

Fixes #386.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 19:07:12 +01:00
Joachim Wiberg 6443995fc9 Fix #385: internal conditions are type oneshot, always active
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 09:04:35 +01:00
Joachim Wiberg 180faf8a40 test: minor, disable debug as final step in function
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 09:04:15 +01:00
Joachim Wiberg 0ebdd32f6b Fix #384: reassemble value fragments after wordexp() before setenv()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 08:50:12 +01:00
Joachim Wiberg 60bf858302 test: extend svc-env.sh with more common use-case
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-12 08:37:05 +01:00
Joachim Wiberg 7c86b40190 Fix #383: configure must expand FINIT_RUNPATH_ before define
This fixes an annying buglet that creeped in just before the v4.5 release
causing none of the internal services to be registered properly:

    conf_save_service():Failed creating ${localstatedir}/run/finit/system/dbus.conf: No such file or directory
    plugin_run_hook():Calling modules-load hook n:o 5 (arg: 0x55c4c8133621) ...
    load():Scanning /etc/modules-load.d for config files ...
    cond_set_oneshot():hook/svc/plugin
    cond_set_oneshot_noupdate():hook/svc/plugin => /run/finit/cond/hook/svc/plugin
    cond_update():hook/svc/plugin
    parse_conf():*** Parsing /etc/finit.conf
    conf_save_service():Failed creating ${localstatedir}/run/finit/system/runparts.conf: No such file or directory

The fix, like most, is simple when you find it.  We must expand $runstatedir
before creating the #define in config.h

For convenience, here's the patch for the generated configure script:

&<---------------------------[cut here]---------------------------
--- a/configure	2023-11-05 23:39:51.907334321 +0100
+++ b/configure	2023-11-05 23:39:58.339299795 +0100
@@ -15352,7 +15352,15 @@
 printf "%s\n" "#define FINIT_EXECPATH_ \"$pkglibexecdir\"" >>confdefs.h

-printf "%s\n" "#define FINIT_RUNPATH_ \"$runstatedir/finit/system\"" >>confdefs.h
+	finit_runpath="$runstatedir/finit/system"
+	finit_runpath=`(
+	    test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+	    test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
+	    eval echo \""$finit_runpath"\"
+	    )`
+
+
+printf "%s\n" "#define FINIT_RUNPATH_ \"$finit_runpath\"" >>confdefs.h

&<---------------------------[cut here]---------------------------
Ensure you include the three empty lines for context at the end!

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-11-05 23:46:26 +01:00
Joachim Wiberg 4f3f140a09 Disable Bash completion in 'make distcheck'
We cannot rely on the auto-detection of Bash completion dir during 'make
distcheck' because autotools does not use DESTDIR, only --prefix for the
install check, and pkg-config returns a system path.

Also, show detected path in configure summary for debug.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 22:54:42 +01:00
Joachim Wiberg 10c24b1674 Minor, reorder alphabetically
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 22:53:20 +01:00
Joachim Wiberg 2b4f89ecd1 test: cannot use absolute path to initctl (distcheck)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 22:09:54 +01:00
Joachim Wiberg c42a6f2869 Update ChangeLog and bump version for v4.5 GA
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 21:05:10 +01:00
Joachim Wiberg 89bb609a7e Update Filesystem Layout section slightly, tie in with bootmisc.so
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 21:04:02 +01:00
Joachim Wiberg da6298aecd test: wait for runparts to finish
In Finit v4.5 we've moved the start of rc.local and runparts to the
transtion from bootstrap to multi-user, so we must give it time to
finish.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 21:04:02 +01:00
Joachim Wiberg 576318cc29 Install Bash completion by default, auto-detect install path
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 20:47:11 +01:00
Joachim Wiberg 0d7d331ad4 Fix minor resource leak at boot, found by Coverity Scan
Introduced in release cycle, no need to document.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 20:11:48 +01:00
Joachim Wiberg c886ecb5cc Add support for multiple if:!foo,!bar to skip loading of service
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 19:25:10 +01:00
Joachim Wiberg 304a096877 test: wait for runparts to finish
In Finit v4.5 we've moved the start of rc.local and runparts to the
transtion from bootstrap to multi-user, so we must give it time to
finish.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 18:16:24 +01:00
Joachim Wiberg 064c7682fc Minor, do not append errno message
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 18:15:34 +01:00
Joachim Wiberg 58239b897b Silence Finit progress output for run/tasks stopping
Sync with Starting message in service_start(), should only be shown for
daemons and sysv services.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 18:01:13 +01:00
Joachim Wiberg 5281d82e80 Fix #378: add run/task support for <!> to allow transition from bootstrap
This odd little feature makes it possible to declare run/tasks with a
condition that does not block Finit transitioning from bootstrap to the
next runlevel.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 17:55:39 +01:00
Joachim Wiberg 5ff28c4dc6 system: minor, ignore generated file
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 16:18:11 +01:00
Joachim Wiberg f2218836af Fix #378: warn on console if run/task times out during bootstrap
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 14:52:26 +01:00
Joachim Wiberg fbb3779d17 Fix bootstrap timeout (120 sec), off by a factor 10 (1200 sec)
Regression in v4.5 release cycle, no changelog notice needed.

Reported as part of issue #378 by Alexander Zangerl.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 13:50:43 +01:00
Joachim Wiberg 68f44f7a97 Fix #377: expand service env:file variables
This change allows us to support constructs like this:

    RUNDIR=/var/run/somesvc
    DAEMON_ARGS=--workdir $RUNDIR --other-args...

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 13:32:09 +01:00
Joachim Wiberg 50e587f447 test: new test, verify env:file variable expansion
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 13:31:36 +01:00
Joachim Wiberg fb4c560196 test: shellcheck fixes to new test
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 13:31:31 +01:00
Joachim Wiberg 8b5fa5eeaa test: add optional argument to sep() helper function
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 13:31:01 +01:00
Joachim Wiberg 88ec21e9cc plugins: change wording, we don't recreate machine-id every boot
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 10:14:32 +01:00
Joachim Wiberg 84adec4006 Fix #382: do not clear service conditions if only paused
Introduced back in v4.3-rc2, 82cc10be8, the support for automatic
service conditions have had a weird and unintended behavior.  Any
change in state (see doc/svc-machine.png) caused Finit to clear
out *all* previously acquired service conditions.

However, when moving between RUNNING and PAUSED states, a service
should not have its conditions cleared.  The PAUSED state, seen
also by all conditions moving to FLUX, is only temporary while an
`initctl reload` is processed.  If a service has no changes to be
applied it will move back to RUNNING.

Also, we cannot clear the service conditions because other run/task
or services may depend on it and clearing them would cause Finit to
SIGTERM these processes (since they are no longer eligible to run).

This patch not only adds this pre-condition to `cond_clearn()`, it
also clarifies which state (before or after) the particular code
is interested in.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 01:05:25 +01:00
Joachim Wiberg 19b2b2a279 test: follow-up to 2235fb83
Renamed .conf file for udev/mdev etc. caused 'mdev -df' to start in
tests.  This fix closes that again since none of that is needed in
our small namespaced world.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 01:02:33 +01:00
Joachim Wiberg e4163b7221 test: new test, issue #382
Alexander Zangerl reports that <service/foo/STATE> conditions seem to be
removed when calling `initctl reload`, even though no .conf changes have
been made.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-30 00:58:28 +01:00
Joachim Wiberg eaef302420 Drop doc/bootstrap.md, inaccurate and confusing to users
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-24 23:43:28 +02:00
Joachim Wiberg d5738da307 system: add support for mdevd, preferred over plain mdev
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 13:37:13 +02:00
Joachim Wiberg c9f930c7ad Skip registering service when if:!name matches a named svc_t
The delayed matcehd works when all run/task/services provide their own
unique identity, but for replacements this is sometimes not the case.

Example from system/10-hotplug.conf.in:

    run nowarn conflict:udevd,mdev cgroup.init name:coldplug <service/mdevd/ready> \
	[S] mdevd-coldplug -- Cold plugging system

vs

    run nowarn conflict:udevd,mdevd cgroup.init name:coldplug if:!mdevd <service/mdev/running> \
	[S] @pkglibexecdir@/coldplug -- Cold plugging system

Here they both provide the <run/coldplug/*> conditions, and if the first
is loaded, because we found mdevd, then we should not attempt to load
this one.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 13:37:13 +02:00
Joachim Wiberg e2ee372b5d Fix #374: describe automount of /run, /tmp and tmpfiles.d support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 12:18:42 +02:00
Joachim Wiberg 7ff7f93364 Fix #376: describe shell limitations with run/task stanzas
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 12:17:07 +02:00
Joachim Wiberg d5a95760ef Replace hardcoded /run/finit/system with configured path
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 11:49:37 +02:00
Joachim Wiberg 24d1425b74 Disable modprobe plugin by default, udevd and mdev loads modules
The updated 10-hotplug.conf now ensures modules are loaded, so we no
longer need the modprobe.so plugin to be enabled by default.

Also, update the hotplug "plugin" description, it is kept entirely
for backwards compatibility reasons after the plugin was converted
to 10-hotplug.conf.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 11:49:37 +02:00
Joachim Wiberg 43d9e25ba7 Fix #367: add support for mdev's netlink daemon mode
This commit replaces the `mdev -s` call to populate the device tree with
the "new" `mdev -df` daemon mode, introduced in BusyBox 1.31.0, 2019.

In daemon mode mdev listens to kernel uevents, replacing the hotplug use
of mdev.  After creating the netlink socket, 'mdev -df' performs the same
initial scan as 'mdev -s' did.

To perform device (re)discovery, module loading and setup, including any
firmware loading, a coldplug operation is typically required.  This is
done by the new /libexec/finit/coldplug script, by Alexander Zangerl.

Unlike 'mdevadm settle', mdev does not offer any mechanism to detect when
the discovery operation is done: on slower systems the triggering side,
the coldplug script, often completes quite a bit earlier than mdev's
uevent processing.  I.e., depending on <run/coldplug/success> is not an
indicator of all devices having been (re)discovered and fully set up.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-22 11:49:29 +02:00
Joachim Wiberg f27998ae4f Assert <int/container> condition if we detect running in container
Useful both for troubleshooting and for triggering if:<int/container> tasks.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-14 08:37:15 +02:00
Joachim Wiberg c8e0b6b9ef Redirect 'log*' output to console when finit.debug is enabled
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-14 08:34:06 +02:00
Joachim Wiberg f7e8fccb2f system: extend final udevadm settle timeout 5 -> 30 sec
On some systems udev may very well take more than five seconds to complete.
Probing modules, loading firmware, etc.  Note, the timeout only sets the
maximum wait time.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-14 08:29:08 +02:00
Joachim Wiberg 7bbccb1213 Silence non-critical failure to remove /run/finit/cond/ at reboot
The directory may hold various custom generated conditions that are not
managed by Finit.  Not being able to remove the directory is not a
critical error.

finit[1]: cond_delpath():Failed removing condition path /var/run/finit/cond/: Directory not empty

Therefore, ignore ENOENT and ENOTEMPTY and log everything/anything else.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-14 08:25:56 +02:00
Joachim Wiberg d38c333e04 Bump version for final candidate, v4.5-rc5
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-05 08:19:24 +02:00
Joachim Wiberg 095f6b645c Update ChangeLog, should be final changes for v4.5 GA
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 19:01:38 +02:00
Joachim Wiberg b4d10cbade Always ensure /run/finit/system exists before saving runtime service
This fixes the regression in the tests, which runs in a very stripped
down world without tmpfiles.d etc.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:48:13 +02:00
Joachim Wiberg 5d703fd39e Support delayed load of services from plugins and bundled services
This adds a new function conf_save_service() replacing service_register() for
plugins and bundled services like watchdogd, keventd, runparts, etc.

The benefits to this change are several:

 - Plugin/Bundled services no longer risk starting before udev or other
   critical services/task have started
 - Definitions can be overridden by an administrator (see docs)
 - Increases visibility (user: where are all these services coming from?)
   Previously the origin (file the service was loaded from) was NULL.
 - Adds another level of extensibility to Finit

The most notable change is that dbus is no longer started before udevd.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:37:43 +02:00
Joachim Wiberg eaaf8d862e Minor, append _ to PATH constant
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:25:09 +02:00
Joachim Wiberg 2468f11cd8 plugins: fix dbus pidfile locator
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:20:50 +02:00
Joachim Wiberg f8a6a119ac system: new name for testserv.conf -> 90-testserv.conf
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:30:08 +02:00
Joachim Wiberg 1889b88aab Log execution order at bootstrap to /run/finit/exec.order
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:21:11 +02:00
Joachim Wiberg 0d70023bfe Log conf file evaluation order at bootstrap to /run/finit/conf.order
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:20:15 +02:00
Joachim Wiberg 41648a073b Fix evaluation order of /lib/finit/system/* vs /etc/finit.d/*
See updated documentation and inline comment for details.

Fix #371

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:20:15 +02:00
Joachim Wiberg 33cee0ba5f system: fix lost udevadm calls due to overloading
The system/10-hotplug.conf needs to index its calls to udevadm for all
calls to udevadm, not just the trigger calls.  Otherwise the first
udevadm is overloaded with all subseequent (unindexed) udevamd stanzas.

Also, make sure all udevadm calls to settle/reload are hidden.

Fix #372

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:19:46 +02:00
Joachim Wiberg 2235fb8352 system: rename *.conf files to ensure proper execution order
At bootstrap we want to start udev as soon as possible (after any
services registered by plugins).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 11:39:39 +02:00
Joachim Wiberg eb9e94935e Failure to open fstab should log to console, reboot if no sulogin
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:56:49 +02:00
Joachim Wiberg fb230f2137 .github: add makeLatest flag based on non-rc/beta/alpha
Note, the makeLatest flag can also be set to 'legacy', which takes
latest date and version.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:42:20 +02:00
Joachim Wiberg 6aa48a8b32 .github: fix pre-release flag input
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:41:52 +02:00
138 changed files with 2786 additions and 1049 deletions
+2 -1
View File
@@ -24,7 +24,8 @@ the maintainer(s) and make it easier for them to include your code.
Coding Style
------------
> **Tip:** Always submit code that follows the style of surrounding code!
> [!TIP]
> Always submit code that follows the style of surrounding code!
First of all, lines are allowed to be longer than 72 characters these
days. In fact, there exist no enforced maximum, but keeping it around
+8 -6
View File
@@ -21,26 +21,25 @@ jobs:
compiler: [gcc, clang]
fail-fast: false
env:
MAKEFLAGS: -j3
CC: ${{ matrix.compiler }}
steps:
- name: Install dependencies
run: |
sudo apt-get -y update
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Static Finit
run: |
./autogen.sh
./configure --prefix= --enable-static
make V=1
make -j3 V=1
- name: Regular Finit
run: |
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
--with-keventd
make clean
make V=1
make -j3 clean
make -j3 V=1
- name: Install to /tmp
run: |
DESTDIR=/tmp make install-strip
@@ -57,11 +56,14 @@ jobs:
run: |
sudo /tmp/sbin/finit -h
sudo /tmp/sbin/initctl -h
- name: Enable unprivileged userns (unshare)
run: |
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
- name: Run Unit Tests
run: |
make check || (cat test/test-suite.log; false)
- name: Upload Test Results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: finit-test-${{ matrix.compiler }}
path: test/*.log
+41 -16
View File
@@ -4,6 +4,7 @@ on:
push:
branches:
- 'dev'
workflow_dispatch:
env:
PROJECT_NAME: finit
@@ -15,22 +16,39 @@ jobs:
coverity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
id: coverity-toolchain-cache
with:
path: cov-analysis-linux64
key: ${{ runner.os }}-coverity
- name: Download Coverity Scan
if: steps.coverity-toolchain-cache.outputs.cache-hit != 'true'
- uses: actions/checkout@v4
- name: Fetch latest Coverity Scan MD5
id: var
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
wget -q https://scan.coverity.com/download/cxx/linux64 \
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
-O cov-analysis-linux64.tar.gz
mkdir cov-analysis-linux64
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
wget -q https://scan.coverity.com/download/cxx/linux64 \
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
-O coverity-latest.tar.gz.md5
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
- uses: actions/cache@v4
id: cache
with:
path: coverity-latest.tar.gz
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
restore-keys: |
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
${{ runner.os }}-coverity-
${{ runner.os }}-coverity
- name: Download Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
if [ ! -f coverity-latest.tar.gz ]; then
wget -q https://scan.coverity.com/download/cxx/linux64 \
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
-O coverity-latest.tar.gz
else
echo "Latest Coverity Scan available from cache :-)"
md5sum coverity-latest.tar.gz
fi
mkdir coverity
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
- name: Install dependencies
run: |
sudo apt-get -y update
@@ -42,13 +60,15 @@ jobs:
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
sudo ldconfig
- name: Build
- name: Configure
run: |
./autogen.sh
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
- name: Build
run: |
export PATH=`pwd`/coverity/bin:$PATH
cov-build --dir cov-int make
- name: Submit result to Coverity Scan
- name: Submit results to Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
@@ -61,3 +81,8 @@ jobs:
--form version=trunk \
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
- name: Upload build.log
uses: actions/upload-artifact@v4
with:
name: coverity-build.log
path: cov-int/build-log.txt
+12 -3
View File
@@ -13,7 +13,7 @@ jobs:
env:
MAKEFLAGS: -j3
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Installing dependencies ...
run: |
sudo apt-get -y update
@@ -23,17 +23,25 @@ jobs:
run: |
ver=${GITHUB_REF#refs/tags/}
echo "ver=${ver}" >> $GITHUB_OUTPUT
if echo $ver | grep -qE '[0-9.]+(-alpha|-beta|-rc)[0-9]*'; then
if echo $ver | grep -qE '^[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
echo "pre=true" >> $GITHUB_OUTPUT
else
echo "pre=false" >> $GITHUB_OUTPUT
fi
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
echo "latest=true" >> $GITHUB_OUTPUT
else
echo "latest=false" >> $GITHUB_OUTPUT
fi
- name: Creating Makefiles ...
run: |
./autogen.sh
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
--with-keventd
- name: Enable unprivileged userns (unshare)
run: |
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
- name: Build release ...
run: |
make release || (cat test/test-suite.log; false)
@@ -48,6 +56,7 @@ jobs:
- uses: ncipollo/release-action@v1
with:
name: Finit v${{ github.ref_name }}
prerelease: ${{ needs.build.outputs.pre }}
prerelease: ${{ steps.build.outputs.pre }}
makeLatest: ${{ steps.build.outputs.latest }}
bodyFile: "release.md"
artifacts: "artifacts/*"
+6 -3
View File
@@ -13,7 +13,7 @@ jobs:
outputs:
run: ${{ steps.check.outputs.run }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Check for any commits since last week
id: schedule
run: |
@@ -25,14 +25,14 @@ jobs:
fi
distcheck:
needs: schedule
if: ${{ needs.schedule.outputs.run }}
if: ${{ needs.schedule.outputs.run == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo apt-get -y update
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Base run
run: |
./autogen.sh
@@ -41,6 +41,9 @@ jobs:
- name: Install to /tmp
run: |
DESTDIR=/tmp make install-strip
- name: Enable unprivileged userns (unshare)
run: |
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
- name: Check dist tarball
run: |
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
+4
View File
@@ -14,6 +14,7 @@ GTAGS
/autom4te.cache
/aclocal.m4
/ar-lib
/backup/
/compile
/config.cache
/config.h
@@ -36,6 +37,9 @@ GTAGS
/test-driver
/test-suite.log
# Misc
/.gdb_history
# TroglOS build system
/.config
/.stamp
+258 -36
View File
@@ -3,8 +3,174 @@ Change Log
All relevant changes are documented in this file.
[4.11][] - 2025-03-27
---------------------
[4.5][] - 2023-10-03
### Changes
- Update documentation regarding transition from runlevel S to 2, how
run/tasks must "complete" before Finit can move to the next runlevel
- Improve argument handling in bundled getty when launching login
### Fixes
- Fix #432: allow services in `setup` state to be stopped. This fixes
a serious blocker introduced in 4.10 that prevented systems from
being rebooted when any service was in this state
- Fix fallback `SIGKILL` when stopping a service with `SIGTERM` does
not work. This fixes a serious issue with services not responding to
the default `SIGTERM`
- Fix pre/post/ready/cleanup script execution if service has an
optional `env:file` (leading `-`)
[4.10][] - 2025-03-03
---------------------
### Changes
- Add support for `cleanup:[0-3600,]script`, runs before service is
removed, unlike `post:script` that runs when service is stopped
- Improved entropy gathering in tertiary fallback of urandom plugin
- Reclassify `sysv` from run/task class to `service`
### Fixes
- Fix #427: using an external getty with custom login program cause
Finit to use login program as the getty command
- Fix #428: allow `sysctl` path to be set at build time
- Fix #429: regression in v4.9 causing Finit to segfault at shutdown
- Fix possible memory leak when sourcing a service `env:file`
- Finit now waits until all `post:scripts` have run before returning
OK to `initctl <reload|runlevel>`. This also applies to the new
`cleanup:scripts` introduced in this release
- RFC3154 conformance formatting fix for `/dev/kmsg` fallback logging
[4.9][] - 2025-02-15
--------------------
> [!CAUTION]
> This release changes how Finit reacts to the exit status of `pre:`
> scripts. Finit will now no longer start the main process if its
> `pre:` script fails for any reason. So, if you have pre scripts that,
> e.g., create directories, make sure they are idempotent.
### Changes
- Add individual timeout (optional) support for pre/post/ready scripts
- Add support for systems with broken RTC, i.e., those that at power-on
may reset the RTC to a random date instead of zero, issue #418
- Add support for detecting "in-container" when in `systemd-nspawn`
- Check exit status of `pre:` scripts, on failure drive service/sysv to
`crashed` state. (The exit code of `post:` scripts remain ignored)
- All pre/post/ready scripts are now also searched for in `$PATH`
- Reset color attributes and clear screen when starting up. This is
for boot loaders like GRUB, which leave background color artifacts
### Fixes
- Fix #415: only mark reverse-dependencies "dirty" if the main service
does not support SIGHUP. This helps avoid unnecessary restarts of
services that depend on a service that supports SIGHUP
- Fix #417: leaking inotify watchers in the cgroup subsystem
- Fix #421: add support for `nofail` mount option in `/etc/fstab`
- Fix #425: ordering bug in detecting .conf file changes to services
and `initctl reload`, or runlevel changes
- Fix `initctl touch` of template services, previously marking a
service created from a template as "dirty" did not take
- Fix unintended restart of template "siblings". I.e., `initctl touch`
of instantiated template service A affected B from same template
- Fix buggy `--with-rtc-date=DATE` configure option
- Fix kill on timeout of pre/post/ready scripts
[4.8][] - 2024-10-13
--------------------
### Changes
- Avoid remounting already mounted `/run` and `/tmp` directories. This
extends the existing support for detecting mounted directories to
include complex mount hierarchies are in use, overlayfs and tmpfs
mounts. Feature by Mathias Thore, Atlas Copco
- getty: trigger /etc/issue compat mode for Alpine Linux
- tmpfiles.d: skip `x11.conf` unless X11 common plugin is enabled
- tmpfiles.d: ignore x/X command, nos support for cleanup at runtime
- Drop debug mode `-D` from `udevd` in `hotplug.conf.in`, allow the
user to set this in `/etc/default/udevd` instead
- Certain initctl APIs at bootstrap are not supported, update warning
log to include command (number) for troubleshooting, issue #398
- Add support for hwrng to urandom plugin and check for empty seed
- Add `runparts -b` (batch mode) support, disables escape sequences
- New configure `--without-rc-local`, disables `/etc/rc.local` support
- New configure `--disable-cgroup` option, disables cgroup v2 detection
- `initctl show template@foo.conf` now shows how an enabled template
service has been evaluated by Finit, issue #411
- Extend `initctl` timeout connecting and waiting for Finit reply. The
previous 2 + 2 second poll timeout has proved to be too short on more
complex systems. Now a 15 + 15 second timeout is applied which should
be more resistant to temporary overload scenarios, issue #407
### Fixes
- Fix #397: system shutdown/reboot can block on console input if action
is started remotely (ssh). Caused by legacy TTY screen size probing,
removed from both bootstrap and shutdown/reboot
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
either mount or `fsck` errors. Problem caused by unresolved status
from pipe, calling `pclose()` without extracting exit status
- Fix #402: `initctl touch` does not respect `-n` (no error) flag
- Fix #403: `initctl touch` does not support template services
- Fix #404: possible undefined behavior when `--with-fstab=no` is set
- Fix #405: `@console` getty does not work with `tty0 ttyS0`
- Fix #409: prevent tmpfiles from following symlinks for `L+` and `R`,
otherwise symlink targets would also be removed. Found and fixed by
Mathias Thore and Ming Liu, Atlas Copco
- Fix #414: Frr Zebra immediately restarts on `initctl stop zebra`.
The fix likely works for all Frr/Quagga services due to the way they
create and delete their pid file
- Cosmetic issue with `[ OK ]` messages being printed out of order at
shutdown/reboot. Caused by nested calls to `service_stop()`
- Cosmetic issue with duplicate "Restoring RTC" message at bootstrap
[4.7][] - 2024-01-07
--------------------
### Changes
- Silence "not available" messages for run/task/service with `nowarn`
- Update docs, `cgroup.root` workaround for `SCHED_RR` tasks
- Drop runlevels 0 and 6 from `keventd`, not needed at reboot/poweroff
- Mount `/dev/shm` with mode 1777 (sticky bit)
- Mount `/dev/mqueue` if available, inspiration from Alpine Linux
- Update Alpine Linux installer and configuration files, tested on
Alpine v3.19, some assembly still required
### Fixes
- Fix confusing warning message when tmpfiles.d fails to install symlink
- Fix tmpfiles.d legacy `/run/lock/subsys`, ordering
- Add missing `/var/tmp` and `/var/lock -> /run/lock` (tmpfiles.d)
- Fix #388: log redirection broken unless Finit runs in debug mode.
Found and fixed by Ryan Rorison
- Fix #389: must libc requires `libgen.h` for `basename()` function.
Reported and worked around with new `basenm()` function by Stargirl
- Fix #392: `service/foo/ready` condition reasserted on pidfile removal
[4.6][] - 2023-11-13
--------------------
### Changes
- Add support for service `notify:pid` and `readiness none` global
option to change how Finit expects readiness notification, issue #386
### Fixes
- Fix #383: dbus and runparts regression in Finit v4.5. The configure
script must expand `FINIT_RUNPATH_` before defining it in `config.h`
- Fix #384: service environment variables drop everything but the first
argument, e.g., `VAR="foo bar qux"` drops everything but `foo`
- Fix #385: internal conditions, e.g., `<int/bootstrap>` turn into flux
when leaving bootstrap, causing depending services to stop
- Fix #387: global environment variables declared with `set VAR=NAME` do
not drop leading `set `, causing `'set VAR'='NAME'` in env.
- Sanity check environment variables, for services and globally. Ensure
the variable name (key) does not contain spaces, or a leading `set `
[4.5][] - 2023-10-30
--------------------
### Changes
@@ -22,7 +188,7 @@ All relevant changes are documented in this file.
- Improved logging on failure to `execvp()` a run/task/service, now
with `errno`, e.g., "No such file or directory" when the command
is missing from `$PATH`
- Add support for Bash completion to `initctl`, issue #360
- Add Bash completion support for `initctl`, configurable, issue #360
- Handle absolute path to `initctl [enable|disable]`, not supported
- Update `finit.conf(5)` man page with the recommended directory
hierarchy in `/etc/finit.d/`
@@ -37,6 +203,24 @@ All relevant changes are documented in this file.
a task only `if:<run/foo/failure>` (here the run task 'foo' failed)
- Document new `if:`, `conflict:`, `nowarn` options for run/task/service
first introduced in v4.4
- Failure to open fstab should log to console, not just log to `/dev/kmsg`
- Rename `/lib/finit/system/*.conf`, added numbered prefix to ensure
proper execution order, e.g., `udevd` should always run first
- Plugins and bundled services: dbus, keventd, watchdogd, and runparts,
are now loaded *after* all services in `/lib/finit/system/`. A new
runtime-only path (for inspection) in `/run/finit/system/` is used
- Redirect `log*` output to console when `finit.debug` is enabled
- Assert `<int/container>` condition if we detect running in container
- Add support for mdev's netlink daemon mode, issue #367
- Add support for mdevd in `10-hotplug.conf`, preferred over plain mdev
- Disable modprobe plugin by default, udevd and mdev/mdevd loads modules
- Update documentation for run/task shell limitations, issue #376
- Update documentation regarding automount of `/run` and `/tmp`
- Update plugin documentation, add section about limited tmpfiles.d(5) support
- Skip registering service when `if:!name` matches a known service.
This allows conditional loading of alternative services, e.g. if udevd
is already loaded we do not need mdevd
- Drop `doc/bootstrap.md`, inaccurate and confusing to users
### Fixes
- Fix #227: believed to have been fixed in v4.3, the root cause was
@@ -52,9 +236,41 @@ All relevant changes are documented in this file.
- Fix #366: document `fsck.*` kernel command line options and simplify
the configure flags `--enable-fsckfix` and `--enable-fastboot` to
only adjust the default values for the `fsck.*` options.
- Fix #371: swap load order of `/lib/finit/system/*` vs `/etc/finit.d/*`
We must run `10-hotplug.conf` first to ensure devices and modules are
up and loaded before the user's run/task/services are called. The order
at bootstrap is now saved in `/run/finit/conf.order` for inspection,
`/run/finit/exec.order` shows the start order of each process
- Fix #372: lost `udevadm` calls due to overloading
- Adjust final `udevadm settle` timeout: 5 -> 30 sec
- Fixed dbus plugin, the function that located `<pidfile> ...` in the
`dbus/system.conf` caused spurious line breaks which led to the
service not being loaded properly
- The `runparts` executor now skips backup files (`foo~`)
- The `runparts` stanza now properly appends ` start` to scripts that
start with `S[0-9]+`. This has been broken for a very long time.
- Fix #377: expand service `env:file` variables, allow constructs like:
RUNDIR=/var/run/somesvc
DAEMON_ARGS=--workdir $RUNDIR --other-args...
- Fix #378: warn on console if run/task times out during bootstrap
- Fix #378: add run/task support for `<!>` to allow transition from
bootstrap to multi-user runlevel even though task has not run yet.
- Fix #382: do not clear `<service/foo/STATE>` conditions on reload.
Introduced back in v4.3-rc2, 82cc10be8, the support for automatic
service conditions have had a weird and unintended behavior. Any
change in state (see `doc/svc-machine.png`) caused Finit to clear
out *all* previously acquired service conditions.
However, when moving between RUNNING and PAUSED states, a service
should not have its conditions cleared. The PAUSED state, seen
also by all conditions moving to FLUX, is only temporary while an
`initctl reload` is processed. If a service has no changes to be
applied it will move back to RUNNING.
Also, we cannot clear the service conditions because other run/task
or services may depend on it and clearing them would cause Finit to
`SIGTERM` these processes (since they are no longer eligible to run).
[4.4][] - 2023-05-15
@@ -149,7 +365,7 @@ All relevant changes are documented in this file.
`/etc/finit.conf`.
For the complete experience a new top-level configuration file directive
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
`rcsd PATH` has also been added. It in turn can be used by `factory.conf`
as follows to override `/etc/finit.d`:
rcsd /etc/factory.d
@@ -732,7 +948,7 @@ make sure to read the whole change log when upgrading.
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
various distro packed udevd and other hotplugging tools
* A proper rescue mode has been added. It is started extremely early
and is protected with a bundled `suslogin`. Exiting rescue mode now
and is protected with a bundled `sulogin`. Exiting rescue mode now
brings up the system as a normal boot, as one expects
* Support for `sysv` start/stop scripts as well as monitoring forking
services, stared using `sysv` or `service` stanza
@@ -1563,40 +1779,46 @@ Major bug fix release.
* Initial release
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.5...HEAD
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
[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.1]: https://github.com/troglobit/finit/compare/4.0...4.1
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.11...HEAD
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
[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.1]: https://github.com/troglobit/finit/compare/4.0...4.1
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
[libuEv]: https://github.com/troglobit/libuev
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
+1 -1
View File
@@ -1,5 +1,5 @@
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+8 -3
View File
@@ -10,6 +10,10 @@ if DOC
SUBDIRS += doc
endif
if BASH
bashdir = $(BASH_DIR)
dist_bash_DATA = initctl
endif
# Compat hook
install-dev:
@make -C src install-pkgincludeHEADERS
@@ -30,6 +34,7 @@ release: distcheck
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
done
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
--enable-testserv-plugin --enable-x11-common-plugin \
--with-watchdog --with-keventd --with-fstab=/etc/fstab
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
--enable-testserv-plugin --enable-x11-common-plugin \
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
--with-bash-completion-dir=no
+27 -22
View File
@@ -3,7 +3,6 @@
* [Introduction](#introduction)
* [Features](#features)
* [Bootstrap](doc/bootstrap.md#bootstrap)
* [Runlevels](#runlevels)
* [Syntax](doc/config.md#syntax)
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
@@ -23,11 +22,10 @@ Introduction
------------
Fast init for Linux systems. Reverse engineered from the [EeePC
fastinit][] over ten years ago by [Claudio Matsuoka][] — "gaps filled
with frog DNA …"
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
![Alpine screenshot](img/finit4-screenshot.png)
*Figure 1: Screenshot showing Finit booting [Alpine Linux](https://www.alpinelinux.org/).*
![Alpine screenshot](img/alpine-screenshot2.png)
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
Features include:
@@ -63,10 +61,13 @@ distributions:
* [Alpine Linux](contrib/alpine/), and
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
> **Note:** support for various Linux distributions does not mean Finit
> installs easily on all architectures. The bundled install scripts are
> examples for standard installations, tested on amd64 (x86_64) systems.
> Custom setups, for embedded systems, can be found in [myLinux][].
> [!NOTE]
> Support for various Linux distributions does not mean Finit installs
> easily on all architectures. The bundled install scripts are examples
> for standard installations, tested on amd64 (x86_64) systems. Custom
> setups, e.g., for embedded systems, can be found in the following
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
Example
@@ -78,9 +79,10 @@ be placed in `/etc/finit.d/available` and enabled by an operator using
the [initctl](#commands--status) tool. See the above mentioned Linux
distributions, or [myLinux][].
> **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
> [!TIP]
> As of Finit v4.4, `.conf` lines can be broken up using the standard
> UNIX continuation character (`\`), trailing comments are now also
> 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).
@@ -285,6 +287,7 @@ run [S] /path/to/ident --
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
```
> [!TIP]
> Notice the trick with an empty description to hide the call to `ident`
> in the Finit progress output.
@@ -367,9 +370,10 @@ The `initctl` tool has three commands to help debug and optimize the
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
commands for details.
> **Note:** systems that do not support cgroups, specifically version 2,
> are automatically detected. On such systems the above functionality
> is disabled early at boot.
> [!NOTE]
> Systems that do not support cgroups, specifically version 2, are
> automatically detected. On such systems the above functionality is
> disabled early at boot.
Runparts & /etc/rc.local
@@ -391,8 +395,7 @@ Right after the runlevel change when all services have started properly,
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
If it exists and is an executable shell script Finit calls it at the very
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
in [doc/plugins.md](doc/plugins.md#hooks), and about the system bootstrap
in [doc/bootstrap.md](doc/bootstrap.md).
in [doc/plugins.md](doc/plugins.md#hooks).
### Limitations
@@ -406,8 +409,7 @@ The event loop is the whole thing which Finit is built around, except
for runlevel S, which remains a slow procession through a lot of set up,
with a few hooks and blocking call outs to external scripts.
However, not all `initctl` commands are prohibited, supported commands:
are:
However, not all `initctl` commands are prohibited. Supported commands:
- `inictl cond`: only operate of files in `/run/finit/cond`
- `initctl enable/disable`: enabled run/task/service is activated on
@@ -575,9 +577,10 @@ file must be used to tell Finit to stop and start it on `reload` and
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
these will also affect how a service is maintained.
> **Note:** even though it is possible to start services not belonging in
> the current runlevel these services will not be respawned automatically
> by Finit if they exit (crash). Hence, if the runlevel is 2, the below
> [!NOTE]
> Even though it is possible to start services not belonging in the
> current runlevel these services will not be respawned automatically by
> Finit if they exit (crash). Hence, if the runlevel is 2, the below
> Dropbear SSH service will not be restarted if it is killed or exits.
The `status` command is the default, it displays a quick overview of all
@@ -707,6 +710,8 @@ and proposed extensions.
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
[Claudio Matsuoka]: https://github.com/cmatsuoka
[Joachim Wiberg]: https://troglobit.com
[Buildroot]: https://buildroot.org
[Infix]: https://kernelkit.github.io
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
[License]: https://en.wikipedia.org/wiki/MIT_License
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
+70 -19
View File
@@ -1,4 +1,4 @@
AC_INIT([Finit], [4.5-rc4], [https://github.com/troglobit/finit/issues],
AC_INIT([Finit], [4.11], [https://github.com/troglobit/finit/issues],
[finit], [https://troglobit.com/projects/finit/])
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
@@ -15,10 +15,10 @@ AC_CONFIG_FILES([Makefile
man/Makefile
plugins/Makefile
src/Makefile
system/Makefile
tmpfiles.d/Makefile
system/Makefile system/10-hotplug.conf
test/test.env test/Makefile
test/lib/Makefile test/src/Makefile])
test/lib/Makefile test/src/Makefile
tmpfiles.d/Makefile])
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
#m4_include([m4/plugin.m4])
@@ -67,10 +67,18 @@ AC_ARG_ENABLE(fsckfix,
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
enable_fsckfix=no])
AC_ARG_ENABLE(cgroup,
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
enable_cgroup=yes])
AC_ARG_ENABLE(redirect,
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
enable_redirect=yes])
AC_ARG_ENABLE(kernel_logging,
AS_HELP_STRING([--disable-kernel-logging], [Disable kernel logging to console (use 'quiet' instead!]),,[
enable_kernel_logging=yes])
AC_ARG_ENABLE(logrotate,
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
enable_logrotate=yes])
@@ -94,18 +102,22 @@ AC_ARG_ENABLE(all_plugins,
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
AC_PLUGIN([modprobe], [yes], [Coldplug modules using modalias magic])
AC_PLUGIN([modprobe], [no], [Coldplug modules using modalias magic])
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
AC_PLUGIN([hotplug], [yes], [Start udevd or mdev kernel event datamon])
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
# Check for extra arguments or packages
AC_ARG_WITH([bash-completion-dir],
AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Directory to install Bash completion, default: auto]),
[bash_dir=$withval], [bash_dir=yes])
AC_ARG_WITH(fstab,
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
[fstab=$withval], [fstab=yes])
@@ -165,9 +177,13 @@ AC_ARG_WITH(plugin-path,
[plugin_path=$withval], [plugin_path=yes])
AC_ARG_WITH(rtc-date,
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM", default "2000-01-01 00:00"]),
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
[rtc_date=$withval], [rtc_date=no])
AC_ARG_WITH(rtc-file,
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
[rtc_file=$withval], [rtc_file=no])
### Enable features ###########################################################################
# Create config.h from selected features and fallback defaults
@@ -177,6 +193,12 @@ AS_IF([test "x$enable_auto_reload" = "xyes"], [
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
AS_IF([test "x$enable_kernel_logging" = "xyes"], [
AC_DEFINE(KERNEL_LOGGING, 1, [Keep kernel warn/err logs to console])])
AS_IF([test "x$enable_cgroup" = "xyes"], [
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
AS_IF([test "x$enable_fastboot" = "xyes"], [
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
@@ -196,6 +218,12 @@ AS_IF([test "x$enable_rescue" != "xno"], [
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
### With features ##############################################################################
AS_IF([test "x$bash_dir" = "xyes"], [
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
[BASH_DIR="$(pkg-config --variable=completionsdir bash-completion)"],
[BASH_DIR="$datadir/bash-completion/completions"])], [
BASH_DIR="$bash_dir"])
AS_IF([test "x$with_fstab" != "xno"], [
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
AC_EXPAND_DIR(fstab_path, "$fstab")
@@ -217,10 +245,9 @@ AC_DEFINE_UNQUOTED(FINIT_RCSD, "$rcsd_path", [Finit rcS.d/, default /etc/finit.d
AC_SUBST(FINIT_RCSD, "$rcsd_path")
AS_IF([test "x$with_rc_local" != "xno"], [
AS_IF([test "x$rclocal" = "xyes"], [
rclocal=$sysconfdir/rc.local])])
AC_EXPAND_DIR(rclocal_path, "$rclocal")
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])
AS_IF([test "x$rclocal" = "xyes"], [rclocal=$sysconfdir/rc.local])
AC_EXPAND_DIR(rclocal_path, "$rclocal")
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])])
AS_IF([test "x$with_sysconfig" != "xno"], [
AS_IF([test "x$sysconfig" != "xdefault"], [
@@ -255,9 +282,16 @@ AS_IF([test "x$with_random_seed" != "xno"], [
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
AS_IF([test "x$rtc_date" != "xno"], [
AC_DEFINE(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
rtc_date=""])
AS_IF([test "x$rtc_file" != "xno"], [
AS_IF([test "x$rtc_file" = "xyes"], [
rtc_file=/var/lib/misc/rtc])
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
AS_IF([test "x$with_sulogin" != "xno"], [
@@ -285,19 +319,27 @@ AS_IF([test "x$with_plugin_path" != "xno"], [
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
# Control build with automake flags
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
# Workaround for as-of-yet unreleased runstatedir support, planned for
# autoconf 2.70, which some major distros have backported.
AS_IF([test -z "$runstatedir"], runstatedir="$localstatedir/run")
AC_SUBST(runstatedir)
# Override default libdir, used for plugins and rescue.conf
pkglibdir=$libdir/finit
AC_SUBST(pkglibexecdir)
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
AC_EXPAND_DIR(finit_runpath, "$runstatedir/finit/system")
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "$finit_runpath", [Finit runtime dynamic system services])
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
AC_SUBST(plugin_path)
@@ -305,7 +347,7 @@ AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
AC_SUBST(tmpfiles_path)
AC_DEFINE_UNQUOTED(TMPFILES_PATH, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
AC_DEFINE_UNQUOTED(TMPFILES_PATH_, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
AC_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
AC_SUBST(finit_tmpfiles)
@@ -313,13 +355,16 @@ AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf p
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
AC_SUBST(system_path)
AC_DEFINE_UNQUOTED(FINIT_SYSPATH, "$system_path", [Static services, previously generated at runtime by plugins])
AC_DEFINE_UNQUOTED(FINIT_SYSPATH_, "$system_path", [Static services, previously generated at runtime by plugins])
AC_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
AC_EXPAND_DIR(bash_completion_dir, "$BASH_DIR")
AC_SUBST(BASH_DIR, "$bash_completion_dir")
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
@@ -334,15 +379,16 @@ cat <<EOF
------------------ Summary ------------------
$PACKAGE_NAME version $PACKAGE_VERSION
Prefix................: $prefix
Exec prefix...........: $eprefix
Prefix................: $(eval echo $prefix)
Exec prefix...........: $(eval echo $exec_prefix)
Libdir................: $(eval echo $libdir)
Sysconfdir............: `eval echo $sysconfdir`
Localstatedir.........: `eval echo $localstatedir`
Default fstab.........: `eval echo $fstab`
Finit config file.....: $conf_path
Finit config.d path...: $rcsd_path
Finit plugin path.....: $plugin_path
Compat rc.local path..: $rclocal_path
Compat rc.local path..: `eval echo $rclocal`
System environment....: ${sysconfig_path:-${sysconfig}}
Random seed path......: $random_path
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
@@ -352,14 +398,19 @@ Behavior:
Boot heading..........: $heading
Plugins...............: $plugins
RTC restore date......: $RTC_DATE
RTC fallback file.....: $rtc_file
Optional features:
Install doc/..........: $enable_doc
Install contrib/......: $enable_contrib
Bash completion.......: $bash_completion_dir
Built-in keventd......: $with_keventd
Built-in sulogin......: $with_sulogin $sulogin
Built-in watchdogd....: $with_watchdog $watchdog
Built-in logrotate....: $enable_logrotate
Use cgroup v2.........: $enable_cgroup
Parse kernel cmdline..: $enable_kernel_cmdline
Keep kernel logging...: $enable_kernel_logging
Skip fsck check.......: $enable_fastboot
Run fsck fix mode.....: $enable_fsckfix
Redirect output.......: $enable_redirect
+5 -2
View File
@@ -1,5 +1,8 @@
HowTo: Finit on Alpine Linux 3.4-3.6
====================================
HowTo: Finit on Alpine Linux 3.4...3.19
=======================================
> [!TIP]
> https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
the user has already installed make, a compiler, C library header files,
+1 -2
View File
@@ -1,8 +1,7 @@
SUBDIRS = available
docsdir := @docdir@/contrib/alpine/finit.d
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
keymap.conf modules.conf ntpd.conf \
klogd.conf syslogd.conf
keymap.conf modules.conf ntpd.conf syslogd.conf
install-exec-hook:
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
+1 -1
View File
@@ -1,4 +1,4 @@
docsdir := @docdir@/contrib/alpine/finit.d/available
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
lxdm.conf modules.conf ntpd.conf syslog.conf watchdog.conf
lxdm.conf modules.conf ntpd.conf syslogd.conf watchdog.conf
EXTRA_DIST = $(docs_DATA)
@@ -4,4 +4,4 @@
#module evdev
#module mousedev
#module 8139cp
module softdog
#module softdog
+35 -29
View File
@@ -1,45 +1,53 @@
#!/bin/sh
if [ "x`id -u`" != "x0" ]; then
echo
echo "*** This script must run as root"
echo
if [ "$(id -u)" != "0" ]; then
printf "\n\e[1m*** This script must run as root\e[0m\n\n"
exit 1
fi
# shellcheck disable=SC3037,SC3045,SC2154
yorn()
{
printf "\e[1m> %s (y/N)?\e[0m " "$*"
read -rn1 yorn
echo
if [ "$yorn" = "y" ] || [ "$yorn" = "Y" ]; then
return 0
fi
return 1
}
# Adjust base directory
grep -q alpine Makefile 2>/dev/null
if [ $? -eq 0 ]; then
if grep -q contrib/alpine Makefile 2>/dev/null; then
cd ../..
elif [ ! -e configure.ac ]; then
echo "*** Please run this script from the Finit base directory."
fi
if [ ! -e configure.ac ]; then
printf "\n\e[1m*** Please run this script from the Finit base directory.\e[0m\n"
exit 1
fi
echo
echo "*** Install Finit on Alpine Linux"
echo "========================================================================"
echo "/sbin/finit - PID 1"
echo "/lib/finit/plugins/* - All enabled Finit plugins"
echo "/etc/finit.conf - Finit configuration file"
echo "/etc/finit.d/ - Finit services"
echo
read -p "Do you want to continue (y/N)? " yorn
printf "\n\e[1mInstall Finit on Alpine Linux\n"
printf "========================================================================\e[0m\n"
printf "/sbin/finit - PID 1\n"
printf "/lib/finit/plugins/* - All enabled Finit plugins\n"
printf "/etc/finit.conf - Finit configuration file\n"
printf "/etc/finit.d/ - Finit services\n"
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
echo
echo "*** Installing Finit files ..."
if yorn "Do you want to continue"; then
printf "\n\e[1m*** Installing Finit files ...\e[0m\n"
make install
cd /usr/share/doc/finit/contrib/alpine
cd /usr/share/doc/finit/contrib/alpine || exit 1
for file in finit.conf rc.local; do
install -vbD $file /etc/$file
done
cp -va finit.d /etc/
read -p "*** Install Finit as the system default Init (y/N)? " yorn
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
echo "*** Updating /sbin/init symlink --> finit ..."
cd /sbin
if yorn "Install Finit as the system default Init"; then
printf "\e[1m*** Updating /sbin/init symlink --> finit ...\e[0m\n"
cd /sbin || exit 1
rm init
ln -s finit init
@@ -48,10 +56,8 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
ln -s reboot shutdown
ln -s reboot suspend
fi
echo "*** Done"
printf "\n\e[1m*** Done\e[0m\n"
echo
else
echo
echo "*** Aborting install."
echo
printf "\n\e[1m*** Aborting install.\e[0m\n\n"
fi
+5 -3
View File
@@ -20,8 +20,9 @@ tools pre-systemd work as intended.
root@debian:~# apt install initscripts console-setup
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
> the main section of Debian. So just install the -dev packages :)
> [!TIP]
> As of Debian 11 (Bullseye), libuev and libite are part of the main
> section of Debian. So just install the -dev packages :)
The following script can then be used to configure, build, install and
set up your system to run Finit:
@@ -47,7 +48,8 @@ comands to `initctl`, followed by `reload` to activate your changes.
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
and initialization like keyboard language etc.
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
> [!NOTE]
> For the X Window system, you may need to `sudo apt install elogind`
> (Bullseye and later), followed by `initctl reload` to activate it (it
> is enabled by default), and logout/login again. The elogind daemon
> ensures a regular non-root user can start and interact with an X
-59
View File
@@ -1,59 +0,0 @@
Bootstrap
=========
0. Get bearings, disable kernel logs, initialize TTY and print banner,
unless `HOOK_BANNER` is defined, then call that instead
1. Prepare emergency shell, if enabled
2. Set up initial signal handlers
3. Set up default $PATH early
4. Mount `/proc` and `/sys`
5. Check kernel command line for `debug` to figure out log level
6. Load all `.so` plugins
7. Call `fsck` on file systems listed in `/etc/fstab`
8. Populate `/dev` using either udev or mdev, depending on system type
9. Parse `/etc/finit.conf`
10. Start built-in watchdog, if enabled and `WDT_DEVNODE` exists. This
means any WDT that requires a kernel module need to be either
compiled into the kernel, or insmod'ed in `/etc/finit.conf`
11. Load all `/etc/finit.d/*.conf` files and set hostname
12. Remount `/` read-write if `/` is listed in `/etc/fstab` without `ro`
13. Call 1st level hooks, `HOOK_ROOTFS_UP`
14. Mount all file systems listed in `/etc/fstab` and swap, if available.
On mount error `HOOK_MOUNT_ERROR` is called. After mount, regardless
of error, `HOOK_MOUNT_POST` is called
15. Enable SysV init signals
16. Call 2nd level hooks, `HOOK_BASEFS_UP`
17. Cleanup stale files from `/tmp/*` et al, handled by `bootmisc` plugin
18. Load kernel params from `/etc/sysctl.d/*.conf`, `/etc/sysctl.conf`
et al. (Supports all locations that SysV init does.), handled by
`procps` plugin
19. Start all 'S' runlevel tasks and services
20. Bring up loopback interface and all `/etc/network/interfaces`, if
the `.conf` setting `network <SCRIPT>` is set, it is called instead
21. Call 3rd level hooks, `HOOK_NETWORK_UP`
22. If `runparts <DIR>` is set, [run-parts(8)][] is called on `<DIR>`
23. Switch to the configured runlevel from `/etc/finit.conf`, default 2.
At every runlevel change all `*.conf` files in `/etc/finit.d/` are
(re)loaded and new services, tasks, and blocking run commands are
started. Provided they are allowed in the new runlevel and all of
their conditions, if any, are set.
24. Call 4th level hooks, `HOOK_SVC_UP`
25. Call `/etc/rc.local`, if it exists and is an executable shell script
26. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
27. Start all configured TTYs
In (19) and (23) tasks and services defined in `/etc/finit.conf` and
`/etc/finit.d/*.conf` are started.
Notice the seven hook points that are called at various point in the
bootstrap process. This is where plugins can extend the boot in any
way they please. There are other hook points available, for more on
this, see [plugins.md](plugins.md).
For instance, at `HOOK_BASEFS_UP` a plugin could read an XML file from a
USB stick, convert/copy its contents to the system's `/etc/` directory,
well before all 'S' runlevel tasks are started. This could be used with
system images that are created read-only and all configuration is stored
on external media.
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
+30 -24
View File
@@ -1,5 +1,5 @@
Building
========
Building Finit
==============
* [Introduction](#introduction)
* [Configure](#configure)
@@ -17,14 +17,15 @@ optional plugins to enable. It depends on two external libraries:
- [libuEv][], the event loop
- [libite][] (-lite), much needed frog DNA
**NOTE:** Most free/open source software that uses `configure` default
to install to `/usr/local`. However, some Linux distributions do no
longer search that path for installed software, e.g. Fedora and Alpine
Linux. To get finit's configure script to find its dependencies you
have to help the `pkg-config` tool a bit if you do not change the
default prefix path:
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
> [!IMPORTANT]
> Most free/open source software packages that use `configure` default
> to install to `/usr/local`. However, some Linux distributions do no
> longer search that path for installed software, e.g. Fedora and Alpine
> Linux. To get finit's configure script to find its dependencies you
> have to help the `pkg-config` tool a bit if you do not change the
> default prefix path:
>
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
The configure script checks for all dependencies, including the correct
version of the above mentioned libraries. Currently required versions:
@@ -71,12 +72,13 @@ Below are a few of the main switches to configure:
For more configure flags, see <kbd>./configure --help</kbd>
> **Note:** the configure script is not available in the GIT sources. It is
> however included in (officially supported) released tarballs. The
> idea is that you should not need GNU autotools to build, only the
> above mentioned dependencies, a POSIX shell, a C compiler and make.
> Any contributing to Finit can generate it from `configure.ac` using
> the `autogen.sh` script.
> [!NOTE]
> The configure script is not available in the GIT sources. It is
> however included in (officially supported) released tarballs. The
> idea is that you should not need GNU autotools to build, only the
> above mentioned dependencies, a POSIX shell, a C compiler and make.
> Any contributing to Finit can generate it from `configure.ac` using
> the `autogen.sh` script.
Example
@@ -115,10 +117,11 @@ Linux config to:
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
**Note:** If you run into problems starting Finit, take a look at
`finit.c`. One of the most common problems is a custom Linux kernel
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
system `/etc/fstab`.
> [!TIP]
> If you run into problems starting Finit, take a look at `finit.c`.
> One of the most common problems is a custom Linux kernel build that
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
> `/etc/fstab`.
Running
@@ -157,8 +160,10 @@ enabled. The default Finit rescue mode configuration is installed into
By default the a root shell, without login, is started.
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
> force `reboot`, `shutdown`, or `poweroff`.
> [!IMPORTANT]
> In rescue mode `initctl` will not work, the same goes for `reboot`,
> `shutdown`, and `poweroff` commands, provided they are the Finit
> versions of these commands. Use the `-f` flag to force the action.
Debugging
@@ -187,8 +192,9 @@ kernel usually reboots: `configure --enable-emergency-shell`. However,
the behavior of Finit is severely limited when this is enabled, so use
it only for debugging start up issues when Finit crashes.
**NOTE:** Neither of these options should be enabled on production
systems since they can potentially give a user root access.
> [!CAUTION]
> None of these options should be enabled on production systems since
> they can potentially give a user root access.
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
+6 -4
View File
@@ -4,10 +4,11 @@ Tips & Tricks with the kernel cmdline
This document summarizes the different boot parameters that can be
passed on the Linux kernel command line. Not limited to Finit.
The `bool` setting is one of `on, off, true false, 1, 0`.
> [!IMPORTANT]
> Remember to use `--` to separate kernel parameters from parameters to
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
> **NOTE:** remember to use `--` to separate kernel parameters from
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
The `bool` setting is one of `on, off, true false, 1, 0`.
* `debug`: Enable kernel debug. Debug messages are printed to the
console until Finit starts up, unless `loglevel=7` (below) is used.
@@ -30,7 +31,8 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
Very useful for selecting different boot modes, e.g. manufacturing test,
firmware upgrade, or rescue mode.
> Note: `<boot/...>` conditions cannot be cleared with `initctl`!
> [!NOTE]
> `<boot/...>` conditions cannot be cleared with `initctl`!
* `finit.config=/path/to/alternative/finit.conf`: override the
compile-time bootstrap config file, default:
+44 -11
View File
@@ -27,6 +27,16 @@ specified separated by comma. Multiple conditions are logically AND'ed
during evaluation, i.e. all conditions must be satisfied in order for a
service to run.
A special syntax, using a leading `!` in run/task/service conditions,
denote if a:
- service does not support `SIGHUP`
- run/task should not block runlevel changes (i.e., bootstrap)
Finit guarantees by default that all run/tasks run (at least) once
per runlevel. For most tasks this is a good default, for example
checking SSH host keys or loading keymap. However, for conditions
that are unlikely to happen it is not. (See example below.)
### Example
@@ -37,9 +47,23 @@ both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
`pid/` condition is satisfied by the corresponding service's PID file
being created, i.e., the service's default readiness notification.
**NOTE:** Conditions also stop services when a condition is no longer
asserted. I.e., if the Zebra process above stops or restarts, netd
will also stop or restart.
> [!IMPORTANT]
> Conditions also stop services when a condition is no longer asserted.
> I.e., if the `zebra` process above stops or restarts, `netd` will also
> stop or restart.
Another example is `dropbear`, it does not support `SIGHUP`, but we can
also see optional sourcing of arguments from an environment file:
service [2345789] <!> env:-/etc/default/dropbear dropbear -F -R $DROPBEAR_ARGS -- Dropbear SSH daemon
Finally, the weird "block runlevel changes" example. Here we see what
happens when Finit receives `SIGPWR`, sent from a power daemon like
[powstatd(8)][]. A condition is asserted and a user can set up their
own task to act on it. We do not want this task to block Finit from
moving to the next runlevel after bootstrap, so we set `<!>`:
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
Triggering
@@ -83,11 +107,16 @@ on this, see [Internals](#internals).) Thus, after a reconfiguration it
is up to the "owner" of the condition to convey the new (or possibly
unchanged) state of it.
> **Note:** For `pid/` conditions it is expected that services "touch"
> or recreate their PID file on `SIGHUP`.
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
> [!IMPORTANT]
> For `pid/` conditions it is expected that the service reassert, i.e.,
> "touch" or recreate, their PID file on `SIGHUP`. This can be done by
> calling `utimensat()` on the PID file. Provided, of course, that the
> service supports reloading on `SIGHUP`, otherwise it will be restarted
> by Finit when they instead exit on the signal. For such services, use
> `<!>` to tell Finit the service does not support `SIGHUP`.
Built-in Conditions
-------------------
@@ -148,9 +177,10 @@ Built-in conditions:
- `boot/arg`
- `dev/node` and `dev/dir/node`
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
difference is that `running` tells if the NIC has link.
> [!NOTE]
> Here, `up` means administratively up, the interface flag `IFF_UP`.
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
> difference is that `running` tells if the NIC has link.
Composition
@@ -182,8 +212,9 @@ the service stanza for the daemon. It is far from optimal since any
synchronization of depending services may fail due to the daemon not
having reinitialized/created their IPC sockets, or similar.
> **Note:** in versions of Finit prior to v4, the PID conditions were
> called 'svc' conditions, and they were far more complex.
> [!NOTE]
> In versions of Finit prior to v4, the PID conditions were called 'svc'
> conditions, and they were far more complex.
Debugging
@@ -260,3 +291,5 @@ Therefore, any plugin that supplies Finit with conditions must ensure
that their state is updated after each reconfiguration. This can be
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
to do this, see `plugins/pidfile.c`.
[powstatd(8)]: https://manpages.ubuntu.com/manpages/trusty/en/man8/powstatd.8.html
+267 -148
View File
@@ -18,8 +18,8 @@ Finit Configuration
* [Alternate rcS.d/](#alternate-rcs-d-)
* [Resource Limits](#resource-limits)
* [Runlevels](#runlevels)
* [One-shot Commands (sequence)](#one-shot-commands--sequence-)
* [One-shot Commands (parallel)](#one-shot-commands--parallel-)
* [One-shot Commands (sequence)](#one-shot-commands-sequence)
* [One-shot Commands (parallel)](#one-shot-commands-parallel)
* [SysV Init Scripts](#sysv-init-scripts)
* [Services](#services)
* [Run-parts Scripts](#run-parts-scripts)
@@ -46,27 +46,58 @@ Plugins start at [hook points](plugins.md#hooks) and can run various set
up, or install event handlers that later provide runtime services, e.g.,
PID file monitoring, or [conditions](conditions.md).
> **Tip:** see [SysV Init Compatibility](#sysv-init-compatibility) for
> help to quickly get going with an existing SysV or BusyBox init setup.
> [!TIP]
> See [SysV Init Compatibility](#sysv-init-compatibility) for help to
> quickly get going with an existing SysV or BusyBox init setup.
### Configuration Files
Originally Finit was configured using a single file, `/etc/finit.conf`.
Although still possible to use this single configuration file, today the
following familiar layout is recommended:
Originally Finit was configured using a single file, `/etc/finit.conf`,
and although still possible to use a single configuration file, today
the following layout is recommended:
/etc/
|- finit.d/
| |- available/
| | `- my-service.conf
: |- enabled/
: | `- my-service.conf -> ../available/my-service.conf
: :
: |- static-service.conf
: `- another-static.conf
:
`- finit.conf
/
|- etc/
| |- finit.d/
| | |- available/
| | | `- my-service.conf
| : |- enabled/
| : | `- my-service.conf -> ../available/my-service.conf
| : :
| : |- static-service.conf
| : `- another-static.conf
| :
| `- finit.conf
|- lib
| `- finit/
| `- system/
| |- 10-hotplug.conf
| `- ...
`- run/
`- finit/
`- system/
|- dbus.conf
|- keventd.conf
|- runparts.conf
|- watchdogd.conf
`- ...
Configuration files in `/etc` are provided by the user, or projects like
[finit-skel](https://github.com/troglobit/finit-skel) and extended by
the user.
The files in `/lib/finit/system/*.conf` are system critical services and
setup provided by Finit, e.g. udev/mdev that must run very early at system
bootstrap. This system directory was introduced in Finit v4.4 to replace
the hard-coded services provided by plugins before. All .conf files in this
directory be either replaced by a system administrator or overridden by a
file with the same name in `/etc/finit.d/`.
The files in `/run/finit/system/*.conf` are created by plugins and Finit
bundled services like runparts, the [watchdog](#watchdog), and `keventd`
if they are enabled. Like `/lib/finit/system/*.conf`, these files can
be overridden by file with the same name in `/etc/finit.d/`.
Services in the `available/` and `enabled/` sub-directories are called
dynamic services, in contrast to static services -- the only difference
@@ -75,12 +106,31 @@ with the `enable` and `disable` commands. An administrator can always
create files and symlinks manually.
At bootstrap, and `initctl reload`, all .conf files are read, starting
with `finit.conf`, then, in alphabetical order, all `finit.d/*.conf`
files, and finally (still in alphabetical order) all `enabled/*.conf`
files.
with `finit.conf`, then `/lib/finit/system/*.conf`, `finit.d/*.conf`,
and finally all `finit.d/enabled/*.conf` files. Each directory is a
unique group, where files within each group are sorted alphabetically.
> **Note:** the `finit.conf` and `finit.d/` names are only defaults.
> They can be changed at compile-time with two `configure` options:
**Example:**
/lib/finit/system/10-hotplug.conf
/lib/finit/system/90-testserv.conf
/run/finit/system/dbus.conf
/run/finit/system/runparts.conf
/etc/finit.d/10-abc.conf
/etc/finit.d/20-abc.conf
/etc/finit.d/enabled/1-aaa.conf
/etc/finit.d/enabled/1-abc.conf
The resulting combined configuration is read line by line, each `run`,
`task`, and `service` added to an ordered list that ensures they are
started in the same order. This is important because of the blocking
properties of the `run` statement. For an example on the relation of
`service` and `run` statements, and dependency handling between them,
see [Conditional Loading](#conditional-loading), below.
> [!NOTE]
> The names `finit.conf` and `finit.d/` are only defaults. They can be
> changed at compile-time with two `configure` options:
> `--with-config=/etc/foo.conf` and `--with-rcsd=/var/foo.d`.
>
> They can also be overridden from the [kernel command line](cmdline.md)
@@ -126,18 +176,23 @@ layout, as specified in the [FHS][]:
|- spool/
`- tmp/
Finit starts (very early) by mounting `/dev`, `/proc/`, and `/sys`,
unless they (i.e., `/dev`) are already mounted. When all plugins and
other, core Finit functions, have been set up, all relevant filesystems
(`PASS > 0`) are checked and mounted from the selected `fstab`, either
Finit starts by mounting the critical file systems `/dev`, `/proc/`, and
`/sys`, unless they are already mounted. When all plugins and other,
core Finit functions, have been set up, all relevant filesystems (where
`PASS > 0`) are checked and mounted from the selected `fstab`, either
the default `/etc/fstab`, or any custom one selected from the command
line, or at build time.
Any file system not listed `fstab` are automatically mounted by Finit,
as listed above, provided their respective mount point exists.
To provide a smooth ride, file system not listed in the given `fstab`,
e.g. `/tmp` and `/run`, are automatically mounted by Finit, as listed
above, provided their respective mount point exists.
With all filesystems mounted, Finit calls `swapon`.
> [!TIP]
> To see what happens when all filesystems are mounted, have a look at
> the [`bootmisc.so` plugin](plugins.md).
At shutdown, and after having stopped all services and other lingering
processes have been killed, filesystems are unmounted in the reverse
order, and `swapoff` is called.
@@ -146,6 +201,18 @@ order, and `swapoff` is called.
### Runlevels
Finit supports runlevels, but unlike other init systems runlevels are
declared per service/run/task/sysv command. When booting up a system
Finit pass through three phases:
1. Setting up the console, parsing any command line options, and other
housekeeping tasks like mounting all filesystems, and calling `fsck`
2. Starting all run/task/services in runlevel S, then waiting for all
services to have started, and all run/tasks to have completed
3. Go to runlevel 2, or whatever the user has set in the configuration
Available runlevels:
- ` S`: bootStrap
- ` 1`: Single user mode
- `2-5`: traditional multi-user mode
@@ -153,36 +220,40 @@ order, and `swapoff` is called.
- `7-9`: multi-user mode (extra)
- ` 0`: shutdown
Runlevels are declared per service/run/task/sysv command. Starting in
runlevel S ([bootStrap](bootstrap.md)), usually only for tasks supposed
to run once at boot, and services like `syslogd`, which you need to
start and run throughout the whole time your system is up. Before `S`
is started, however, Finit performs a lot of housekeeping tasks like
mounting all filesystems, calling `fsck` if needed, and making sure the
everything is OK.
Runlevel S (bootStrap), is for tasks supposed to run once at boot, and
services like `syslogd`, which need to start early and run throughout
the lifetime of your system.
Example:
task [S] /lib/console-setup/console-setup.sh
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
After runlevel S, Finit proceeds to runlevel 2. This can be changed in
`/etc/finit.conf` using the `runlevel N` directive, or by a script
running in runlevel S that calls, e.g., `initctl runlevel 9`. The
latter is useful if startup scripts detect problems outside of Finit's
control, e.g., critical services/devices missing or hardware problems.
When bootstrap has completed, Finit moves to runlevel 2. This can be
changed in `/etc/finit.conf` using the `runlevel N` directive, or by a
script running in runlevel S that calls, e.g., `initctl runlevel 9`.
The latter is useful if startup scripts detect problems outside of
Finit's control, e.g., critical services/devices missing or hardware
problems.
Before starting the services in runlevel 2, Finit first stops everything
that is not allowed to run in 2, and then brings up networking.
Networking is expected to be available in all runlevels except: S, 1
(single user level), 6, and 0. Networking is enabled either by the
`network script` directive, or if you have an `/etc/network/interfaces`
file, Finit calls `ifup -a` -- at the very least the loopback interface
is brought up.
Each runlevel must be allowed to "complete". Meaning, all services in
runlevel S must have started and all run/tasks have been started and
collected (exited). Finit waits 120 seconds for all run/tasks in S to
complete before proceeding to 2.
> **Note:** when moving from runlevel S to 2, all run/task/services that
> were constrained to runlevel S only are dropped from bookkeeping. So
> when reaching the prompt, `initctl` will not show these run/tasks.
> This is a safety mechanism to prevent bootstrap-only tasks from
> accidentally being run again. E.g., `console-setup.sh` above.
Finit first stops everything that is not allowed to run in 2, and then
brings up networking. Networking is expected to be available in all
runlevels except: S, 1 (single user level), 6, and 0. Networking is
enabled either by the `network script` directive, or if you have an
`/etc/network/interfaces` file, Finit calls `ifup -a` -- at the very
least the loopback interface is brought up.
> [!NOTE]
> When moving from runlevel S to 2, all run/task/services that were
> constrained to runlevel S only are dropped from bookkeeping. So when
> reaching the prompt, `initctl` will not show these run/tasks. This is
> a safety mechanism to prevent bootstrap-only tasks from accidentally
> being run again. E.g., `console-setup.sh` above.
### Managing Services
@@ -269,7 +340,8 @@ the `ps` command we can see that the process is started with:
foo -n --extra-arg=bar -s -x
> **Note:** the leading `-` determines if Finit should treat a missing
> [!NOTE]
> The leading `-` in `env:` determines if Finit should treat a missing
> environment file as blocking the start of the service or not. When
> `-` is used, a missing environment file does *not* block the start.
@@ -303,26 +375,41 @@ most notably systemd and s6, other methods for signaling "readiness"
arrived and daemons were adapted to these new schemes to a larger
extent.
As of Finit v4.4 partial support for systemd and s6 is available. The
native PID file mode of operation is still default, the other's can be
defined per service, like this:
As of Finit v4.4 partial support for systemd and s6 style readiness
notification is available, and the native PID file mode of operation is,
as of Finit v4.6 optional, by default it is still enabled, but this can
be changed in `finit.conf`:
readiness none
This will be made the default in Finit 5.0. In this mode of operation,
every service needs to explicitly declare their readiness notification,
like this:
service notify:pid watchdogd
service notify:systemd foo
service notify:s6 bar
service notify:none qux
The `notify:none` syntax is for completeness in systems which run in
`readiness pid` mode (default). Services declared with `notify:none`
will assert ready condition as soon as Finit has started them, e.g.,
`service/qux/ready`.
To synchronize two services the following condition can be used:
service notify:systemd A
service <service/A/ready> B
service notify:pid watchdogd
service <service/watchdogd/ready> stress-ng --cpu 8
For details on the syntax and options, see below.
> **Note:** on `initctl reload` conditions are normally set in "flux",
> while figuring out which to stop, start or restart. Services that
> need to be restarted have their `ready` condition removed prior to
> Finit sending them SIGHUP (if they support that), or stop-starting
> them. A daemon is expected to reassert its readiness, e.g. systemd
> style daemons to write `READY=1\n`.
> [!NOTE]
> On `initctl reload` conditions are set in "flux", while figuring out
> which to stop, start or restart. Services that need to be restarted
> have their `ready` condition removed prior to Finit sending them
> SIGHUP (if they support that), or stop-starting them. A daemon is
> expected to reassert its readiness, e.g. systemd style daemons to
> write `READY=1\n`.
>
> However, the s6 notify mode does not support this because in s6 you
> are expected to close your notify descriptor after having written
@@ -362,9 +449,10 @@ example employs a wrapper script in `/etc/start.d`.
# Execute the program
exec /usr/bin/program $OPTIONS
> **Note:** the example sets `<!>` to denote that it doesn't support
> `SIGHUP`. That way Finit will stop/start the service
> instead of sending SIGHUP at restart/reload events.
> [!NOTE]
> The example sets `<!>` to denote that it doesn't support `SIGHUP`.
> That way Finit will stop/start the service instead of sending SIGHUP
> at restart/reload events.
Templating
@@ -392,7 +480,7 @@ Cgroups
There are three major cgroup configuration directives:
1. Global top-level group: init, system, user, or a custom group
1. Global top-level group: `init`, `system`, `user`, or a custom group
2. Selecting a top-level group for a set of run/task/services
3. Per run/task/service limits
@@ -443,6 +531,11 @@ except for expanding the shorthand `mem.` to `memory.`, if the file is
not available, either the cgroup controller is not available in your
Linux kernel, or the name is misspelled.
A daemon using `SCHED_RR` currently need to run outside the default cgroups.
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
> [!NOTE]
> Linux cgroups and details surrounding values are not explained in the
> Finit documentation. The Linux admin-guide cover this well:
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
@@ -468,12 +561,9 @@ service name:sysklogd [S123456789] \
```
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
following directives:
> **Note:** not all directives are available in `/etc/finit.d/*.conf`
> and some directives are only available at [bootstrap][], runlevel `S`,
> see [Limitations](#limitations) below for details.
following directives. Some directives have restrictions, e.g., only
available at bootstrap, runlevel `S`, see [Limitations](#limitations)
below for details.
### Hostname
@@ -485,7 +575,8 @@ the contents of that file is used.
Deprecated. We recommend using `/etc/hostname` instead.
> **Note:** only read and executed in runlevel S ([bootstrap][]).
> [!NOTE]
> Only read and executed in runlevel S (bootstrap).
### Kernel Modules
@@ -503,7 +594,8 @@ BusyBox mdev tool, add to `/etc/mdev.conf`:
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
> **Note:** only read and executed in runlevel S ([bootstrap][]).
> [!NOTE]
> Only read and executed in runlevel S (bootstrap).
### Networking
@@ -516,7 +608,8 @@ Deprecated. We recommend using dedicated task/run stanzas per runlevel,
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
> **Note:** only read and executed in runlevel S ([bootstrap][]).
> [!NOTE]
> Only read and executed in runlevel S (bootstrap).
### Alternate finit.d/
@@ -537,8 +630,9 @@ another set of .conf files, e.g.:
rcsd /etc/factory.d
> **Note:** this directive is only available from the top-level
> bootstrap .conf file.
> [!NOTE]
> This directive is only available from the top-level bootstrap .conf
> file, usually `/etc/finit.conf`.
### Resource Limits
@@ -571,16 +665,18 @@ stanzas can share the same rlimits if they are in the same .conf.
**Syntax:** `runlevel <N>`
The system runlevel to go to after [bootstrap][] (S) has completed. `N`
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
halt.
The system runlevel to go to after bootstrap (S) has completed. `N` is
the runlevel number 0-9, where 6 is reserved for reboot and 0 for halt.
Completed in this context means all services have been started and all
run/tasks have been started and collected.
It is recommended to keep runlevel 1 as single-user mode, because
Finit disables networking in this mode.
*Default:* 2
> **Note:** only read and executed in runlevel S ([bootstrap][]).
> [!NOTE]
> Only read and executed in runlevel S (bootstrap).
### One-shot Commands (sequence)
@@ -594,10 +690,11 @@ optional arguments and description. `run` commands are guaranteed to be
completed before running the next command. Useful when serialization is
required.
> **Warning:** try to avoid the `run` command. It blocks much of the
> functionality in Finit, like (re)starting other (perhaps crashing)
> services while a `run` task is executing. Use other synchronization
> mechanisms instead, like conditions.
> [!WARNING]
> Try to avoid the `run` command. It blocks much of the functionality
> in Finit, like (re)starting other (perhaps crashing) services while a
> `run` task is executing. Use other synchronization mechanisms
> instead, like conditions.
Incomplete list of unsupported `initctl` commands in `run` tasks:
@@ -620,11 +717,14 @@ also the `--quiet` and `--batch` options.
One-shot like 'run', but starts in parallel with the next command.
Both `run` and `task` commands are run in a shell, so pipes and
redirects can be freely used:
Both `run` and `task` commands are run in a shell, so basic pipes and
redirects can be used:
task [s] echo "foo" | cat >/tmp/bar
Please note, `;`, `&&`, `||`, and similar are *not supported*. Any
non-trivial constructs are better placed in a separate shell script.
### SysV Init Scripts
@@ -634,7 +734,7 @@ redirects can be freely used:
Similar to `task` is the `sysv` stanza, which can be used to call SysV
style scripts. The primary intention for this command is to be able to
re-use much of existing setup and init scripts in Linux distributions.
reuse much of existing setup and init scripts in Linux distributions.
When entering an allowed runlevel, Finit calls `init-script start`, when
entering a disallowed runlevel, Finit calls `init-script stop`, and if
@@ -649,7 +749,8 @@ file, but rather watch that file for the resulting forked-off PID. This
syntax also works for forking daemons that do not have a command line
option to run it in the foreground, more on this below in `service`.
> **Tip:** see also [SysV Init Compatibility](#sysv-init-compatibility).
> [!TIP]
> See also [SysV Init Compatibility](#sysv-init-compatibility).
### Services
@@ -657,13 +758,13 @@ option to run it in the foreground, more on this below in `service`.
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
Service, or daemon, to be monitored and automatically restarted if it
exits prematurely. Finit tries to restart services that die, by
default 10 times before giving up and marking them as *crashed*.
After which they have to be manually restarted with `initctl restart
NAME`. The limits controling this are configurable, see the options
below.
exits prematurely. Finit tries to restart services that die, by default
10 times before giving up and marking them as *crashed*. After which
they have to be manually restarted with `initctl restart NAME`. The
limits controlling this are configurable, see the options below.
> **Tip:** to allow endless restarts, see below option `respawn`
> [!TIP]
> To allow endless restarts, see below option `respawn`
For daemons that support it, we recommend appending `--foreground`,
`--no-background`, `-n`, `-F`, or similar command line argument to
@@ -816,33 +917,52 @@ configurable with the following options:
* `oncrash:script` -- similarly, but instead of rebooting, call the
`post:script` action if set, see below.
When stopping a service (run/task/sysv/service), either manually or
when moving to another runlevel, Finit starts by sending `SIGTERM`, to
allow the process to shut down gracefully. If the process has not
been collected within 3 seconds, Finit sends `SIGKILL`. To halt the
process using a different signal, use the option `halt:SIGNAL`, e.g.,
`halt:SIGPWR`. To change the delay between your halt signal and KILL,
use the option `kill:SEC`, e.g., `kill:10` to wait 10 seconds before
sending `SIGKILL`.
When stopping a service (run/task/sysv/service), either manually or when
moving to another runlevel, Finit starts by sending `SIGTERM`, to allow
the process to shut down gracefully. However, if the process has not
been collected within 3 seconds, Finit will send `SIGKILL`. To stop the
process using a different signal than `SIGTERM`, use `halt:SIGNAL`,
e.g., `halt:SIGPWR`. To change the delay between the stop signal and
KILL, use the option `kill:<1-60>`, e.g., `kill:10` to wait 10 seconds
before sending `SIGKILL`.
Services support `pre:script` and `post:script` actions as well. These
run as the same `@USER:GROUP` as the service itself, with any `env:file`
sourced. The scripts must use an absolute path, but are executed from
the `$HOME` of the given user. The scripts are not called with any
argument (currently), but both get the `SERVICE_IDENT=foo` environment
variable set. Here `foo` denotes the identity of the service, which if
there are multiple services named `foo`, may be `foo:1`, or any unique
identifier specified in the .conf file. The `post:script` is called
with an additional set of environment variables:
Services, including the `sysv` variant, support pre/post/ready and
cleanup scripts:
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
* `pre:[0-3600,]script` -- called before the sysv/service is stated
* `post:[0-3600,]script` -- called after the sysv/service has stopped
* `ready:[0-3600,]script` -- called when the sysv/service is ready
* `cleanup:[0-3600,]script` -- called when run/task/sysv/service is removed
The optional number (0-3600) is the timeout before Finit kills the
script, it defaults to the kill delay value and can be disabled by
setting it to zero. These scripts run as the same `@USER:GROUP` as the
service itself, with any `env:file` sourced. The scripts are executed
from the `$HOME` of the given user. The scripts are not called with any
argument, but get a set of environment variables:
* `SERVICE_IDENT=foo:1`
* `SERVICE_NAME=foo`
* `SERVICE_ID=1`
The `post:script` is called with an additional set of environment
variables. Yes, the text is correct, the naming was an accident:
- `EXIT_CODE=[exited,signal,crashed]`: normal exit, signaled, or
crashed
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
the program, if it exited normally, or the signal name (`HUP`,
`TERM`, etc.) if it exited due to signal
These script actions *must terminate*, so they have a default execution
time of 3 seconds before they are SIGKILLed, this can be adjusted using
the above `kill:SEC` syntax.
When a run/task/sys/service is removed (disable + reload) it is first
stopped and then removed from the runlevel. The `post:script` always
runs when the process has stopped, and the `cleanup:script` runs when
the the stanza has been removed from the runlevel.
> [!IMPORTANT]
> These script actions are intended for setup, cleanup, and readiness
> notification. It is up to the user to ensure the scripts terminate.
#### Conditional Loading
@@ -860,7 +980,7 @@ if that is not found Finit automatically logs a warning. The `nowarn`
option disables this warning so that the second line can be evaluated,
which also provides a service named `udevd`.
run nowarn if:udevd <pid/udevd> udevadm settle -t 0
run nowarn if:udevd <pid/udevd> :1 udevadm settle -t 0
This line is only loaded if we know of a service named `udevd`. Again,
we do not warn if `udevadm` is not found, Execution will also stop here
@@ -915,9 +1035,8 @@ previous stanza can also be written as:
**Syntax:** `runparts [progress] [sysv] <DIR>`
Call [run-parts(8)][] on `DIR` to run start scripts. All executable
files, or scripts, in the directory are called, in alphabetic order.
The scripts in this directory are executed at the very end of runlevel
`S`, [bootstrap][].
files in the directory are called, in alphabetic order. The scripts in
this directory are executed at the very end of runlevel `S`.
A common use-case for runparts scripts is to create and enable/disable
services, which Finit will then apply when changing runlevel from S to
@@ -942,10 +1061,10 @@ before continuing. None of them can issue commands to start, stop, or
restart other services. Also, ensure all your services and programs
either terminate or start in the background or you will block Finit.
> **Note:** `runparts` scrips are only read and executed in runlevel S
> ([bootstrap][]). See [hook scripts](plugins.md#hooks) for other ways
> to run scripts at certain points during the complete lifetime of the
> system.
> [!NOTE]
> `runparts` scripts are only read and executed in runlevel S. See
> [hook scripts](plugins.md#hooks) for other ways to run scripts at
> certain points during the complete lifetime of the system.
**Recommendations:**
@@ -1058,8 +1177,8 @@ can be omitted to keep the kernel default.
tty [12345] @console noclear vt220
On really bare bones systems, or for board bringup, Finit can give you a
shell prompt as soon as [bootstrap][] is done, without opening any
device node:
shell prompt as soon as bootstrap is done, without opening any device
node:
tty [12345789] notty
@@ -1217,8 +1336,9 @@ This rescue mode can be disabled at configure time using:
The rescue mode comes in two flavors; *traditional* and *fallback*.
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
> force `reboot`, `shutdown`, or `poweroff`.
> [!NOTE]
> In this mode `initctl` will not work. Use the `-f` flag to force
> `reboot`, `shutdown`, or `poweroff`.
### Traditional
@@ -1230,11 +1350,12 @@ program is used instead. If a successful login is made, or if the user
exits (Ctrl-D), the rescue mode is ended and the system boots up
normally.
> **Note:** the bundled sulogin in Finit can at configure time be given
> another user than the default (root). If the sulogin user does not
> have a password, or __the account is locked__, the user is presented
> with a password-less `"Press enter to enter maintenance mode."`,
> prompt which opens up a root shell.
> [!WARNING]
> The bundled sulogin in Finit can at configure time be given another
> user than the default (root). If the sulogin user does not have a
> password, or __the account is locked__, the user is presented with a
> prompt: `"Press enter to enter maintenance mode."`, which will open
> up a root shell *without prompting for password*!
### Fallback
@@ -1282,10 +1403,11 @@ These can now also be set in any `.conf` file in `/etc/finit.d`.
There is, however, nothing preventing you from having all configuration
settings in `/etc/finit.conf`.
> **Note:** The `/etc/finit.d` directory was previously the default
> Finit [runparts](#run-parts-scripts) directory. Finit >=v4.0
> no longer has a default `runparts` directory, make sure to
> update your setup, or the finit configuration, accordingly.
> [!IMPORTANT]
> The default `rcsd`, i.e., `/etc/finit.d`, was previously the Finit
> [runparts](#run-parts-scripts) directory. Finit >=v4.0 no longer has
> a default `runparts` directory, make sure to update your setup, or the
> finit configuration, accordingly.
Watchdog
@@ -1294,12 +1416,11 @@ Watchdog
When built `--with-watchdog` a separate service is built and installed
in `/libexec/finit/watchdogd`. If this exists at runtime, and the WDT
device node exists, Finit will start it and treat it as the elected
watchdog service to delegate its reboot to. See [bootstrap][] for
details. This delegation is to ensure that the system is rebooted by a
hardware watchdog timer -- on many embedded systems this is crucial to
ensure all circuits on the board are properly reset for the next boot,
in effect ensuring the system works the same after both a power-on and
reboot event.
watchdog service to delegate its reboot to. This delegation is to
ensure that the system is rebooted by a hardware watchdog timer -- on
many embedded systems this is crucial to ensure all circuits on the
board are properly reset for the next boot, in effect ensuring the
system works the same after both a power-on and reboot event.
The delegation is performed at the very last steps of system shutdown,
if reboot has been selected and an elected watchdog is known, first a
@@ -1321,8 +1442,6 @@ device descriptor. If the kernel driver has been built without this,
the only option is to remove `/libexec/finit/watchdogd` or build without
it at configure time.
[bootstrap]: bootstrap.md
keventd
-------
+3 -2
View File
@@ -34,8 +34,9 @@ build time:
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
```
> **Note:** remember `--prefix` et al as well, the default is likely
> *not* what you want. See the [build docs][1] for details.
> [!IMPORTANT]
> Remember `--prefix` et al as well, the default is likely *not* what
> you want. See the [build docs][1] for details.
The resulting directory structure is depicted below. Please notice how
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
+35 -18
View File
@@ -28,9 +28,17 @@ For your convenience a set of *optional* plugins are available:
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
file systems must be writable for this plugin to work.
Note: On an embedded system both `/var` and `/run` can be `tmpfs` RAM
disks and `/dev` is usually a `devtmpfs`. This must be defined in the
`/etc/fstab` file and in the Linux kernel config.
This plugin is a wrapper for the [tmpfiles.d(5)][] implementation that
Finit has. Capable but limited: no aging, attributes, or subvolumes.
By default, `/lib/finit/tmpfiles.d` carries all the default .conf
files distributed with Finit. It is read first but can be overridden
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
> [!NOTE]
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
> disks and `/dev` is usually a `devtmpfs`. This must be defined in
> the `/etc/fstab` file and in the Linux kernel config.
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
_Optional plugin._
@@ -50,11 +58,15 @@ For your convenience a set of *optional* plugins are available:
customized at build-time using the `--with-hook-scripts-path=PATH`
argument to `configure`.
* *hotplug.so*: Setup and start either udev or mdev hotplug daemon, if
available. Enabled by default.
* *hotplug.so*: Replaced with `/lib/finit/system/10-hotplug.conf`, which
checks for `udevd` and `mdev` at boot. This file can be overridden by a
file in `/etc/finit.d/10-hotplug.conf`.
Enabled by default.
> See the [Services](config.md#services) section in the configuration
> guide for an example how to run `mdevd`, alternative to plain mdev.
> [!TIP]
> See the [Services](config.md#services) section in the configuration
> guide for an example how to run `mdevd`, alternative to plain mdev.
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
Enabled by default.
@@ -79,16 +91,17 @@ For your convenience a set of *optional* plugins are available:
set index 1234
**Note:** unlike the traditional .conf `module` directive, which load
any listed module immediately, this plugin creates a background `task`
which load the module(s) in the background. The program is modprobe,
`/sbin/modprobe`, which you can override per .conf file:
Since these tasks run in the background, they return `[ OK ]` at boot,
unless the modprobe tool does not exist. Check syslog for warnings
and the actual status of the operation using `initctl`.
set modprobe /path/to/maybe-a-modprobe-wrapper
Since these tasks run in the background, they usually return `[ OK ]`
at boot, unless the modprobe tool does not exist. Check syslog for
warnings and the actual status of the operation using `initctl`.
> [!IMPORTANT]
> Unlike the traditional .conf `module` directive, which load any listed
> module immediately, this plugin creates a background `task` which load
> the module(s) in the background. The program is modprobe,
> `/sbin/modprobe`, which you can override per .conf file:
>
> set modprobe /path/to/maybe-a-modprobe-wrapper
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
interfaces. These events are then sent to the Finit service monitor
@@ -148,8 +161,10 @@ hook points:
EOF
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
> [!IMPORTANT]
> To use hook scripts, even for pre-bootstrap and pre-shutdown tasks,
> you must build with `configure --enable-hook-scripts-plugin`.
### Bootstrap Hooks
@@ -217,3 +232,5 @@ Plugins like `tty.so` extend finit by acting on events, they are called
I/O plugins and are called from the finit main loop when `poll()`
detects an event. See the source code for `plugins/*.c` for more help
and ideas.
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
+3 -2
View File
@@ -22,8 +22,9 @@ Finit can *not* start and monitor a daemon that:
| ✔ | No | No | Yes, optionally |
| ✘ | Yes | No | No |
> **Note:** PID files is one mechanism used to assert conditions to
> synchronize the start and stop of other, dependent, services.
> [!NOTE]
> PID files is one mechanism used to assert conditions to synchronize
> the start and stop of other, dependent, services.
### Forks to Background w/ PID File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 320 KiB

+2 -2
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 814 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File
+39 -25
View File
@@ -175,13 +175,13 @@ task [s] echo "foo" | cat >/tmp/bar
.Ed
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
Similar to
.Cm task
.Cm service
is the
.Cm sysv
stanza, which can be used to call SysV style start/stop scripts. The
primary intention for this command is to be able to re-use much of
existing setup and init scripts in Linux distributions.
.Pp
primary intention for this command is to be able to re-use traditional
SysV init scripts in Linux distributions.
.Pp
When entering an allowed runlevel, Finit calls
.Cm init-script start ,
when entering a disallowed runlevel, Finit calls
@@ -434,30 +434,42 @@ e.g.,
.Cm kill:10
to wait 10 seconds before sending SIGKILL.
.Pp
Services support the
.Cm pre:script
and
.Cm post:script
command actions as well. These run as the same
Services, including the
.Cm sysv
variant, support pre/post/ready and cleanup scripts:
.Bl -tag -width 1n
.It Cm pre:[0-3600,]script
called before the sysv/service is stated
.It Cm post:[0-3600,]script
called after the sysv/service has stopped
.It Cm ready:[0-3600,]script
called when the sysv/service is ready
.It Cm cleanup:[0-3600,]script
called when run/task/sysv/service is removed
.El
.Pp
The optional number (0-3600) is the timeout before Finit kills the
script, it defaults to the kill delay value and can be disabled by
setting it to zero. These scripts run as the same
.Cm @USER:GROUP
as the service itself, with any
.Cm env:file
sourced. The scripts must use an absolute path, but are executed from
the
.Cm $HOME
of the given user. The scripts are not called with any argument
(currently), but both get the
.Cm SERVICE_IDENT=foo
environment variable set. Here
.Cm foo
denotes the identity of the service, which if there are multiple
services named
.Cm foo ,
may be
.Cm foo:1 ,
or any unique identifier specified in the .conf file. The
of the given user. The scripts are not called with any argument, but
both get a set of environment variables:
.Pp
.Bl -tag -width 1n -compact
.It Cm SERVICE_IDENT=foo:1
.It Cm SERVICE_NAME=foo
.It Cm SERVICE_ID=1
.El
.Pp
The
.Cm post:script
is called with an additional set of environment variables:
is called with an additional set of environment variables, and yes the
naming looks like it should be swapped:
.Bl -tag -offset indent -width 1n
.It Cm EXIT_CODE=[exited,signal,crashed]
set to one of
@@ -471,10 +483,12 @@ set to one of exit status code from the program, if it exited normally,
or the signal name (HUP, TERM, etc.) if it exited due to signal
.El
.Pp
The scripts have a default execution time of 3 seconds before they are
SIGKILLed, this can be adjusted using the
.Cm kill:SEC
modifier syntax.
When a run/task/sys/service is removed (disable + reload) it is first
stopped and then removed from the runlevel. The
.Cm post:script
always runs when the process has stopped, and the
.Cm cleanup:script
runs when the the stanza has been removed from the runlevel.
.It Cm runparts Aq DIR
Call
.Xr run-parts 8
+1 -1
View File
@@ -1,6 +1,6 @@
/* Save and restore ALSA sound settings using alsactl
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* Setup necessary system files for, e.g. UTMP (tracking logins)
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+6 -7
View File
@@ -1,6 +1,6 @@
/* Setup and start system message bus, D-Bus
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -83,6 +83,7 @@ static char *dbus_pidfn(void)
break;
}
*pos = 0;
break;
}
fclose(fp);
@@ -142,23 +143,21 @@ static void setup(void *arg)
/* Generate machine id for dbus */
if (whichp("dbus-uuidgen"))
run_interactive("dbus-uuidgen --ensure", "Creating machine UUID for D-Bus");
run_interactive("dbus-uuidgen --ensure", "Verifying D-Bus machine UUID");
/*
* Register service with Finit
* Note: dbus drops privs after starting up.
*/
if (pidfn) {
snprintf(line, sizeof(line), "[S123456789] cgroup.system name:dbus pid:!%s %s %s -- %s",
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus pid:!%s %s %s -- %s",
pidfn, cmd, DBUS_ARGS, DBUS_DESC);
free(pidfn);
} else
snprintf(line, sizeof(line), "[S123456789] cgroup.system name:dbus %s %s -- %s",
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus %s %s -- %s",
cmd, DBUS_ARGS, DBUS_DESC);
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
err(1, "Failed registering %s", DBUS_DAEMON);
conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf");
free(cmd);
}
+3 -4
View File
@@ -1,6 +1,6 @@
/* Coldplug modules using modalias magic
*
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -132,11 +132,10 @@ static FILE *maybe_fopen_alias(const char *file, const char *path)
{
const char *basename;
basename = rindex(path, '/');
if (!basename)
basename = basenm(path);
if (!strcmp(basename, path))
return NULL;
basename++;
if (strcmp(file, basename))
return NULL;
+1 -1
View File
@@ -41,7 +41,7 @@
*
* Please note, the :ID is there for your benefit, it ensures that tasks
* in Finit are unique. If you have two tasks with the same name and ID
* (or no ID), the last one read replaces any preceeding one!
* (or no ID), the last one read replaces any preceding one!
*/
#include <unistd.h>
+1 -1
View File
@@ -2,7 +2,7 @@
/* Netlink plugin for IFUP/IFDN and GW events
*
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
* Copyright (C) 2009-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (C) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
+21 -11
View File
@@ -1,7 +1,7 @@
/* Simple pidfile event monitor for the Finit condition engine
*
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -52,7 +52,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
ptr = slash++;
slash = strchr(ptr, '/');
if (slash) {
dbg("Path too deep, skipping.");
dbg("Path too deep, skipping %s", path);
return -1;
}
}
@@ -66,6 +66,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
char cond[MAX_COND_LEN];
char fn[PATH_MAX];
svc_t *svc;
char *nm;
paste(fn, sizeof(fn), dir, name);
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
@@ -79,16 +80,23 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
return;
}
dbg("Found svc %s for %s with pid %d", svc->name, fn, svc->pid);
/* Service condistion to set/clear */
mkcond(svc, cond, sizeof(cond));
nm = svc_ident(svc, NULL, 0);
dbg("Found svc %s for %s with pid %d", nm, fn, svc->pid);
if (svc_is_stopping(svc)) {
dbg("Ignoring pidfile death rattles while service %s is %s", nm, svc_status(svc));
goto sneaky_zebra;
}
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
/*
* only mark native services as started, the s6 and
* systemd style services rely on their respective
* readiness notification. Issue #343
*/
if (!svc->notify)
if (svc->notify == SVC_NOTIFY_PID)
svc_started(svc);
if (!svc_has_pidfile(svc)) {
@@ -120,13 +128,15 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
}
}
cond_set(cond);
if (!svc->notify)
service_ready(svc);
if (svc->notify == SVC_NOTIFY_PID)
cond_set(cond);
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
service_ready(svc, 1);
} else if (mask & IN_DELETE) {
sneaky_zebra:
cond_clear(cond);
if (!svc->notify)
service_ready(svc);
if (svc->notify == SVC_NOTIFY_PID)
service_ready(svc, 0);
}
}
@@ -240,8 +250,8 @@ static void pidfile_reconf(void *arg)
if (svc_is_changed(svc) || svc_is_starting(svc))
continue;
if (!svc->notify)
service_ready(svc);
if (svc->notify == SVC_NOTIFY_PID)
service_ready(svc, 1);
mkcond(svc, cond, sizeof(cond));
if (cond_get(cond) == COND_ON)
+6 -2
View File
@@ -1,6 +1,6 @@
/* Set kernel variables from /etc/sysctl.conf et al
*
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,6 +32,10 @@
#include "helpers.h"
#include "plugin.h"
#ifndef SYSCTL_PATH
#define SYSCTL_PATH "/sbin/sysctl"
#endif
static void setup(void *arg)
{
glob_t gl;
@@ -54,7 +58,7 @@ static void setup(void *arg)
for (i = 0; i < gl.gl_pathc; i++) {
char cmd[160];
snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
snprintf(cmd, sizeof(cmd), "%s -e -p %s >/dev/null", SYSCTL_PATH, gl.gl_pathv[i]);
run(cmd, "sysctl");
}
globfree(&gl);
+1 -1
View File
@@ -1,6 +1,6 @@
/* Setup necessary files for resolvconf
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+179 -61
View File
@@ -1,6 +1,6 @@
/* Save and restore RTC using hwclock
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,8 +36,15 @@
#include "helpers.h"
#include "plugin.h"
/* Kernel RTC driver validates against this date for sanity check */
/*
* Kernel RTC driver validates against this date for sanity check. The
* on NTP sync the driver can also update the RTC every 11 mins. We use
* the same update interval to handle manual time set and file save.
*/
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
#define RTC_FMT "%Y-%m-%d %H:%M:%S"
#define RTC_PERIOD (11 * 60 * 1000)
#ifdef RTC_TIMESTAMP_CUSTOM
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
#else
@@ -45,6 +52,10 @@ static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
#endif
static time_t rtc_date_fallback = 946684800LL;
static char *rtc_file = RTC_FILE;
static uev_t rtc_timer;
static void tz_set(char *tz, size_t len)
{
char *ptr;
@@ -68,6 +79,125 @@ static void tz_restore(char *tz)
tzset();
}
static int time_set(struct tm *tm)
{
struct tm fallback = { 0 };
struct timeval tv = { 0 };
char tz[128];
int rc = 0;
tz_set(tz, sizeof(tz));
if (!tm) {
logit(LOG_NOTICE, "Resetting system clock to kernel default, %s.", rtc_timestamp);
tm = &fallback;
/* Attempt to set RTC to a sane value ... */
tv.tv_sec = rtc_date_fallback;
if (!gmtime_r(&tv.tv_sec, tm)) {
rc = 1;
goto out;
}
}
tm->tm_isdst = -1; /* Use tzdata to figure it out, please. */
tv.tv_sec = mktime(tm);
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
errno = EINVAL;
rc = 2;
} else {
if (settimeofday(&tv, NULL) == -1)
rc = 1;
}
out:
tz_restore(tz);
return rc;
}
static int time_get(struct tm *tm)
{
struct timeval tv = { 0 };
char tz[128];
int rc = 0;
tz_set(tz, sizeof(tz));
rc = gettimeofday(&tv, NULL);
if (rc < 0 || tv.tv_sec < rtc_date_fallback)
rc = 2;
else
gmtime_r(&tv.tv_sec, tm);
tz_restore(tz);
return rc;
}
static void file_save(void *arg)
{
struct tm tm = { 0 };
int rc = 0;
FILE *fp;
if (!rtc_file)
return;
fp = fopen(rtc_file, "w");
if (!fp) {
logit(LOG_WARNING, "Failed saving system clock to %s, code %d: %s",
rtc_file, errno, strerror(errno));
return;
}
if ((rc = time_get(&tm))) {
logit(LOG_WARNING, "System clock invalid, before %s, not saving", rtc_timestamp);
print_desc(NULL, "System clock invalid, skipping");
} else {
char buf[32] = { 0 };
print_desc(NULL, "Saving system clock to file");
strftime(buf, sizeof(buf), RTC_FMT, &tm);
fprintf(fp, "%s\n", buf);
}
print(rc, NULL);
fclose(fp);
}
static void file_restore(void *arg)
{
struct tm tm = { 0 };
int rc = 1;
FILE *fp;
if (!rtc_file) {
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
return;
}
print_desc(NULL, "Restoring system clock from backup");
fp = fopen(rtc_file, "r");
if (fp) {
char buf[32];
if (fgets(buf, sizeof(buf), fp)) {
chomp(buf);
strptime(buf, RTC_FMT, &tm);
rc = time_set(&tm);
}
fclose(fp);
} else
logit(LOG_WARNING, "Missing %s", rtc_file);
if (rc) {
time_set(NULL);
rc = 2;
}
print(rc, NULL);
}
static int rtc_open(void)
{
char *alt[] = {
@@ -91,10 +221,8 @@ static int rtc_open(void)
static void rtc_save(void *arg)
{
struct timeval tv = { 0 };
struct tm tm = { 0 };
int fd, rc = 0;
char tz[128];
if (rescue) {
dbg("Skipping %s plugin in rescue mode.", __FILE__);
@@ -105,38 +233,26 @@ static void rtc_save(void *arg)
if (fd < 0)
return;
tz_set(tz, sizeof(tz));
rc = gettimeofday(&tv, NULL);
if (rc < 0 || tv.tv_sec < rtc_date_fallback) {
if ((rc = time_get(&tm))) {
print_desc(NULL, "System clock invalid, not saving to RTC");
invalid:
logit(LOG_ERR, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
} else {
print_desc(NULL, "Saving system clock (UTC) to RTC");
rc = ioctl(fd, RTC_SET_TIME, &tm);
}
if (rc && errno == EINVAL) {
logit(LOG_WARNING, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
rc = 2;
goto out;
}
print_desc(NULL, "Saving system time (UTC) to RTC");
gmtime_r(&tv.tv_sec, &tm);
if (ioctl(fd, RTC_SET_TIME, &tm) < 0) {
if (EINVAL == errno)
goto invalid;
rc = 1;
goto out;
}
out:
tz_restore(tz);
print(rc, NULL);
close(fd);
}
static void rtc_restore(void *arg)
{
struct timeval tv = { 0 };
struct tm tm = { 0 };
int fd, rc = 0;
char tz[128];
if (rescue) {
dbg("Skipping %s plugin in rescue mode.", __FILE__);
@@ -145,65 +261,62 @@ static void rtc_restore(void *arg)
fd = rtc_open();
if (fd < 0) {
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
file_restore(arg);
return;
}
tz_set(tz, sizeof(tz));
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
if ((rc = ioctl(fd, RTC_RD_TIME, &tm)) < 0) {
char msg[120];
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
EINVAL == errno ? "RTC time is too old" :
ENOENT == errno ? "RTC has no saved time" : "see log for details");
print_desc(NULL, msg);
} else {
print_desc(NULL, "Restoring system clock (UTC) from RTC");
rc = time_set(&tm);
}
invalid:
logit(LOG_ERR, "Failed restoring system clock from RTC.");
if (rc) {
logit(LOG_WARNING, "Failed restoring system clock from RTC.");
if (EINVAL == errno)
logit(LOG_ERR, "RTC time is too old (before %s)", rtc_timestamp);
logit(LOG_WARNING, "RTC time is too old (before %s)", rtc_timestamp);
else if (ENOENT == errno)
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
logit(LOG_WARNING, "RTC has no previously saved (valid) time.");
else
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
logit(LOG_WARNING, "RTC error code %d: %s", errno, strerror(errno));
/* Been here already? */
if (rc)
goto out;
print(2, NULL);
/* Attempt to set RTC to a sane value ... */
tv.tv_sec = rtc_date_fallback;
if (!gmtime_r(&tv.tv_sec, &tm))
goto out;
/* Try restoring from last save game */
if (rtc_file)
file_restore(arg);
} else
print(0, NULL);
logit(LOG_NOTICE, "Resetting RTC to kernel default, %s.", rtc_timestamp);
rc = 2;
}
print_desc(NULL, "Restoring system clock (UTC) from RTC");
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
tv.tv_sec = mktime(&tm);
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
errno = EINVAL;
goto invalid;
}
if (settimeofday(&tv, NULL) == -1)
rc = 1;
out:
tz_restore(tz);
print(rc, NULL);
close(fd);
}
static void save(void *arg)
{
rtc_save(arg);
file_save(arg);
}
static void update(uev_t *w, void *arg, int events)
{
save(arg);
}
static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_BASEFS_UP] = {
.cb = rtc_restore
},
.hook[HOOK_SHUTDOWN] = {
.cb = rtc_save
.cb = save
}
};
@@ -211,16 +324,21 @@ PLUGIN_INIT(plugin_init)
{
struct tm tm = { 0 };
if (!strptime(rtc_timestamp, "%Y-%m-%d %H:%M", &tm))
rtc_date_fallback = mktime(&tm);
else
if (!strptime(rtc_timestamp, RTC_FMT, &tm)) {
logit(LOG_WARNING, "Invalid restore date '%s', reverting to '%s'",
rtc_timestamp, RTC_TIMESTAMP_BEGIN_2000);
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
} else
rtc_date_fallback = mktime(&tm);
uev_timer_init(ctx, &rtc_timer, update, NULL, RTC_PERIOD, RTC_PERIOD);
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
uev_timer_stop(&rtc_timer);
plugin_unregister(&plugin);
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* System condition event monitor for the Finit condition engine
*
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,7 +1,7 @@
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
*
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
* Copyright (c) 2013-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+50 -11
View File
@@ -1,6 +1,6 @@
/* Setup and save random seed at boot/shutdown
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <sys/time.h> /* gettimeofday() */
#include <sys/types.h>
#include <sys/resource.h> /* getrusage() */
#ifdef _LIBITE_LITE
# include <libite/lite.h>
#else
@@ -42,11 +43,43 @@
#define RANDOM_BYTES (32*1024)
#endif
#ifdef RANDOMSEED
/*
* This is the fallback seed function, please make sure you have drivers
* enabling /dev/hwrng instead.
*/
static void fallback(FILE *fp)
{
unsigned long seed;
struct timeval tv;
struct rusage ru;
int iter = 128;
gettimeofday(&tv, NULL);
getrusage(RUSAGE_SELF, &ru);
/* Mix multiple sources of "randomness" */
seed = tv.tv_sec ^ (tv.tv_usec << 16);
seed ^= ru.ru_utime.tv_sec ^ (ru.ru_utime.tv_usec << 16);
seed ^= ru.ru_stime.tv_sec ^ (ru.ru_stime.tv_usec << 16);
seed ^= getpid() << 8;
srandom(seed);
while (iter--) {
uint32_t i, prng = random();
for (i = 0; i < sizeof(prng); i++)
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
}
}
#endif
static void setup(void *arg)
{
#ifdef RANDOMSEED
struct rand_pool_info *rpi;
ssize_t len = 0;
struct stat st;
int rc = -1;
int fd, err;
@@ -55,7 +88,7 @@ static void setup(void *arg)
return;
}
if (!fexist(RANDOMSEED)) {
if (stat(RANDOMSEED, &st) || st.st_size < 512) {
int ret = 1;
mode_t prev;
FILE *fp;
@@ -64,16 +97,22 @@ static void setup(void *arg)
prev = umask(077);
fp = fopen(RANDOMSEED, "w");
if (fp) {
int iter = 128;
struct timeval tv;
const char *hwrng = "/dev/hwrng";
FILE *hw;
gettimeofday(&tv, NULL);
srandom(tv.tv_sec % 3600);
while (iter--) {
uint32_t i, prng = random();
hw = fopen(hwrng, "r");
if (hw) {
char buf[512];
size_t len;
for (i = 0; i < sizeof(prng); i++)
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
if (len == 0)
fallback(fp);
else
len = fwrite(buf, sizeof(buf[0]), len, fp);
fclose(hw);
} else {
fallback(fp);
}
ret = fclose(fp);
}
@@ -130,7 +169,7 @@ static void setup(void *arg)
close(fd);
free(rpi);
if (rc < 0)
logit(LOG_ERR, "Failed adding entropy to kernel random pool: %s", strerror(err));
logit(LOG_WARNING, "Failed adding entropy to kernel random pool: %s", strerror(err));
print_result(rc < 0);
return;
fallback:
+1 -1
View File
@@ -1,6 +1,6 @@
/* User-defined condition event monitor for the Finit condition engine
*
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* Console setup (for X)
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+2
View File
@@ -19,6 +19,8 @@ if WATCHDOGD
pkglibexec_PROGRAMS += watchdogd
endif
dist_pkglibexec_SCRIPTS = coldplug
finit_pkglibdir = $(pkglibdir)
finit_pkglib_SCRIPTS = rescue.conf sample.conf
+10 -5
View File
@@ -1,6 +1,6 @@
/* External client API, using UNIX domain socket.
*
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -332,6 +332,11 @@ static void api_cb(uev_t *w, void *arg, int events)
int sd, lvl;
svc_t *svc;
if (UEV_ERROR == events) {
dbg("%s(): api socket %d invalid.", __func__, w->fd);
goto error;
}
sd = accept(w->fd, NULL, NULL);
if (sd < 0) {
err(1, "Failed serving API request");
@@ -377,7 +382,9 @@ static void api_cb(uev_t *w, void *arg, int events)
case INIT_CMD_POWEROFF:
case INIT_CMD_SUSPEND:
if (IS_RESERVED_RUNLEVEL(runlevel)) {
warnx("Unsupported command in runlevel S and 6/0.");
strterm(rq.data, sizeof(rq.data));
warnx("Unsupported command (cmd: %d, data: %s) in runlevel S and 6/0.",
rq.cmd, rq.data);
goto leave;
}
default:
@@ -555,7 +562,7 @@ static void api_cb(uev_t *w, void *arg, int events)
}
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
err(1, "Falied initializing %s readiness notifier", svc_ident(svc, NULL, 0));
err(1, "Failed initializing %s readiness notifier", svc_ident(svc, NULL, 0));
break;
}
return; /* Don't close sd, used for notify */
@@ -576,8 +583,6 @@ static void api_cb(uev_t *w, void *arg, int events)
leave:
close(sd);
if (UEV_ERROR == events)
goto error;
return;
error:
api_exit();
+12 -2
View File
@@ -1,6 +1,6 @@
/* Finit control group support functions
*
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -259,6 +259,11 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
ssize_t sz;
size_t off;
if (UEV_ERROR == events) {
dbg("%s(): inotify socket %d invalid.", __func__, w->fd);
return;
}
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
if (sz <= 0) {
err(1, "invalid inotify event");
@@ -463,10 +468,15 @@ void cgroup_init(uev_ctx_t *ctx)
FILE *fp;
int fd;
#ifndef CGROUP2_ENABLED
avail = 0;
return;
#endif
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
if (errno == ENOENT)
logit(LOG_INFO, "Kernel does not support cgroups v2, disabling.");
else if (errno == EPERM) /* Probably inside an unpriviliged container */
else if (errno == EPERM) /* Probably inside an unprivileged container */
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
else
err(1, "Failed mounting cgroup v2");
+1 -1
View File
@@ -1,6 +1,6 @@
/* Finit control group support functions
*
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* New client tool, replaces old /dev/initctl API and telinit tool
*
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* Cgroup utility functions for initctl
*
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+5 -3
View File
@@ -1,6 +1,6 @@
/* External client API, using UNIX domain socket.
*
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,8 @@
#include "client.h"
#include "log.h"
#define REQUEST_TIMEOUT 15000
static int sd = -1;
int client_connect(void)
@@ -85,7 +87,7 @@ int client_request(struct init_request *rq, ssize_t len)
pfd.fd = sd;
pfd.events = POLLOUT;
if (poll(&pfd, 1, 2000) <= 0) {
if (poll(&pfd, 1, REQUEST_TIMEOUT) <= 0) {
warn("Timed out waiting for Finit, errno %d", errno);
return -1;
}
@@ -107,7 +109,7 @@ int client_request(struct init_request *rq, ssize_t len)
pfd.fd = sd;
pfd.events = POLLIN | POLLERR | POLLHUP;
if ((rc = poll(&pfd, 1, 2000)) <= 0) {
if ((rc = poll(&pfd, 1, REQUEST_TIMEOUT)) <= 0) {
if (rc) {
if (errno == EINTR) /* shutdown/reboot */
return -1;
+1 -1
View File
@@ -1,6 +1,6 @@
/* External client API, using UNIX domain socket.
*
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
# With the daemon mode ('mdev -df') we no longer need the hotplug helper
echo "" > /proc/sys/kernel/hotplug
# Wait for 'mdev -df' to set up its event queue.
sleep 1
# Trigger 'add' event for all devices and subsystems to load all modules
# and any firmware needed by the hardware.
find /sys/devices -name uevent -print | while IFS='' read X; do echo add > $X; done
+19 -7
View File
@@ -35,6 +35,7 @@
#include "cond.h"
#include "pid.h"
#include "service.h"
#include "sm.h"
struct cond_boot {
TAILQ_ENTRY(cond_boot) link;
@@ -112,7 +113,7 @@ static void cond_boot_strap(void)
*
* => 'pid/' + 'teamd' + '' = condition <pid/teamd>
*
* When you add a second aggrate you need to tell Finit it's a different
* When you add a second aggregate you need to tell Finit it's a different
* instance usugin the :ID syntax:
*
* service :lag2 teamd -f /etc/teamd/lag2.conf -- Aggregate lag2
@@ -214,7 +215,10 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
err(1, "Failed removing condition %s", fpath);
cond = ptr + strlen(COND_BASE) + 1;
cond_update(cond);
if (sm_is_in_teardown(&sm))
cond_clear_noupdate(cond);
else
cond_update(cond);
return 0;
}
@@ -222,8 +226,16 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
static void cond_delpath(const char *path)
{
nftw(path, do_delete, 20, FTW_DEPTH);
if (remove(path) && errno != ENOENT)
err(1, "Failed removing condition path %s", path);
if (remove(path)) {
switch (errno) {
case ENOENT: /* Ignore */
case ENOTEMPTY: /* Only at shutdown and for directories */
break;
default:
err(1, "Failed removing condition path %s", path);
break;
}
}
}
int cond_set_path(const char *path, enum cond_state next)
@@ -276,7 +288,7 @@ int cond_update(const char *name)
svc_t *svc, *iter = NULL;
int affects = 0;
dbg("%s", name);
// dbg("%s", name);
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
continue;
@@ -309,7 +321,7 @@ int cond_set_noupdate(const char *name)
void cond_set(const char *name)
{
dbg("%s", name);
// dbg("%s", name);
if (cond_set_noupdate(name))
return;
@@ -360,7 +372,7 @@ int cond_clear_noupdate(const char *name)
void cond_clear(const char *name)
{
dbg("%s", name);
// dbg("%s", name);
if (cond_clear_noupdate(name))
return;
+199 -31
View File
@@ -1,6 +1,6 @@
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -348,8 +348,11 @@ static void parse_kernel_loglevel(void)
*/
void conf_parse_cmdline(int argc, char *argv[])
{
const char *ptr;
/* Set up defaults */
fstab = strdup(FINIT_FSTAB);
if ((ptr = FINIT_FSTAB))
fstab = strdup(ptr);
finit_conf = strdup(FINIT_CONF);
finit_rcsd = strdup(FINIT_RCSD);
path = getenv("PATH");
@@ -414,6 +417,79 @@ void conf_saverc(void)
fclose(fp);
}
/*
* Called at bootstrap to log execution order (for debug)
*/
void conf_save_exec_order(svc_t *svc, char *cmdline, int result)
{
const char *fn = _PATH_VARRUN "finit/exec.order";
const char *ststr = !result ? "[ OK ]" : "[FAIL]";
static char *prepared = NULL;
int first = !fexist(fn);
FILE *fp;
fp = fopen(fn, "a+");
if (!fp) {
err(1, "failed writing to %s", fn);
return;
}
if (first) {
fprintf(fp, "# Execution order of run/task/services at bootstrap\n");
fprintf(fp, "# ST TYPE COMMAND LINE (DESC)\n");
}
if (result == -1) {
int len;
len = snprintf(NULL, 0, " %-7s %-64s (%s)", svc_typestr(svc), cmdline, svc->desc);
if (len > 0) {
if (prepared)
free(prepared);
prepared = malloc(++len);
if (!prepared)
goto done;
snprintf(prepared, len, " %-7s %-64s (%s)", svc_typestr(svc), cmdline, svc->desc);
}
} else {
if (prepared) {
memcpy(prepared, ststr, strlen(ststr));
fprintf(fp, "%s\n", prepared);
free(prepared);
prepared = NULL;
} else {
fprintf(fp, "%s %-7s %-64s (%s)\n", ststr, svc_typestr(svc), cmdline, svc->desc);
}
}
done:
fclose(fp);
}
/*
* Called by plugins and similar that dynamically generate system services
*/
void conf_save_service(int type, char *cfg, char *file)
{
char fn[256];
svc_t foo;
FILE *fp;
mkpath(FINIT_RUNPATH_, 0755);
snprintf(fn, sizeof(fn), "%s/%s", FINIT_RUNPATH_, file);
if (fexist(fn))
warnx("File %s already exists, overwriting.", fn);
fp = fopen(fn, "w");
if (!fp) {
err(1, "Failed creating %s", fn);
return;
}
foo.type = type;
fprintf(fp, "# Generated by finit:%s()\n", __func__);
fprintf(fp, "%s %s\n", svc_typestr(&foo), cfg);
fclose(fp);
}
/*
* Sets, and makes a note of, all KEY=VALUE lines in a given .conf line
* from finit.conf, or other .conf file. Note, PATH is always reset in
@@ -472,6 +548,23 @@ static void parse_env(char *line)
*end-- = 0;
}
/* strip any leading 'set ' */
end = key;
if (!strncmp(key, "set", 3))
end += 3;
/* check key, no spaces allowed */
while (*end && isspace(*end))
end++;
key = end;
while (*end && !isspace(*end))
end++;
if (*end != 0) {
warnx("'%s=%s': not a valid identifier", key, val);
return; /* invalid key */
}
dbg("Global env '%s'='%s'", key, val);
setenv(key, val, 1);
node = malloc(sizeof(*node));
@@ -583,11 +676,22 @@ void conf_parse_cond(svc_t *svc, char *cond)
return;
}
/* First character must be '!' if SIGHUP is not supported. */
/*
* First character must be '!' if:
* - service: SIGHUP is not supported
* - run/task: Do not block bootstrap
*/
ptr = cond;
if (ptr[i] == '!') {
svc->sighup = 0;
ptr++;
if (svc_is_runtask(svc)) {
/* see service_runtask_clean() */
svc->sighup = 1;
svc->once = 1;
} else {
svc->sighup = 0;
}
}
while (ptr[i] != '>' && ptr[i] != 0)
@@ -874,6 +978,18 @@ static int parse_static(char *line, int is_rcsd)
return 0;
}
/*
* Before Finit 5 the default readiness notification is PID.
* This default can be changed by setting 'readiness none' in
* the file /etc/finit.conf, only read once at bootstrap.
*/
if (BOOTSTRAP && MATCH_CMD(line, "readiness ", x)) {
char *token = strip_line(x);
if (!strcmp(token, "none"))
readiness = SVC_NOTIFY_NONE;
}
if (MATCH_CMD(line, "reboot-delay ", x)) {
syncsec = strtonum(strip_line(x), 0, 60, NULL);
return 0;
@@ -1152,22 +1268,53 @@ int conf_reload(void)
* but are now regular files that can be overridden by files in
* /etc/finit.d -- similar to how tmfiles.d(5) work. E.g., add
* an override .conf, or an ignore by symlinking to /dev/null
*
* The .conf files (and run/task/service stanzas) are parsed and
* started in order. Each directory is sorted alphanumerically
* and then the result is appended to the overall order:
*
* /lib/finit/system/10-hotplug.conf
* /lib/finit/system/90-testserv.conf
* /run/finit/system/dbus.conf
* /run/finit/system/tty.conf
* /etc/finit.d/10-abc.conf
* /etc/finit.d/20-abc.conf
* /etc/finit.d/enabled/1-aaa.conf
* /etc/finit.d/enabled/1-abc.conf
* /etc/finit.d/enabled/2-aaa.conf
*/
glob_append(&gl, 0, "%s/*.conf", finit_rcsd);
glob_append(&gl, 1, "%s/*.conf", FINIT_SYSPATH);
glob_append(&gl, 0, "%s/*.conf", FINIT_SYSPATH_);
glob_append(&gl, 1, "%s/*.conf", FINIT_RUNPATH_);
glob_append(&gl, 1, "%s/*.conf", finit_rcsd);
glob_append(&gl, 1, "%s/enabled/*.conf", finit_rcsd);
if (bootstrap) {
const char *fn = _PATH_VARRUN "finit/conf.order";
FILE *fp;
fp = fopen(fn, "w");
if (!fp) {
err(1, "failed creating %s", fn);
} else {
fprintf(fp, "# Evaluation & execution order of .conf files\n");
for (i = 0; i < gl.gl_pathc; i++)
fprintf(fp, "%s\n", gl.gl_pathv[i]);
fclose(fp);
}
}
for (i = 0; i < gl.gl_pathc; i++) {
char *path = gl.gl_pathv[i];
char *rp = NULL;
struct stat st;
size_t j, len;
/* check for FINIT_SYSPATH overrides */
/* check for FINIT_SYSPATH_ or FINIT_RUNPATH_ overrides */
for (j = i + 1; j < gl.gl_pathc; j++) {
if (strncmp(path, FINIT_SYSPATH, strlen(FINIT_SYSPATH)))
if (strncmp(path, FINIT_SYSPATH_, strlen(FINIT_SYSPATH_)) &&
strncmp(path, FINIT_RUNPATH_, strlen(FINIT_RUNPATH_)))
continue;
if (strcmp(basename(path), basename(gl.gl_pathv[j])))
if (strcmp(basenm(path), basenm(gl.gl_pathv[j])))
continue;
path = NULL; /* replacement later in list, skip this */
break;
@@ -1225,6 +1372,9 @@ done:
/* Drop record of all .conf changes */
drop_changes();
if (bootstrap)
wdog = svc_find("watchdog", "finit");
/* Override configured runlevel, user said 'S' on /proc/cmdline */
if (BOOTSTRAP && single)
cfglevel = 1;
@@ -1275,22 +1425,29 @@ static int conf_change_act(char *dir, char *name, uint32_t mask)
struct conf_change *node;
char *rp = NULL;
if (name[0])
/* Check for actual printable characters, sometimes STX */
if (name[0] && name[0] >= ' ')
paste(fn, sizeof(fn), dir, name);
else
strlcpy(fn, dir, sizeof(fn));
dbg("path: %s mask: %08x", fn, mask);
/* Handle disabling/removal of service */
rp = realpath(fn, NULL);
if (!rp) {
if (errno != ENOENT)
goto fail;
if (strchr(name, '@')) {
/* Skip realpath for templates */
rp = strdup(fn);
if (!rp)
goto fail;
} else {
/* Handle disabling/removal of service */
rp = realpath(fn, NULL);
if (!rp) {
if (errno != ENOENT)
goto fail;
rp = strdup(fn);
}
}
if (!rp)
goto fail;
node = conf_find(rp);
if (node) {
dbg("event already registered for %s ...", name);
@@ -1329,7 +1486,11 @@ int conf_changed(char *file)
if (!file)
return 0;
rp = realpath(file, NULL);
if (strchr(file, '@'))
rp = strdup(file);
else
rp = realpath(file, NULL);
if (!rp)
return 0;
@@ -1381,6 +1542,11 @@ static int conf_iwatch_read(int fd)
static void conf_cb(uev_t *w, void *arg, int events)
{
if (UEV_ERROR == events) {
dbg("%s(): iwatch socket %d invalid.", __func__, w->fd);
return;
}
if (conf_iwatch_read(w->fd)) {
err(1, "invalid inotify event");
return;
@@ -1413,25 +1579,26 @@ int conf_monitor(void)
* have or not have symlinks in place. We need to monitor for
* changes to either symlink or target.
*/
rc += iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
rc |= iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
snprintf(path, sizeof(path), "%s/available/", finit_rcsd);
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
snprintf(path, sizeof(path), "%s/enabled/", finit_rcsd);
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
rc += iwatch_add(&iw_conf, finit_conf, 0);
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
rc |= iwatch_add(&iw_conf, finit_conf, 0);
/*
* Systems with /etc/default, /etc/conf.d, or similar, can also
* monitor changes in env files sourced by .conf files (above)
* define your own with --with-sysconfig=/path/to/envfiles
*/
rc += iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
rc += iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
rc |= iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
rc |= iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
#ifdef FINIT_SYSCONFIG
rc += iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
rc |= iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
#endif
rc |= conf_reload();
return rc + conf_reload();
return rc;
}
/*
@@ -1461,15 +1628,16 @@ int conf_init(uev_ctx_t *ctx)
*/
#ifdef WDT_DEVNODE
if (whichp(FINIT_EXECPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) {
service_register(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init name:watchdog :finit " FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", global_rlimit, NULL);
wdog = svc_find("watchdog", "finit");
conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init notify:none name:watchdog :finit "
FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", "watchdogd.conf");
}
#endif
/*
* Start kernel event daemon as soon as possible, if enabled
*/
if (whichp(FINIT_EXECPATH_ "/keventd"))
service_register(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init " FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", global_rlimit, NULL);
conf_save_service(SVC_TYPE_SERVICE, "[S12345789] cgroup.init notify:none "
FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf");
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
plugin_run_hooks(HOOK_SVC_PLUGIN);
@@ -1502,10 +1670,10 @@ int conf_init(uev_ctx_t *ctx)
if (runparts_sysv)
strlcat(args, "-s ", sizeof(args));
snprintf(conf, sizeof(conf), "[S] <int/bootstrap> log:console %s %s %s"
snprintf(conf, sizeof(conf), "[S] <int/bootstrap> notify:none log:console %s %s %s"
" -- Calling runparts %s in the background",
_PATH_RUNPARTS, args, runparts, runparts);
service_register(SVC_TYPE_TASK, conf, global_rlimit, NULL);
conf_save_service(SVC_TYPE_TASK, conf, "runparts.conf");
}
return 0;
+3 -1
View File
@@ -1,6 +1,6 @@
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -44,6 +44,8 @@ int conf_monitor (void);
void conf_reset_env (void);
void conf_saverc (void);
void conf_save_exec_order (svc_t *svc, char *cmdline, int result);
void conf_save_service (int type, char *cfg, char *file);
void conf_parse_cmdline (int argc, char *argv[]);
int conf_parse_runlevels (char *runlevels);
void conf_parse_cond (svc_t *svc, char *cond);
+1 -1
View File
@@ -1,6 +1,6 @@
/* Device node monitor for the Finit condition engine
*
* Copyright (c) 2022-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* Device node monitor for the Finit condition engine
*
* Copyright (c) 2022-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+22 -21
View File
@@ -1,7 +1,7 @@
/* Functions for exec'ing processes
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -138,31 +138,32 @@ int run(char *cmd, char *log)
pid = fork();
if (0 == pid) {
int rc = EX_OSERR;
char *pfx, buf[256];
FILE *pp;
int rc;
setsid();
sig_unblock();
if (!log) {
do_redirect();
execvp(args[0], args);
} else {
char *pfx = *log ? ": " : "";
FILE *pp;
pp = popen(cmd, "r");
if (pp) {
char buf[256];
while (fgets(buf, sizeof(buf), pp)) {
chomp(buf);
logit(LOG_NOTICE, "%s%s%s", log, pfx, buf);
}
rc = pclose(pp);
}
_exit(EX_OSERR);
}
_exit(rc);
pp = popen(cmd, "r");
if (!pp)
_exit(EX_OSERR);
pfx = *log ? ": " : "";
while (fgets(buf, sizeof(buf), pp)) {
chomp(buf);
logit(LOG_NOTICE, "%s%s%s", log, pfx, buf);
}
rc = pclose(pp);
if (rc == -1)
_exit(EX_OSERR);
_exit(WEXITSTATUS(rc));
} else if (-1 == pid) {
err(1, "%s", !log ? args[0] : cmd);
if (backup)
@@ -198,7 +199,6 @@ int run(char *cmd, char *log)
int run_interactive(char *cmd, char *fmt, ...)
{
int status, oldout = 1, olderr = 2;
char line[LINE_SIZE];
FILE *fp;
if (!cmd) {
@@ -243,6 +243,7 @@ int run_interactive(char *cmd, char *fmt, ...)
/* Dump any results of cmd on stderr after we've printed [ OK ] or [FAIL] */
if (fp && !debug) {
char line[LINE_SIZE];
size_t len, written;
rewind(fp);
@@ -280,7 +281,7 @@ int exec_runtask(char *cmd, char *args[])
return execvp(_PATH_BSHELL, argv);
}
static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit rlimit[])
static void prepare_tty(char *tty, speed_t speed, const char *procname, struct rlimit rlimit[])
{
char name[80];
int fd, dummy;
@@ -350,7 +351,7 @@ static int activate_console(int noclear, int nowait)
dprint(STDERR_FILENO, clr, strlen(clr));
dprint(STDERR_FILENO, msg, strlen(msg));
while ((rc = read(STDIN_FILENO, &ch, 1)) > 0 && ch != '\r' && ch != '\n')
continue;
;
/* On any error (likely EINTR), we avoid starting getty */
if (rc == -1)
+40 -14
View File
@@ -1,7 +1,7 @@
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -66,9 +66,10 @@ int prevlevel = -1;
int debug = 0; /* debug mode from kernel cmdline */
int rescue = 0; /* rescue mode from kernel cmdline */
int single = 0; /* single user mode from kernel cmdline */
int bootstrap = 1; /* set while bootrapping (for TTYs) */
int bootstrap = 1; /* set while bootstrapping (for TTYs) */
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
int syncsec = 0; /* reboot delay */
int readiness = SVC_NOTIFY_PID;
char *finit_conf= NULL;
char *finit_rcsd= NULL;
char *fstab = NULL;
@@ -86,14 +87,22 @@ svc_t *wdog = NULL; /* No watchdog by default */
*/
static void banner(void)
{
#ifndef KERNEL_LOGGING
/*
* Silence kernel logs, assuming users have sysklogd or
* similar enabled to start emptying /dev/kmsg, but for
* our progress we want to own the console.
* similar enabled to start emptying /dev/kmsg.
*
* Instead of using `configure --disable-kernel-logging`, we
* recommend adjusting the kernel log level in the kernel's
* menuconfig, or using sysctl kernel.printk, or setting the
* desired log level, on the kernel cmdline, e.g. 'quiet'.
*
* By default KERNEL_LOGGING is enabled so you can see any
* warnings/errors or higher on your system console.
*/
if (!debug && !kerndebug)
klogctl(6, NULL, 0);
#endif
/*
* First level hooks, if you want to run here, you're
* pretty much on your own. Nothing's up yet ...
@@ -204,7 +213,7 @@ static int fsck(int pass)
fp = setmntent(fstab, "r");
if (!fp) {
err(1, "Failed opening fstab: %s", fstab);
logit(LOG_CONSOLE | LOG_ALERT, "Failed opening fstab: %s", fstab);
sulogin(1);
}
dbg("Opened %s, pass %d", fstab, pass);
@@ -263,10 +272,15 @@ static int fsck(int pass)
* errors were corrected but that the boot may proceed.
*/
if (fsck_rc > 1) {
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
sulogin(1);
if (hasmntopt(mnt,"nofail")) {
logit(LOG_CONSOLE | LOG_WARNING, "Ignoring failed fsck %s because of nofail option", dev);
fsck_rc = 0;
} else {
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
sulogin(1);
}
}
rc += fsck_rc;
rc |= fsck_rc;
}
endmntent(fp);
@@ -354,6 +368,8 @@ static void fs_remount_root(int fsckerr)
*/
static void fs_finalize(void)
{
int flags = MS_NOEXEC | MS_NOSUID;
/*
* Some systems rely on us to both create /dev/shm and, to mount
* a tmpfs there. Any system with dbus needs shared memory, so
@@ -361,8 +377,8 @@ static void fs_finalize(void)
* the /etc/fstab file already.
*/
if (!fismnt("/dev/shm")) {
makedir("/dev/shm", 0777);
fs_mount("shm", "/dev/shm", "tmpfs", 0, "mode=0777");
makedir("/dev/shm", 1777);
fs_mount("shm", "/dev/shm", "tmpfs", flags | MS_NODEV, "mode=1777");
}
/* Modern systems use /dev/pts */
@@ -380,7 +396,13 @@ static void fs_finalize(void)
snprintf(opts, sizeof(opts), "gid=%d,mode=%d,ptmxmode=0666", gid, mode);
makedir("/dev/pts", 0755);
fs_mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, opts);
fs_mount("devpts", "/dev/pts", "devpts", flags, opts);
}
/* Needed on systems like Alpine Linux */
if (!fismnt("/dev/mqueue")) {
makedir("/dev/mqueue", 1777);
fs_mount("mqueue", "/dev/mqueue", "tmpfs", flags | MS_NODEV, NULL);
}
/*
@@ -392,7 +414,7 @@ static void fs_finalize(void)
* To override any of this behavior, add entries to /etc/fstab
* for /run (and optionally /run/lock).
*/
if (fisdir("/run") && !fismnt("/run")) {
if (fisdir("/run") && !fismnt("/run") && !fistmpfs("/run")) {
fs_mount("tmpfs", "/run", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, "mode=0755,size=10%");
/* This prevents user DoS of /run by filling /run/lock at the expense of another tmpfs, max 5MiB */
@@ -401,7 +423,7 @@ static void fs_finalize(void)
}
/* Modern systems use tmpfs for /tmp */
if (!fismnt("/tmp"))
if (!fismnt("/tmp") && !fistmpfs("/tmp"))
fs_mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV, "mode=1777");
}
@@ -695,6 +717,10 @@ int main(int argc, char *argv[])
cond_set_oneshot(plugin_hook_str(HOOK_BANNER));
cond_set_oneshot(plugin_hook_str(HOOK_ROOTFS_UP));
/* Some bootstrap tasks may need to know if we're in a container. */
if (in_container())
cond_set_oneshot("int/container");
/*
* Initialize .conf system and load static /etc/finit.conf then
* tell the world what we used.
+2 -1
View File
@@ -1,7 +1,7 @@
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -121,6 +121,7 @@ extern int single;
extern int bootstrap;
extern int kerndebug;
extern int syncsec;
extern int readiness;
extern char *fstab;
extern char *sdown;
extern char *network;
+6 -3
View File
@@ -1,6 +1,6 @@
/* Initialize and serve a login terminal
*
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -121,6 +121,9 @@ static int osrel(struct osrel *rel)
snprintf(rel->version, sizeof(rel->version), "(%s)", codename);
}
if (rel->id[0] && !strcmp(rel->id, "alpine"))
return 1; /* compat mode for \r et al. */
return 0;
}
@@ -309,9 +312,9 @@ static int exec_login(char *name)
struct stat st;
if (passenv)
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", name, NULL);
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", "--", name, NULL);
else
execl(_PATH_LOGIN, _PATH_LOGIN, name, NULL);
execl(_PATH_LOGIN, _PATH_LOGIN, "--", name, NULL);
/*
* Failed to exec login, should not happen on normal systems.
+16 -11
View File
@@ -1,7 +1,7 @@
/* Misc. utility functions for finit and its plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -87,6 +87,9 @@ void console_init(void)
/* Enable line wrap, if disabled previously, e.g., qemu */
dprint(STDOUT_FILENO, "\033[?7h", 5);
/* Reset attributes, background and foreground color */
dprint(STDOUT_FILENO, "\033[49m\033[39m\e[2J", 14);
log_init();
}
@@ -522,9 +525,10 @@ void networking(int updown)
pid = fork();
if (pid == 0) {
int rc = EX_OSERR;
const char *cmd;
char buf[256];
FILE *pp;
int rc;
setsid();
sig_unblock();
@@ -539,16 +543,16 @@ void networking(int updown)
cmd = "ifdown -a -f 2>&1";
pp = popen(cmd, "r");
if (pp) {
char buf[256];
if (!pp)
_exit(EX_OSERR);
while (fgets(buf, sizeof(buf), pp))
logit(LOG_NOTICE, "network: %s", chomp(buf));
while (fgets(buf, sizeof(buf), pp))
logit(LOG_NOTICE, "network: %s", chomp(buf));
rc = pclose(pp);
}
_exit(rc);
rc = pclose(pp);
if (rc == -1)
_exit(EX_OSERR);
_exit(WEXITSTATUS(rc));
}
cgroup_service("network", pid, NULL);
print(pid > 0 ? 0 : 1, "%s network interfaces ...",
@@ -581,7 +585,8 @@ int in_container(void)
"lxc",
"docker",
"kubepod",
"unshare"
"unshare",
"systemd-nspawn"
};
const char *files[] = {
"/run/.containerenv",
+3 -2
View File
@@ -1,7 +1,7 @@
/* Misc. utility functions and C-library extensions for finit and its plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -141,6 +141,7 @@ static inline int ln(const char *target, const char *linkpath)
return 0;
}
static inline int dprint(int fd, const char *s, size_t len)
{
size_t loop = 3;
@@ -159,7 +160,7 @@ static inline int dprint(int fd, const char *s, size_t len)
return rc;
}
static inline char *fgetval(char *line, const char *key, char *sep)
static inline char *fgetval(const char *line, const char *key, char *sep)
{
char *ptr, *str, *copy;
size_t len;
+2 -2
View File
@@ -1,6 +1,6 @@
/* New client tool, replaces old /dev/initctl API and telinit tool
*
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -872,7 +872,7 @@ static char *svc_environ(svc_t *svc, char *buf, size_t len, int ansi)
{
int bold = missing(svc);
if (!ansi || svc_checkenv(svc) || svc->env[0] == '-')
if (!ansi || svc_checkenv(svc))
bold = 0;
strlcpy(buf, bold ? "\e[1m" : "", len);
+1 -1
View File
@@ -1,6 +1,6 @@
/* New client tool, replaces old /dev/initctl API and telinit tool
*
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+7 -1
View File
@@ -1,7 +1,7 @@
/* inotify watcher for files or directories
*
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -96,6 +96,12 @@ int iwatch_add1(struct iwatch *iw, char *file, uint32_t mask)
if (!initialized)
return -1;
iwp = iwatch_find_by_path(iw, file);
if (iwp) {
dbg("skipping, %s already registered", file);
return 0;
}
if (!fexist(file)) {
dbg("skipping %s: no such file or directory", file);
return 0;
+1 -1
View File
@@ -1,7 +1,7 @@
/* inotify watcher for files or directories
*
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* Listens to kernel events like AC power status and manages sys/ conditions
*
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+2 -11
View File
@@ -1,6 +1,6 @@
/* Finit daemon log functions
*
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -42,8 +42,6 @@ static int loglevel = LOG_INFO;
void log_init(void)
{
ttinit();
if (debug)
loglevel = LOG_DEBUG;
else
@@ -53,13 +51,6 @@ void log_init(void)
/* If we enabled terse mode at boot, restore to previous setting at shutdown */
void log_exit(void)
{
/*
* Unless in debug mode at shutdown, Reinitialize screen,
* terminal may have been resized at runtime
*/
if (!debug)
ttinit();
enable_progress(1);
}
@@ -148,7 +139,7 @@ void logit(int prio, const char *fmt, ...)
goto done;
}
fprintf(fp, "<%d>finit[1]:", LOG_DAEMON | prio);
fprintf(fp, "<%d>finit[1]: ", LOG_DAEMON | prio);
vfprintf(fp, fmt, ap);
fclose(fp);
+1 -1
View File
@@ -1,6 +1,6 @@
/* Finit daemon log functions
*
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+8 -6
View File
@@ -1,6 +1,6 @@
/* Handle MD arrays
*
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,7 @@
#include <string.h>
#include "helpers.h"
#include "util.h"
static glob_t *get_arrays(void)
@@ -48,17 +49,18 @@ static glob_t *get_arrays(void)
*/
void mdadm_wait(void)
{
size_t i;
glob_t *gl;
char cmd[160];
/* Setup kernel specific settings, e.g. allow broadcast ping, etc. */
gl = get_arrays();
if (gl) {
for (i = 0; i < gl->gl_pathc; i++) {
char *array;
size_t i;
array = basename(gl->gl_pathv[i]);
for (i = 0; i < gl->gl_pathc; i++) {
const char *array;
char cmd[160];
array = basenm(gl->gl_pathv[i]);
snprintf(cmd, sizeof(cmd), "mdadm --wait-clean /dev/%s >/dev/null", array);
run_interactive(cmd, "Marking MD array %s as clean", array);
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* Mount and unmount helpers
*
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+2 -2
View File
@@ -1,7 +1,7 @@
/* PID and PID file helpers
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -192,7 +192,7 @@ int pid_file_set(svc_t *svc, char *file, int not)
* pid:foo.tla --> /run/foo.tla.pid
* pid:/tmp/foo --> /tmp/foo.pid (Not handled by pidfile plugin!)
*
* An exclamation mark, or logial NOT, in the first character position
* An exclamation mark, or logical NOT, in the first character position
* indicates that Finit should *not* manage the PID file, and that the
* process uses a "non-standard" location. Eg. if service is 'bar'
* Finit would assume the PID file is /run/bar.pid and the below simply
+1 -1
View File
@@ -1,7 +1,7 @@
/* PID and PID file helpers
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+13 -9
View File
@@ -1,6 +1,6 @@
/* Plugin based services architecture for finit
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,6 +43,7 @@
#include "private.h"
#include "service.h"
#include "sig.h"
#include "util.h"
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0)
#define SEARCH_PLUGIN(str) \
@@ -77,23 +78,26 @@ static char *trim_ext(char *name)
int plugin_register(plugin_t *plugin)
{
const char *nm;
if (!plugin) {
errno = EINVAL;
return 1;
}
/* Setup default name if none is provided */
if (!plugin->name) {
nm = plugin->name;
if (!nm) {
#ifndef ENABLE_STATIC
Dl_info info;
if (dladdr(plugin, &info) && info.dli_fname)
plugin->name = basename(info.dli_fname);
nm = basenm(info.dli_fname);
#endif
if (!plugin->name)
plugin->name = "unknown";
if (!nm)
nm = "unknown";
}
plugin->name = trim_ext(strdup(plugin->name));
plugin->name = trim_ext(strdup(nm));
/* Already registered? */
if (plugin_find(plugin->name)) {
@@ -253,7 +257,7 @@ void plugin_run_hook(hook_point_t no, void *arg)
PLUGIN_ITERATOR(p, tmp) {
if (p->hook[no].cb) {
dbg("Calling %s hook n:o %d (arg: %p) ...", basename(p->name), no, arg ?: "NIL");
dbg("Calling %s hook n:o %d (arg: %p) ...", basenm(p->name), no, arg ?: "NIL");
p->hook[no].cb(arg ? arg : p->hook[no].arg);
}
}
@@ -301,9 +305,9 @@ int plugin_io_init(plugin_t *p)
if (!is_io_plugin(p))
return 0;
dbg("Initializing plugin %s for I/O", basename(p->name));
dbg("Initializing plugin %s for I/O", basenm(p->name));
if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags)) {
warn("Failed setting up I/O plugin %s", basename(p->name));
warn("Failed setting up I/O plugin %s", basenm(p->name));
return 1;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* Plugin based services architecture for finit
*
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,7 +1,7 @@
/* Private header file for main finit daemon, not for plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* reboot, halt, poweroff, shutdown, suspend for finit
*
* Copyright (c) 2009-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+18 -6
View File
@@ -26,18 +26,27 @@
#else
#include <sys/prctl.h>
const char *active_msg = NULL;
int interactive = 1;
int debug;
static void print_desc(const char *prefix, const char *msg)
{
fprintf(stderr, "\e[1m[\e[0m\e[1;33m ⋯ \e[0m\e[1m]\e[0m %s %s", prefix, msg);
if (interactive)
fprintf(stderr, "\e[1m[\e[0m\e[1;33m ⋯ \e[0m\e[1m]\e[0m %s %s", prefix, msg);
else
fprintf(stderr, "%s %s ...\n", prefix, msg);
active_msg = msg;
}
static void print_result(int rc)
{
if (rc)
fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
else
fputs("\r\e[1m[\e[0m\e[1;32m OK \e[0m\e[1m]\e[0m\n", stderr);
if (interactive) {
if (rc)
fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
else
fputs("\r\e[1m[\e[0m\e[1;32m OK \e[0m\e[1m]\e[0m\n", stderr);
} else
fprintf(stderr, "[%s] %s\n", rc ? "FAIL" : " OK ", active_msg ?: "");
}
void sig_unblock(void)
@@ -193,8 +202,11 @@ int main(int argc, char *argv[])
int rc, c, progress = 0, sysv = 0;
char *dir;
while ((c = getopt(argc, argv, "dh?ps")) != EOF) {
while ((c = getopt(argc, argv, "bdh?ps")) != EOF) {
switch(c) {
case 'b': /* batch mode */
interactive = 0;
break;
case 'd':
debug = 1;
break;
+3 -1
View File
@@ -1,6 +1,6 @@
/* Work queue helper functions
*
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,7 @@
#include "config.h"
#include "finit.h"
#include "log.h"
#include "schedule.h"
#define SC_INIT 0x494E4954 /* "INIT", see ascii(7) */
@@ -35,6 +36,7 @@ static void cb(uev_t *w, void *arg, int events)
struct wq *work = (struct wq *)arg;
if (UEV_ERROR == events) {
dbg("%s(): spurious problem with schedule work timer, restarting.", __func__);
uev_timer_start(w);
return;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* Work queue helper functions
*
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+47 -28
View File
@@ -1,6 +1,6 @@
/* List and enable/disable service configurations
*
* Copyright (c) 2017-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2017-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -222,20 +222,13 @@ int serv_list(char *arg)
* If the resulting file doesn't exist, and creat is not set, *or*
* the base directory doesn't exist, we return NULL.
.*/
static char *conf(char *path, size_t len, char *name, int creat)
static char *conf(char *path, size_t len, char *name, int creat, int template)
{
char corr[40];
if (!name || !name[0] || !strcmp(name, "finit") || !strcmp(name, "finit.conf")) {
strlcpy(path, finit_conf, len);
return path;
}
if (!strstr(name, ".conf")) {
snprintf(corr, sizeof(corr), "%s.conf", name);
name = corr;
}
if (!fisdir(finit_rcsd))
return NULL;
@@ -243,14 +236,25 @@ static char *conf(char *path, size_t len, char *name, int creat)
if (!fisdir(path)) {
if (creat && mkdir(path, 0755) && errno != EEXIST)
return NULL;
else
paste(path, len, finit_rcsd, name);
paste(path, len, finit_rcsd, name);
} else
strlcat(path, name, len);
if (suffix(path, len, ".conf"))
return NULL;
/* fall back to static service unless edit/create */
if (!creat && !fexist(path))
paste(path, len, finit_rcsd, name);
if (!creat && !fexist(path)) {
char *at = strchr(path, '@');
if (template && at)
*++at = 0;
else
paste(path, len, finit_rcsd, name);
if (suffix(path, len, ".conf"))
return NULL;
}
return path;
}
@@ -336,14 +340,14 @@ int do_disable(char *arg, int check)
return serv_list("available");
}
len = strlen(arg);
serv = alloca(len + 6);
len = strlen(arg) + 7;
serv = alloca(len);
if (!serv)
ERR(71, "failed allocating stack");
strlcpy(serv, arg, len + 6);
if (len < 6 || strcmp(&serv[len - 5], ".conf"))
strlcat(serv, ".conf", len + 6);
strlcpy(serv, arg, len);
if (suffix(serv, len, ".conf"))
ERR(71, "failed composing service name (%s)", serv);
if (chdir(finit_rcsd))
ERR(72, "failed cd %s", finit_rcsd);
@@ -374,20 +378,30 @@ int serv_touch(char *arg)
return serv_list("enabled");
}
fn = conf(path, sizeof(path), arg, 0);
/* 1. Try /etc/finit.d/enabled/$arg.conf to handle template@.conf */
paste(path, sizeof(path), finit_rcsd, "enabled/");
strlcat(path, arg, sizeof(path));
if (!suffix(path, sizeof(path), ".conf") && fexist(path)) {
fn = path;
goto touchit;
}
/* 2. Try /etc/finit.d/available/$arg.conf and other combos (legacy) */
fn = conf(path, sizeof(path), arg, 0, 0);
if (!fexist(fn)) {
if (!strstr(arg, "finit.conf"))
ERRX(72, "%s not available.", arg);
ERRX(noerr ? 0 : 72, "%s not available.", arg);
if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg);
ERRX(noerr ? 0 : 4, "%s is a built-in service.", arg);
strlcpy(path, finit_conf, sizeof(path));
fn = path;
}
touchit:
/* libite:touch() follows symlinks */
if (utimensat(AT_FDCWD, fn, NULL, AT_SYMLINK_NOFOLLOW))
ERR(71, "failed marking %s for reload", fn);
ERR(noerr ? 0 : 71, "failed marking %s for reload", fn);
return 0;
}
@@ -397,13 +411,18 @@ int serv_show(char *arg)
char path[256];
char *fn;
fn = conf(path, sizeof(path), arg, 0);
fn = conf(path, sizeof(path), arg, 0, 0);
if (!fexist(fn)) {
if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg);
WARNX("Cannot find %s", arg);
return 1;
fn = conf(path, sizeof(path), arg, 0, 1);
if (!fn || !fexist(fn)) {
WARNX("Cannot find %s", arg);
return 1;
}
return systemf("cat %s | sed 's/%%i/system/g'", fn);
}
return systemf("cat %s", fn);
@@ -434,7 +453,7 @@ static int do_edit(char *arg, int creat)
char path[256];
char *fn;
fn = conf(path, sizeof(path), arg, creat);
fn = conf(path, sizeof(path), arg, creat, 0);
if (!fexist(fn)) {
if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg);
@@ -488,7 +507,7 @@ int serv_creat(char *arg)
return do_edit(arg, 1);
/* Open fn for writing from pipe */
fn = conf(buf, sizeof(buf), arg, 1);
fn = conf(buf, sizeof(buf), arg, 1, 0);
if (!fn)
ERR(73, "failed creating conf %s", arg);
@@ -517,7 +536,7 @@ int serv_delete(char *arg)
return serv_list("available");
}
fn = conf(buf, sizeof(buf), arg, 0);
fn = conf(buf, sizeof(buf), arg, 0, 0);
if (!fn) {
if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg);
+1 -1
View File
@@ -1,6 +1,6 @@
/* List and enable/disable service configurations
*
* Copyright (c) 2017-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2017-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+398 -146
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,7 +1,7 @@
/* Finit service monitor, task starter and generic API for managing svc_t
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -42,14 +42,14 @@ int service_timeout_after (svc_t *svc, int timeout, void (*cb)(svc_t *svc
int service_timeout_cancel (svc_t *svc);
void service_forked (svc_t *svc);
void service_ready (svc_t *svc);
void service_ready (svc_t *svc, int ready);
int service_stop (svc_t *svc);
int service_step (svc_t *svc);
void service_step_all (int types);
void service_worker (void *unused);
int service_completed (void);
int service_completed (svc_t **svc);
void service_notify_reconf (void);
void service_init (uev_ctx_t *ctx);
+3 -1
View File
@@ -1,7 +1,7 @@
/* Signal management - Be conservative with what finit responds to!
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -232,6 +232,8 @@ void do_iterate_proc(int (*cb)(int, void *), void *data)
dbg("Skipping %s ...", file);
else if (file[0] == '@')
dbg("Skipping %s ...", &file[1]);
else if (strstr(file, "initctl"))
dbg("Skipping %s ...", file);
else
if (cb(pid, data)) {
dbg("PID %d is still alive (%s)", pid, file);
+1 -1
View File
@@ -1,7 +1,7 @@
/* Signal management - Be conservative with what finit responds to!
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+67 -11
View File
@@ -52,22 +52,30 @@ sm_t sm;
*/
static void sm_check_bootstrap(void *work)
{
static int cnt = 120 * 10; /* We run with 100ms period */
int level = cfglevel;
static int timeout = 120;
int bootstrap_done;
int level = cfglevel;
svc_t *svc = NULL;
dbg("Step all services ...");
service_step_all(SVC_TYPE_ANY);
if (cnt-- > 0 && !service_completed()) {
dbg("Not all bootstrap run/tasks have completed yet ... %d", cnt);
bootstrap_done = service_completed(&svc);
if (timeout-- > 0 && !bootstrap_done) {
dbg("Not all bootstrap run/tasks have completed yet ... %d", timeout);
schedule_work(work);
return;
}
if (cnt > 0)
if (timeout > 0) {
dbg("All run/task have completed, resuming bootstrap.");
else
} else {
dbg("Timeout, resuming bootstrap.");
if (svc)
print(2, "Timeout waiting for %s to run, resuming bootstrap", svc_ident(svc, NULL, 0));
else
print(2, "Timeout waiting for unknown run/task, resuming bootstrap");
}
dbg("Flushing pending .conf file events ...");
conf_flush_events();
@@ -99,6 +107,9 @@ static char *sm_status(sm_state_t state)
case SM_BOOTSTRAP_STATE:
return "bootstrap";
case SM_BOOTSTRAP_WAIT_STATE:
return "bootstrap/wait";
case SM_RUNNING_STATE:
return "running";
@@ -108,15 +119,20 @@ static char *sm_status(sm_state_t state)
case SM_RUNLEVEL_WAIT_STATE:
return "runlevel/wait";
case SM_RUNLEVEL_CLEAN_STATE:
return "runlevel/clean";
case SM_RELOAD_CHANGE_STATE:
return "reload/change";
case SM_RELOAD_WAIT_STATE:
return "reload/wait";
default:
return "unknown";
case SM_RELOAD_CLEAN_STATE:
return "reload/clean";
}
return "unknown";
}
static char sm_runlevel(int lvl)
@@ -161,11 +177,17 @@ void sm_init(sm_t *sm)
void sm_set_runlevel(sm_t *sm, int newlevel)
{
sm->newlevel = newlevel;
dbg("Flushing pending .conf file events ...");
conf_flush_events();
}
void sm_set_reload(sm_t *sm)
{
sm->reload = 1;
dbg("Flushing pending .conf file events ...");
conf_flush_events();
}
int sm_is_in_teardown(sm_t *sm)
@@ -187,7 +209,7 @@ restart:
switch (sm->state) {
case SM_BOOTSTRAP_STATE:
dbg("Bootstrapping all services in runlevel S from %s", finit_conf);
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE);
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE | SVC_TYPE_SYSV);
sm->state = SM_BOOTSTRAP_WAIT_STATE;
break;
@@ -208,7 +230,7 @@ restart:
service_step_all(SVC_TYPE_ANY);
/* Allow runparts to start */
cond_set("int/bootstrap");
cond_set_oneshot("int/bootstrap");
if (sm->newlevel == -1)
break;
@@ -221,7 +243,7 @@ restart:
/* Disable progress output at normal runtime */
enable_progress(0);
/* System bootrapped, launch TTYs et al */
/* System bootstrapped, launch TTYs et al */
bootstrap = 0;
service_step_all(SVC_TYPE_RESPAWN);
sm->state = SM_RUNNING_STATE;
@@ -305,12 +327,30 @@ restart:
sm->in_teardown = 0;
service_step_all(SVC_TYPE_ANY);
sm->state = SM_RUNLEVEL_CLEAN_STATE;
break;
case SM_RUNLEVEL_CLEAN_STATE:
/*
* Wait for post:script or cleanup:script to be collected,
* which moves the svc to HALTED or DEAD state. We will
* be called by the service_monitor() on collect.
*/
svc = svc_clean_completed();
if (svc) {
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
break;
}
/* Cleanup stale services */
svc_clean_dynamic(service_unregister);
#ifdef FINIT_RC_LOCAL
/* Compat SysV init */
if (prevlevel == INIT_LEVEL && !rescue)
run_bg(FINIT_RC_LOCAL, NULL);
#endif
/*
* "I've seen things you people wouldn't believe. Attack ships on fire off
@@ -356,6 +396,22 @@ restart:
dbg("Starting services after reconf ...");
service_step_all(SVC_TYPE_ANY);
sm->state = SM_RELOAD_CLEAN_STATE;
break;
case SM_RELOAD_CLEAN_STATE:
/*
* Wait for post:script or cleanup:script to be collected,
* which moves the svc to HALTED or DEAD state. We will
* be called by the service_monitor() on collect.
*/
svc = svc_clean_completed();
if (svc) {
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
break;
}
/* Cleanup stale services */
svc_clean_dynamic(service_unregister);
+4 -2
View File
@@ -29,9 +29,11 @@ typedef enum {
SM_BOOTSTRAP_WAIT_STATE, /* Waiting for bootstrap to complete */
SM_RUNNING_STATE, /* Normal state, services running */
SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occurred */
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped runlevel processes to be halted */
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped processes to halt */
SM_RUNLEVEL_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
SM_RELOAD_CHANGE_STATE, /* A reload event has occurred */
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped reload processes to be halted */
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped processes to halt */
SM_RELOAD_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
} sm_state_t;
typedef struct sm {
+1 -1
View File
@@ -1,6 +1,6 @@
/* Reset terminal line settings (stty sane)
*
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
/* poor man's sulogin, may be statically linked
*
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
+74 -26
View File
@@ -1,7 +1,7 @@
/* Low-level service primitives and generic API for managing svc_t structures
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -348,6 +348,43 @@ svc_t *svc_stop_completed(void)
return NULL;
}
/**
* svc_clean_completed - Have post: and cleanup: scripts finished?
*
* Called late in runlevel and reload transitions to check if all post: and
* cleanup:scripts have completed. A removed service should end up in the
* DEAD state, while a service with a post:script ends up in HALTED.
*
* Returns:
* %NULL if post: and cleanup: scripts have run, otherwise a pointer to
* the first found svc_t waiting for post: or cleanup:script.
*/
svc_t *svc_clean_completed(void)
{
svc_t *svc, *iter = NULL;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (svc_enabled(svc))
continue;
if (svc_is_runtask(svc) && svc->state == SVC_DONE_STATE)
continue;
if (svc_is_removed(svc)) {
if (svc->state == SVC_DEAD_STATE)
continue; /* any cleanup:script done */
} else {
if (svc->state == SVC_HALTED_STATE)
continue; /* any post:script done */
}
return svc;
}
return NULL;
}
/**
* svc_find - Find a service object by its full path name
* @name: Full path name, e.g., /sbin/syslogd
@@ -580,7 +617,7 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
svc_t *svc, *iter = NULL;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (svc->removed && cb)
if (svc_is_removed(svc) && cb)
cb(svc);
}
}
@@ -649,7 +686,7 @@ int svc_enabled(svc_t *svc)
return 0;
}
if (!svc_ifthen(0, NULL, svc->ifstmt)) {
if (!svc_ifthen(0, NULL, svc->ifstmt, svc->nowarn)) {
// dbg("ifthen:%s>", svc->ifstmt[0] ? svc->ifstmt : "<");
return 0;
}
@@ -704,12 +741,14 @@ int svc_conflicts(svc_t *svc)
* @is_conf: Set when called by service_mark_unavail()
* @ident: svc_t identififcation (name:id)
* @stmt: if: statement from .conf file
* @quiet: If non-zero, do not warn in syslog
*
* Returns:
* %TRUE(1) yes, use this svc_t, %FALSE(0) prune
*/
int svc_ifthen(int is_conf, const char *ident, char *stmt)
int svc_ifthen(int is_conf, const char *ident, char *stmt, int quiet)
{
char stmts[MAX_IDENT_LEN];
int not = 0;
svc_t *svc;
@@ -724,39 +763,48 @@ int svc_ifthen(int is_conf, const char *ident, char *stmt)
if (is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
}
while (ptr[i] != '>' && ptr[i] != 0)
i++;
ptr[i] = 0;
cond = cond_get(stmt);
if (not && cond == COND_ON)
return 0;
if (!not && cond == COND_OFF)
return 0;
strlcpy(stmts, stmt, sizeof(stmts));
for (stmt = strtok(stmts, ","); stmt; stmt = strtok(NULL, ","), not = 0) {
if (stmt[0] == '!') {
stmt++;
not++;
}
cond = cond_get(stmt);
if (not && cond == COND_ON)
return 0;
if (!not && cond == COND_OFF)
return 0;
}
return 1;
}
if (!is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
}
strlcpy(stmts, stmt, sizeof(stmts));
for (stmt = strtok(stmts, ","); stmt; stmt = strtok(NULL, ","), not = 0) {
if (stmt[0] == '!') {
stmt++;
not++;
}
svc = svc_find_by_str(stmt);
if (not && svc) {
logit(LOG_NOTICE, "skipping %s, %s already loaded.", ident, svc_ident(svc, NULL, 0));
return 0;
}
if (!not && !svc) {
logit(LOG_NOTICE, "skipping %s, %s not available.", ident, stmt);
return 0;
svc = svc_find_by_str(stmt);
if (not && svc) {
if (!quiet)
logit(LOG_NOTICE, "skipping %s, %s already loaded.", ident, svc_ident(svc, NULL, 0));
return 0;
}
if (!not && !svc) {
if (!quiet)
logit(LOG_NOTICE, "skipping %s, %s not available.", ident, stmt);
return 0;
}
}
return 1;
+39 -9
View File
@@ -1,7 +1,7 @@
/* Low-level service primitives and generic API for managing svc_t structures
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -52,14 +52,16 @@ typedef enum {
} svc_type_t;
#define SVC_TYPE_ANY (-1)
#define SVC_TYPE_RESPAWN (SVC_TYPE_SERVICE | SVC_TYPE_TTY)
#define SVC_TYPE_RUNTASK (SVC_TYPE_RUN | SVC_TYPE_TASK | SVC_TYPE_SYSV)
#define SVC_TYPE_RESPAWN (SVC_TYPE_SERVICE | SVC_TYPE_SYSV | SVC_TYPE_TTY)
#define SVC_TYPE_RUNTASK (SVC_TYPE_RUN | SVC_TYPE_TASK)
typedef enum {
SVC_HALTED_STATE = 0, /* Not allowed in runlevel, or not enabled. */
SVC_DONE_STATE, /* Task/Run job has been run */
SVC_DEAD_STATE, /* Process is dead and scheduled for removal */
SVC_CLEANUP_STATE, /* Running cleanup: script */
SVC_TEARDOWN_STATE, /* Running post: script */
SVC_STOPPING_STATE, /* Waiting to collect the child process */
SVC_CLEANUP_STATE, /* Running post: script */
SVC_SETUP_STATE, /* Running pre: script */
SVC_PAUSED_STATE, /* Condition is in flux, process SIGSTOPed */
SVC_WAITING_STATE, /* Enabled but condition not satisfied */
@@ -83,6 +85,14 @@ typedef enum {
SVC_ONCRASH_SCRIPT,
} svc_oncrash_action_t;
/* 0: none, 1: systemd, 2: s6 */
typedef enum {
SVC_NOTIFY_NONE = 0,
SVC_NOTIFY_PID,
SVC_NOTIFY_SYSTEMD,
SVC_NOTIFY_S6,
} svc_notify_t;
#define MAX_ID_LEN 16
#define MAX_ARG_LEN 64
#define MAX_CMD_LEN 256
@@ -138,7 +148,7 @@ typedef struct svc {
char cond[MAX_COND_LEN];
/* Instance specifics */
int job; /* For intenal use only, canonical ref is NAME:ID */
int job; /* For internal use only, canonical ref is NAME:ID */
char name[MAX_ARG_LEN];
char id[MAX_ID_LEN]; /* :ID */
char ifstmt[MAX_IDENT_LEN];
@@ -188,9 +198,18 @@ typedef struct svc {
char conflict[MAX_ARG_LEN];
char desc[MAX_STR_LEN];
char env[MAX_CMD_LEN];
char pre_script[MAX_CMD_LEN];
int pre_tmo;
char post_script[MAX_CMD_LEN];
int post_tmo;
char ready_script[MAX_CMD_LEN];
int ready_tmo;
char cleanup_script[MAX_CMD_LEN];
int cleanup_tmo;
/*
* Used to forcefully kill services that won't shutdown on
@@ -202,7 +221,7 @@ typedef struct svc {
/*
* Readiness notification socket: systemd, s6
*/
int notify; /* 0: none, 1: systemd, 2: s6 */
svc_notify_t notify;
uev_t notify_watcher; /* i/o watcher */
/* time at svc_del(), used by gc timer */
@@ -229,6 +248,7 @@ void svc_foreach (int (*cb)(svc_t *));
void svc_foreach_type (int types, int (*cb)(svc_t *));
svc_t *svc_stop_completed (void);
svc_t *svc_clean_completed (void);
void svc_mark (svc_t *svc);
void svc_mark_dynamic (void);
@@ -241,7 +261,7 @@ void svc_prune_bootstrap (void);
void svc_enable (svc_t *svc);
int svc_enabled (svc_t *svc);
int svc_conflicts (svc_t *svc);
int svc_ifthen (int is_conf, const char *ident, char *stmt);
int svc_ifthen (int is_conf, const char *ident, char *stmt, int quiet);
int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *));
@@ -251,6 +271,7 @@ static inline int svc_is_tty (svc_t *svc) { return svc && SVC_TYPE_TTY
static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type);}
static inline int svc_is_forking (svc_t *svc) { return svc && svc->forking; }
static inline int svc_is_manual (svc_t *svc) { return svc && svc->manual; }
static inline int svc_is_nohup (svc_t *svc) { return svc && (0 == svc->sighup); }
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sighup || 0 != svc->args_dirty); }
@@ -258,11 +279,14 @@ static inline int svc_has_pidfile (svc_t *svc) { return svc_is_daemon(svc) && s
static inline int svc_has_pre (svc_t *svc) { return svc->pre_script[0]; }
static inline int svc_has_post (svc_t *svc) { return svc->post_script[0]; }
static inline int svc_has_ready (svc_t *svc) { return svc->ready_script[0];}
static inline int svc_has_cleanup (svc_t *svc) { return svc->cleanup_script[0]; }
static inline void svc_starting (svc_t *svc) { if (svc) svc->starting = 1; }
static inline void svc_started (svc_t *svc) { if (svc) svc->starting = 0; }
static inline int svc_is_starting (svc_t *svc) { return svc && 0 != svc->starting; }
static inline int svc_is_running (svc_t *svc) { return svc && svc->state == SVC_RUNNING_STATE; }
static inline int svc_is_stopping (svc_t *svc) { return svc && svc->state == SVC_STOPPING_STATE; }
static inline int svc_is_stopped (svc_t *svc) { return svc && svc->block == SVC_BLOCK_USER; }
static inline int svc_is_removed (svc_t *svc) { return svc && svc->removed; }
static inline int svc_is_changed (svc_t *svc) { return svc && 0 != svc->dirty; }
@@ -377,12 +401,15 @@ static inline char *svc_status(svc_t *svc)
return "stopping";
}
case SVC_CLEANUP_STATE:
return "cleanup";
case SVC_TEARDOWN_STATE:
return "teardown";
case SVC_SETUP_STATE:
return "setup";
case SVC_CLEANUP_STATE:
return "cleanup";
case SVC_PAUSED_STATE:
return "paused";
@@ -395,6 +422,9 @@ static inline char *svc_status(svc_t *svc)
case SVC_RUNNING_STATE:
return "running";
case SVC_DEAD_STATE:
return "dead";
default:
return "UNKNOWN";
}
+10 -6
View File
@@ -1,6 +1,6 @@
/* Limited tmpfiles.d implementation
*
* Copyright (c) 2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -78,8 +78,8 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
if (ftw->level == 0)
return 1;
if (remove(fpath))
warn("Failed removing condition %s", fpath);
if (remove(fpath) && errno != EBUSY)
warn("Failed removing %s", fpath);
return 0;
@@ -90,7 +90,7 @@ static int rmrf(const char *path)
if (!fisdir(path))
return 0;
nftw(path, do_delete, 20, FTW_DEPTH);
nftw(path, do_delete, 20, FTW_DEPTH | FTW_PHYS);
if (remove(path) && errno != ENOENT)
warn("Failed removing path %s", path);
@@ -434,6 +434,10 @@ static void tmpfiles(char *line)
}
}
break;
case 'X':
case 'x':
dbg("Unsupported x/X command, ignoring %s, no support for clean at runtime.", path);
break;
case 'Z':
opts = "-R";
/* fallthrough */
@@ -471,7 +475,7 @@ void tmpfilesd(void)
/* in priority order */
char *dir[] = {
FINIT_TMPFILES "/*.conf",
TMPFILES_PATH "/*.conf",
TMPFILES_PATH_ "/*.conf",
"/usr/lib/tmpfiles.d/*.conf",
"/run/tmpfiles.d/*.conf",
"/etc/tmpfiles.d/*.conf", /* local admin overrides */
@@ -492,7 +496,7 @@ void tmpfilesd(void)
/* check for overrides */
for (j = i + 1; j < gl.gl_pathc; j++) {
if (strcmp(basename(fn), basename(gl.gl_pathv[j])))
if (strcmp(basenm(fn), basenm(gl.gl_pathv[j])))
continue;
fn = NULL;
break;
+1 -1
View File
@@ -1,6 +1,6 @@
/* Limited tmpfiles.d implementation
*
* Copyright (c) 2023 Joachim Wiberg <troglobit@gmail.com>
* Copyright (c) 2024 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal

Some files were not shown because too many files have changed in this diff Show More