Compare commits

...
48 Commits
Author SHA1 Message Date
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
34 changed files with 414 additions and 155 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \ --post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
-O coverity-latest.tar.gz.md5 -O coverity-latest.tar.gz.md5
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
- uses: actions/cache@v3 - uses: actions/cache@v4
id: cache id: cache
with: with:
path: coverity-latest.tar.gz path: coverity-latest.tar.gz
+51 -1
View File
@@ -4,6 +4,54 @@ Change Log
All relevant changes are documented in this file. All relevant changes are documented in this file.
[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 legact 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 [4.7][] - 2024-01-07
-------------------- --------------------
@@ -24,6 +72,7 @@ All relevant changes are documented in this file.
Found and fixed by Ryan Rorison Found and fixed by Ryan Rorison
- Fix #389: must libc requires `libgen.h` for `basename()` function. - Fix #389: must libc requires `libgen.h` for `basename()` function.
Reported and worked around with new `basenm()` function by Stargirl 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 [4.6][] - 2023-11-13
@@ -1655,7 +1704,8 @@ Major bug fix release.
* Initial release * Initial release
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.7...HEAD [UNRELEASED]: https://github.com/troglobit/finit/compare/4.8...HEAD
[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.7]: https://github.com/troglobit/finit/compare/4.6...4.7
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6 [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.5]: https://github.com/troglobit/finit/compare/4.4...4.5
+1 -2
View File
@@ -405,8 +405,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, 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. with a few hooks and blocking call outs to external scripts.
However, not all `initctl` commands are prohibited, supported commands: However, not all `initctl` commands are prohibited. Supported commands:
are:
- `inictl cond`: only operate of files in `/run/finit/cond` - `inictl cond`: only operate of files in `/run/finit/cond`
- `initctl enable/disable`: enabled run/task/service is activated on - `initctl enable/disable`: enabled run/task/service is activated on
+25 -8
View File
@@ -1,4 +1,4 @@
AC_INIT([Finit], [4.7], [https://github.com/troglobit/finit/issues], AC_INIT([Finit], [4.8], [https://github.com/troglobit/finit/issues],
[finit], [https://troglobit.com/projects/finit/]) [finit], [https://troglobit.com/projects/finit/])
AC_CONFIG_AUX_DIR(aux) AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects]) AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
@@ -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]),,[ AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
enable_fsckfix=no]) 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, AC_ARG_ENABLE(redirect,
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[ AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
enable_redirect=yes]) 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, AC_ARG_ENABLE(logrotate,
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[ AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
enable_logrotate=yes]) enable_logrotate=yes])
@@ -181,6 +189,12 @@ AS_IF([test "x$enable_auto_reload" = "xyes"], [
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [ AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])]) 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"], [ AS_IF([test "x$enable_fastboot" = "xyes"], [
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])]) AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
@@ -227,10 +241,9 @@ AC_DEFINE_UNQUOTED(FINIT_RCSD, "$rcsd_path", [Finit rcS.d/, default /etc/finit.d
AC_SUBST(FINIT_RCSD, "$rcsd_path") AC_SUBST(FINIT_RCSD, "$rcsd_path")
AS_IF([test "x$with_rc_local" != "xno"], [ AS_IF([test "x$with_rc_local" != "xno"], [
AS_IF([test "x$rclocal" = "xyes"], [ AS_IF([test "x$rclocal" = "xyes"], [rclocal=$sysconfdir/rc.local])
rclocal=$sysconfdir/rc.local])]) AC_EXPAND_DIR(rclocal_path, "$rclocal")
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.])])
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$with_sysconfig" != "xno"], [
AS_IF([test "x$sysconfig" != "xdefault"], [ AS_IF([test "x$sysconfig" != "xdefault"], [
@@ -355,15 +368,16 @@ cat <<EOF
------------------ Summary ------------------ ------------------ Summary ------------------
$PACKAGE_NAME version $PACKAGE_VERSION $PACKAGE_NAME version $PACKAGE_VERSION
Prefix................: $prefix Prefix................: $(eval echo $prefix)
Exec prefix...........: $eprefix Exec prefix...........: $(eval echo $exec_prefix)
Libdir................: $(eval echo $libdir)
Sysconfdir............: `eval echo $sysconfdir` Sysconfdir............: `eval echo $sysconfdir`
Localstatedir.........: `eval echo $localstatedir` Localstatedir.........: `eval echo $localstatedir`
Default fstab.........: `eval echo $fstab` Default fstab.........: `eval echo $fstab`
Finit config file.....: $conf_path Finit config file.....: $conf_path
Finit config.d path...: $rcsd_path Finit config.d path...: $rcsd_path
Finit plugin path.....: $plugin_path Finit plugin path.....: $plugin_path
Compat rc.local path..: $rclocal_path Compat rc.local path..: `eval echo $rclocal`
System environment....: ${sysconfig_path:-${sysconfig}} System environment....: ${sysconfig_path:-${sysconfig}}
Random seed path......: $random_path Random seed path......: $random_path
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
@@ -382,6 +396,9 @@ Optional features:
Built-in sulogin......: $with_sulogin $sulogin Built-in sulogin......: $with_sulogin $sulogin
Built-in watchdogd....: $with_watchdog $watchdog Built-in watchdogd....: $with_watchdog $watchdog
Built-in logrotate....: $enable_logrotate 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 Skip fsck check.......: $enable_fastboot
Run fsck fix mode.....: $enable_fsckfix Run fsck fix mode.....: $enable_fsckfix
Redirect output.......: $enable_redirect Redirect output.......: $enable_redirect
+2
View File
@@ -1,6 +1,8 @@
HowTo: Finit on Alpine Linux 3.4...3.19 HowTo: Finit on Alpine Linux 3.4...3.19
======================================= =======================================
> **Blog** https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that 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, the user has already installed make, a compiler, C library header files,
and other tools needed to build a GNU configure based project. and other tools needed to build a GNU configure based project.
+11 -2
View File
@@ -52,7 +52,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
ptr = slash++; ptr = slash++;
slash = strchr(ptr, '/'); slash = strchr(ptr, '/');
if (slash) { if (slash) {
dbg("Path too deep, skipping."); dbg("Path too deep, skipping %s", path);
return -1; return -1;
} }
} }
@@ -66,6 +66,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
char cond[MAX_COND_LEN]; char cond[MAX_COND_LEN];
char fn[PATH_MAX]; char fn[PATH_MAX];
svc_t *svc; svc_t *svc;
char *nm;
paste(fn, sizeof(fn), dir, name); paste(fn, sizeof(fn), dir, name);
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0)) if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
@@ -79,9 +80,16 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
return; return;
} }
dbg("Found svc %s for %s with pid %d", svc_ident(svc, NULL, 0), fn, svc->pid); /* Service condistion to set/clear */
mkcond(svc, cond, sizeof(cond)); 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)) { if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
/* /*
* only mark native services as started, the s6 and * only mark native services as started, the s6 and
@@ -125,6 +133,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE) if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
service_ready(svc, 1); service_ready(svc, 1);
} else if (mask & IN_DELETE) { } else if (mask & IN_DELETE) {
sneaky_zebra:
cond_clear(cond); cond_clear(cond);
if (svc->notify == SVC_NOTIFY_PID) if (svc->notify == SVC_NOTIFY_PID)
service_ready(svc, 0); service_ready(svc, 0);
+2 -1
View File
@@ -180,7 +180,8 @@ static void rtc_restore(void *arg)
rc = 2; rc = 2;
} }
print_desc(NULL, "Restoring system clock (UTC) from RTC"); if (!rc)
print_desc(NULL, "Restoring system clock (UTC) from RTC");
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */ tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
tv.tv_sec = mktime(&tm); tv.tv_sec = mktime(&tm);
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) { if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
+33 -9
View File
@@ -42,11 +42,29 @@
#define RANDOM_BYTES (32*1024) #define RANDOM_BYTES (32*1024)
#endif #endif
#ifdef RANDOMSEED
static void fallback(FILE *fp)
{
struct timeval tv;
int iter = 128;
gettimeofday(&tv, NULL);
srandom(tv.tv_sec % 3600);
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) static void setup(void *arg)
{ {
#ifdef RANDOMSEED #ifdef RANDOMSEED
struct rand_pool_info *rpi; struct rand_pool_info *rpi;
ssize_t len = 0; ssize_t len = 0;
struct stat st;
int rc = -1; int rc = -1;
int fd, err; int fd, err;
@@ -55,7 +73,7 @@ static void setup(void *arg)
return; return;
} }
if (!fexist(RANDOMSEED)) { if (stat(RANDOMSEED, &st) || st.st_size < 512) {
int ret = 1; int ret = 1;
mode_t prev; mode_t prev;
FILE *fp; FILE *fp;
@@ -64,16 +82,22 @@ static void setup(void *arg)
prev = umask(077); prev = umask(077);
fp = fopen(RANDOMSEED, "w"); fp = fopen(RANDOMSEED, "w");
if (fp) { if (fp) {
int iter = 128; const char *hwrng = "/dev/hwrng";
struct timeval tv; FILE *hw;
gettimeofday(&tv, NULL); hw = fopen(hwrng, "r");
srandom(tv.tv_sec % 3600); if (hw) {
while (iter--) { char buf[512];
uint32_t i, prng = random(); size_t len;
for (i = 0; i < sizeof(prng); i++) len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp); if (len == 0)
fallback(fp);
else
len = fwrite(buf, sizeof(buf[0]), len, fp);
fclose(hw);
} else {
fallback(fp);
} }
ret = fclose(fp); ret = fclose(fp);
} }
+3 -1
View File
@@ -377,7 +377,9 @@ static void api_cb(uev_t *w, void *arg, int events)
case INIT_CMD_POWEROFF: case INIT_CMD_POWEROFF:
case INIT_CMD_SUSPEND: case INIT_CMD_SUSPEND:
if (IS_RESERVED_RUNLEVEL(runlevel)) { 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; goto leave;
} }
default: default:
+5
View File
@@ -463,6 +463,11 @@ void cgroup_init(uev_ctx_t *ctx)
FILE *fp; FILE *fp;
int fd; int fd;
#ifndef CGROUP2_ENABLED
avail = 0;
return;
#endif
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) { if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
if (errno == ENOENT) if (errno == ENOENT)
logit(LOG_INFO, "Kernel does not support cgroups v2, disabling."); logit(LOG_INFO, "Kernel does not support cgroups v2, disabling.");
+4 -2
View File
@@ -29,6 +29,8 @@
#include "client.h" #include "client.h"
#include "log.h" #include "log.h"
#define REQUEST_TIMEOUT 15000
static int sd = -1; static int sd = -1;
int client_connect(void) int client_connect(void)
@@ -85,7 +87,7 @@ int client_request(struct init_request *rq, ssize_t len)
pfd.fd = sd; pfd.fd = sd;
pfd.events = POLLOUT; 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); warn("Timed out waiting for Finit, errno %d", errno);
return -1; return -1;
} }
@@ -107,7 +109,7 @@ int client_request(struct init_request *rq, ssize_t len)
pfd.fd = sd; pfd.fd = sd;
pfd.events = POLLIN | POLLERR | POLLHUP; pfd.events = POLLIN | POLLERR | POLLHUP;
if ((rc = poll(&pfd, 1, 2000)) <= 0) { if ((rc = poll(&pfd, 1, REQUEST_TIMEOUT)) <= 0) {
if (rc) { if (rc) {
if (errno == EINTR) /* shutdown/reboot */ if (errno == EINTR) /* shutdown/reboot */
return -1; return -1;
+5 -1
View File
@@ -35,6 +35,7 @@
#include "cond.h" #include "cond.h"
#include "pid.h" #include "pid.h"
#include "service.h" #include "service.h"
#include "sm.h"
struct cond_boot { struct cond_boot {
TAILQ_ENTRY(cond_boot) link; TAILQ_ENTRY(cond_boot) link;
@@ -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); err(1, "Failed removing condition %s", fpath);
cond = ptr + strlen(COND_BASE) + 1; 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; return 0;
} }
+4 -1
View File
@@ -348,8 +348,11 @@ static void parse_kernel_loglevel(void)
*/ */
void conf_parse_cmdline(int argc, char *argv[]) void conf_parse_cmdline(int argc, char *argv[])
{ {
const char *ptr;
/* Set up defaults */ /* Set up defaults */
fstab = strdup(FINIT_FSTAB); if ((ptr = FINIT_FSTAB))
fstab = strdup(ptr);
finit_conf = strdup(FINIT_CONF); finit_conf = strdup(FINIT_CONF);
finit_rcsd = strdup(FINIT_RCSD); finit_rcsd = strdup(FINIT_RCSD);
path = getenv("PATH"); path = getenv("PATH");
+18 -17
View File
@@ -138,31 +138,32 @@ int run(char *cmd, char *log)
pid = fork(); pid = fork();
if (0 == pid) { if (0 == pid) {
int rc = EX_OSERR; char *pfx, buf[256];
FILE *pp;
int rc;
setsid(); setsid();
sig_unblock(); sig_unblock();
if (!log) { if (!log) {
do_redirect(); do_redirect();
execvp(args[0], args); execvp(args[0], args);
} else { _exit(EX_OSERR);
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(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) { } else if (-1 == pid) {
err(1, "%s", !log ? args[0] : cmd); err(1, "%s", !log ? args[0] : cmd);
if (backup) if (backup)
+13 -5
View File
@@ -87,14 +87,22 @@ svc_t *wdog = NULL; /* No watchdog by default */
*/ */
static void banner(void) static void banner(void)
{ {
#ifndef KERNEL_LOGGING
/* /*
* Silence kernel logs, assuming users have sysklogd or * Silence kernel logs, assuming users have sysklogd or
* similar enabled to start emptying /dev/kmsg, but for * similar enabled to start emptying /dev/kmsg.
* our progress we want to own the console. *
* 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) if (!debug && !kerndebug)
klogctl(6, NULL, 0); klogctl(6, NULL, 0);
#endif
/* /*
* First level hooks, if you want to run here, you're * First level hooks, if you want to run here, you're
* pretty much on your own. Nothing's up yet ... * pretty much on your own. Nothing's up yet ...
@@ -401,7 +409,7 @@ static void fs_finalize(void)
* To override any of this behavior, add entries to /etc/fstab * To override any of this behavior, add entries to /etc/fstab
* for /run (and optionally /run/lock). * 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%"); 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 */ /* This prevents user DoS of /run by filling /run/lock at the expense of another tmpfs, max 5MiB */
@@ -410,7 +418,7 @@ static void fs_finalize(void)
} }
/* Modern systems use tmpfs for /tmp */ /* 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"); fs_mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV, "mode=1777");
} }
+3
View File
@@ -121,6 +121,9 @@ static int osrel(struct osrel *rel)
snprintf(rel->version, sizeof(rel->version), "(%s)", codename); 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; return 0;
} }
+10 -9
View File
@@ -522,9 +522,10 @@ void networking(int updown)
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
int rc = EX_OSERR;
const char *cmd; const char *cmd;
char buf[256];
FILE *pp; FILE *pp;
int rc;
setsid(); setsid();
sig_unblock(); sig_unblock();
@@ -539,16 +540,16 @@ void networking(int updown)
cmd = "ifdown -a -f 2>&1"; cmd = "ifdown -a -f 2>&1";
pp = popen(cmd, "r"); pp = popen(cmd, "r");
if (pp) { if (!pp)
char buf[256]; _exit(EX_OSERR);
while (fgets(buf, sizeof(buf), pp)) while (fgets(buf, sizeof(buf), pp))
logit(LOG_NOTICE, "network: %s", chomp(buf)); logit(LOG_NOTICE, "network: %s", chomp(buf));
rc = pclose(pp); rc = pclose(pp);
} if (rc == -1)
_exit(EX_OSERR);
_exit(rc); _exit(WEXITSTATUS(rc));
} }
cgroup_service("network", pid, NULL); cgroup_service("network", pid, NULL);
print(pid > 0 ? 0 : 1, "%s network interfaces ...", print(pid > 0 ? 0 : 1, "%s network interfaces ...",
-9
View File
@@ -42,8 +42,6 @@ static int loglevel = LOG_INFO;
void log_init(void) void log_init(void)
{ {
ttinit();
if (debug) if (debug)
loglevel = LOG_DEBUG; loglevel = LOG_DEBUG;
else else
@@ -53,13 +51,6 @@ void log_init(void)
/* If we enabled terse mode at boot, restore to previous setting at shutdown */ /* If we enabled terse mode at boot, restore to previous setting at shutdown */
void log_exit(void) 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); enable_progress(1);
} }
+18 -6
View File
@@ -26,18 +26,27 @@
#else #else
#include <sys/prctl.h> #include <sys/prctl.h>
const char *active_msg = NULL;
int interactive = 1;
int debug; int debug;
static void print_desc(const char *prefix, const char *msg) 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) static void print_result(int rc)
{ {
if (rc) if (interactive) {
fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr); if (rc)
else fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
fputs("\r\e[1m[\e[0m\e[1;32m OK \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) void sig_unblock(void)
@@ -193,8 +202,11 @@ int main(int argc, char *argv[])
int rc, c, progress = 0, sysv = 0; int rc, c, progress = 0, sysv = 0;
char *dir; char *dir;
while ((c = getopt(argc, argv, "dh?ps")) != EOF) { while ((c = getopt(argc, argv, "bdh?ps")) != EOF) {
switch(c) { switch(c) {
case 'b': /* batch mode */
interactive = 0;
break;
case 'd': case 'd':
debug = 1; debug = 1;
break; break;
+46 -27
View File
@@ -222,20 +222,13 @@ int serv_list(char *arg)
* If the resulting file doesn't exist, and creat is not set, *or* * If the resulting file doesn't exist, and creat is not set, *or*
* the base directory doesn't exist, we return NULL. * 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")) { if (!name || !name[0] || !strcmp(name, "finit") || !strcmp(name, "finit.conf")) {
strlcpy(path, finit_conf, len); strlcpy(path, finit_conf, len);
return path; return path;
} }
if (!strstr(name, ".conf")) {
snprintf(corr, sizeof(corr), "%s.conf", name);
name = corr;
}
if (!fisdir(finit_rcsd)) if (!fisdir(finit_rcsd))
return NULL; return NULL;
@@ -243,14 +236,25 @@ static char *conf(char *path, size_t len, char *name, int creat)
if (!fisdir(path)) { if (!fisdir(path)) {
if (creat && mkdir(path, 0755) && errno != EEXIST) if (creat && mkdir(path, 0755) && errno != EEXIST)
return NULL; return NULL;
else paste(path, len, finit_rcsd, name);
paste(path, len, finit_rcsd, name);
} else } else
strlcat(path, name, len); strlcat(path, name, len);
if (suffix(path, len, ".conf"))
return NULL;
/* fall back to static service unless edit/create */ /* fall back to static service unless edit/create */
if (!creat && !fexist(path)) if (!creat && !fexist(path)) {
paste(path, len, finit_rcsd, name); 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; return path;
} }
@@ -336,14 +340,14 @@ int do_disable(char *arg, int check)
return serv_list("available"); return serv_list("available");
} }
len = strlen(arg); len = strlen(arg) + 7;
serv = alloca(len + 6); serv = alloca(len);
if (!serv) if (!serv)
ERR(71, "failed allocating stack"); ERR(71, "failed allocating stack");
strlcpy(serv, arg, len + 6); strlcpy(serv, arg, len);
if (len < 6 || strcmp(&serv[len - 5], ".conf")) if (suffix(serv, len, ".conf"))
strlcat(serv, ".conf", len + 6); ERR(71, "failed composing service name (%s)", serv);
if (chdir(finit_rcsd)) if (chdir(finit_rcsd))
ERR(72, "failed cd %s", finit_rcsd); ERR(72, "failed cd %s", finit_rcsd);
@@ -374,20 +378,30 @@ int serv_touch(char *arg)
return serv_list("enabled"); 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 (!fexist(fn)) {
if (!strstr(arg, "finit.conf")) if (!strstr(arg, "finit.conf"))
ERRX(72, "%s not available.", arg); ERRX(noerr ? 0 : 72, "%s not available.", arg);
if (is_builtin(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)); strlcpy(path, finit_conf, sizeof(path));
fn = path; fn = path;
} }
touchit:
/* libite:touch() follows symlinks */ /* libite:touch() follows symlinks */
if (utimensat(AT_FDCWD, fn, NULL, AT_SYMLINK_NOFOLLOW)) 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; return 0;
} }
@@ -397,13 +411,18 @@ int serv_show(char *arg)
char path[256]; char path[256];
char *fn; char *fn;
fn = conf(path, sizeof(path), arg, 0); fn = conf(path, sizeof(path), arg, 0, 0);
if (!fexist(fn)) { if (!fexist(fn)) {
if (is_builtin(arg)) if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg); ERRX(4, "%s is a built-in service.", arg);
WARNX("Cannot find %s", arg); fn = conf(path, sizeof(path), arg, 0, 1);
return 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); return systemf("cat %s", fn);
@@ -434,7 +453,7 @@ static int do_edit(char *arg, int creat)
char path[256]; char path[256];
char *fn; char *fn;
fn = conf(path, sizeof(path), arg, creat); fn = conf(path, sizeof(path), arg, creat, 0);
if (!fexist(fn)) { if (!fexist(fn)) {
if (is_builtin(arg)) if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg); ERRX(4, "%s is a built-in service.", arg);
@@ -488,7 +507,7 @@ int serv_creat(char *arg)
return do_edit(arg, 1); return do_edit(arg, 1);
/* Open fn for writing from pipe */ /* Open fn for writing from pipe */
fn = conf(buf, sizeof(buf), arg, 1); fn = conf(buf, sizeof(buf), arg, 1, 0);
if (!fn) if (!fn)
ERR(73, "failed creating conf %s", arg); ERR(73, "failed creating conf %s", arg);
@@ -517,7 +536,7 @@ int serv_delete(char *arg)
return serv_list("available"); return serv_list("available");
} }
fn = conf(buf, sizeof(buf), arg, 0); fn = conf(buf, sizeof(buf), arg, 0, 0);
if (!fn) { if (!fn) {
if (is_builtin(arg)) if (is_builtin(arg))
ERRX(4, "%s is a built-in service.", arg); ERRX(4, "%s is a built-in service.", arg);
+28 -24
View File
@@ -1632,11 +1632,18 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
} }
if (type == SVC_TYPE_TTY) { if (type == SVC_TYPE_TTY) {
size_t i, len = 0; size_t i, len;
char *ptr;
if (tty_parse_args(&tty, cmd, &args)) if (tty_parse_args(&tty, cmd, &args))
return errno; return errno;
if (tty_isatcon(tty.dev))
dev = tty_atcon();
else
dev = tty.dev;
next:
len = 0;
if (tty.cmd) if (tty.cmd)
len += strlen(tty.cmd); len += strlen(tty.cmd);
else else
@@ -1659,14 +1666,22 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
if (!cmd) if (!cmd)
return errno; return errno;
if (tty_isatcon(tty.dev))
dev = tty_atcon();
else
dev = tty.dev;
/* tty's always respawn, never incr. restart_cnt */ /* tty's always respawn, never incr. restart_cnt */
respawn = 1; respawn = 1;
next:
/* Create name:id tuple for identity, e.g., tty:S0 */
ptr = strrchr(dev, '/');
if (ptr)
ptr++;
else
ptr = dev;
if (!strncmp(ptr, "tty", 3))
ptr += 3;
name = "tty";
if (!id || id[0] == 0)
id = ptr;
svc = svc_find_by_tty(dev); svc = svc_find_by_tty(dev);
} else } else
svc = svc_find(name, id); svc = svc_find(name, id);
@@ -1722,8 +1737,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
conf_parse_cond(svc, cond); conf_parse_cond(svc, cond);
if (type == SVC_TYPE_TTY) { if (type == SVC_TYPE_TTY) {
char *ptr;
if (dev) if (dev)
strlcpy(svc->dev, dev, sizeof(svc->dev)); strlcpy(svc->dev, dev, sizeof(svc->dev));
if (tty.baud) if (tty.baud)
@@ -1738,19 +1751,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
/* TTYs cannot be redirected */ /* TTYs cannot be redirected */
log = NULL; log = NULL;
/* Create name:id tuple for identity, e.g., tty:S0 */
ptr = strrchr(svc->dev, '/');
if (ptr)
ptr++;
else
ptr = svc->dev;
if (!strncmp(ptr, "tty", 3))
ptr += 3;
if (!id || id[0] == 0)
id = ptr;
strlcpy(svc->name, "tty", sizeof(svc->name));
strlcpy(svc->id, id, sizeof(svc->id));
} }
parse_cmdline_args(svc, cmd, &args); parse_cmdline_args(svc, cmd, &args);
@@ -1870,8 +1870,10 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
/* continue expanding any 'tty @console ...' */ /* continue expanding any 'tty @console ...' */
if (tty_isatcon(tty.dev)) { if (tty_isatcon(tty.dev)) {
dev = tty_atcon(); dev = tty_atcon();
if (dev) if (dev) {
id = NULL; /* reset for next tty:ID */
goto next; goto next;
}
} }
return 0; return 0;
@@ -2261,7 +2263,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
/* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */ /* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */
if (new_state == SVC_STOPPING_STATE) { if (new_state == SVC_STOPPING_STATE) {
dbg("%s is stopping, wait %d sec before sending SIGKILL ...", dbg("%s is stopping, wait %d sec before sending SIGKILL ...",
svc_ident(svc, NULL, 0), svc->killdelay / 1000); svc_ident(svc, NULL, 0), svc->killdelay / 1000);
service_timeout_cancel(svc); service_timeout_cancel(svc);
service_timeout_after(svc, svc->killdelay, service_kill); service_timeout_after(svc, svc->killdelay, service_kill);
} }
@@ -2299,6 +2301,8 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
if ((old_state == SVC_RUNNING_STATE && new_state == SVC_PAUSED_STATE) || if ((old_state == SVC_RUNNING_STATE && new_state == SVC_PAUSED_STATE) ||
(old_state == SVC_PAUSED_STATE && new_state == SVC_RUNNING_STATE)) (old_state == SVC_PAUSED_STATE && new_state == SVC_RUNNING_STATE))
; /* only paused during reload, don't clear conds. */ ; /* only paused during reload, don't clear conds. */
else if (sm_is_in_teardown(&sm))
cond_clear_noupdate(cond);
else else
cond_clear(cond); cond_clear(cond);
+2
View File
@@ -316,9 +316,11 @@ restart:
/* Cleanup stale services */ /* Cleanup stale services */
svc_clean_dynamic(service_unregister); svc_clean_dynamic(service_unregister);
#ifdef FINIT_RC_LOCAL
/* Compat SysV init */ /* Compat SysV init */
if (prevlevel == INIT_LEVEL && !rescue) if (prevlevel == INIT_LEVEL && !rescue)
run_bg(FINIT_RC_LOCAL, NULL); run_bg(FINIT_RC_LOCAL, NULL);
#endif
/* /*
* "I've seen things you people wouldn't believe. Attack ships on fire off * "I've seen things you people wouldn't believe. Attack ships on fire off
+1
View File
@@ -271,6 +271,7 @@ 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 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_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_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_removed (svc_t *svc) { return svc && svc->removed; } 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; } static inline int svc_is_changed (svc_t *svc) { return svc && 0 != svc->dirty; }
+5 -1
View File
@@ -90,7 +90,7 @@ static int rmrf(const char *path)
if (!fisdir(path)) if (!fisdir(path))
return 0; return 0;
nftw(path, do_delete, 20, FTW_DEPTH); nftw(path, do_delete, 20, FTW_DEPTH | FTW_PHYS);
if (remove(path) && errno != ENOENT) if (remove(path) && errno != ENOENT)
warn("Failed removing path %s", path); warn("Failed removing path %s", path);
@@ -434,6 +434,10 @@ static void tmpfiles(char *line)
} }
} }
break; break;
case 'X':
case 'x':
dbg("Unsupported x/X command, ignoring %s, no support for clean at runtime.", path);
break;
case 'Z': case 'Z':
opts = "-R"; opts = "-R";
/* fallthrough */ /* fallthrough */
+16
View File
@@ -42,6 +42,8 @@
# include <sys/ioctl.h> # include <sys/ioctl.h>
#endif #endif
#include <sys/sysinfo.h> /* sysinfo() */ #include <sys/sysinfo.h> /* sysinfo() */
#include <sys/vfs.h> /* statfs */
#include <linux/magic.h>
#ifdef _LIBITE_LITE #ifdef _LIBITE_LITE
# include <libite/lite.h> # include <libite/lite.h>
#else #else
@@ -572,6 +574,20 @@ int fismnt(char *dir)
return ismnt("/proc/mounts", dir, NULL); return ismnt("/proc/mounts", dir, NULL);
} }
/* Return 1 if dir is a backed by tmpfs or overlayfs */
int fistmpfs(char *dir)
{
struct statfs info = {0};
if (statfs(dir, &info))
return 0;
if (info.f_type == TMPFS_MAGIC || info.f_type == OVERLAYFS_SUPER_MAGIC)
return 1;
return 0;
}
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
/* /*
* Called by initctl, and by finit at boot and shutdown, to * Called by initctl, and by finit at boot and shutdown, to
+21
View File
@@ -80,6 +80,7 @@ void de_dotdot (char *file);
int ismnt (char *file, char *dir, char *mode); int ismnt (char *file, char *dir, char *mode);
int fismnt (char *dir); int fismnt (char *dir);
int fistmpfs (char *dir);
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
int ttinit (void); int ttinit (void);
@@ -109,6 +110,26 @@ static inline int paste(char *buf, size_t len, const char *dir, const char *file
fisslashdir(dir) ? "" : file[0] == '/' ? "" : "/", file); fisslashdir(dir) ? "" : file[0] == '/' ? "" : "/", file);
} }
/* ensure path has suffix */
static inline int suffix(char *path, size_t len, const char *sfx)
{
size_t slen = strlen(sfx);
size_t plen = strlen(path);
if (plen < slen)
slen = strlcat(path, sfx, len);
else {
plen -= slen;
if (strcmp(&path[plen], sfx))
slen = strlcat(path, sfx, len);
}
if (slen >= len)
return -1;
return 0;
}
#endif /* FINIT_UTIL_H_ */ #endif /* FINIT_UTIL_H_ */
/** /**
+4 -2
View File
@@ -18,8 +18,10 @@
# change the contents any way you like, it can even be empty. # change the contents any way you like, it can even be empty.
# Check for systemd-udevd and eudev, if we find both, we opt for the latter. # Check for systemd-udevd and eudev, if we find both, we opt for the latter.
service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log /lib/systemd/systemd-udevd -- Device event daemon (udev) service nowarn cgroup.system name:udevd notify:none env:-/etc/default/udevd pid:udevd log \
service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log udevd -D -- Device event daemon (udev) [S12345789] /lib/systemd/systemd-udevd $UDEVD_ARGS -- Device event daemon (udev)
service nowarn cgroup.system name:udevd notify:none env:-/etc/default/udevd pid:udevd log \
[S12345789] udevd $UDEVD_ARGS -- Device event daemon (udev)
# Wait for udevd to start, then trigger coldplug events and module loading. # Wait for udevd to start, then trigger coldplug events and module loading.
# The last 'settle' call waits for it to finalize processing all uevents. # The last 'settle' call waits for it to finalize processing all uevents.
+3 -1
View File
@@ -11,7 +11,9 @@ EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env
skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \ skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
skel/etc/inittab skel/etc/hostname skel/etc/fstab \ skel/etc/inittab skel/etc/hostname skel/etc/fstab \
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \ skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \
skel/etc/finit.d/.empty skel/sbin/task.sh skel/bin/crasher.sh \ skel/etc/finit.d/.empty skel/etc/finit.d/available/.empty \
skel/etc/finit.d/enabled/.empty \
skel/sbin/task.sh skel/bin/crasher.sh \
skel/etc/init.d/S01-service.sh skel/etc/init.d/S02-serv.sh \ skel/etc/init.d/S01-service.sh skel/etc/init.d/S02-serv.sh \
skel/proc/.empty skel/root/.empty skel/run/.empty \ skel/proc/.empty skel/root/.empty skel/run/.empty \
skel/sbin/chrootsetup.sh skel/srv/.empty skel/sys/.empty \ skel/sbin/chrootsetup.sh skel/srv/.empty skel/sys/.empty \
+72 -23
View File
@@ -1,4 +1,10 @@
#!/bin/sh #!/bin/sh
#
# Verify pre:script and post:script runs as intended when starting,
# stopping and disabling services in various configurations and
# conditions.
#
set -eu set -eu
TEST_DIR=$(dirname "$0") TEST_DIR=$(dirname "$0")
@@ -16,6 +22,65 @@ test_teardown()
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
startit()
{
service=$1
conf=$2
pre=$3
precont=$4
say "Add stanza '$service' to $conf ..."
run "echo '$service' > $conf"
if echo "$conf" |grep -q available; then
# configlets need must be enabled
run "initctl enable serv"
fi
say 'Reload Finit'
run "initctl reload"
# Ensure service has started before checking pre condition
retry 'assert_num_children 1 serv'
# Verify pre:script has run
if [ -n "$pre" ]; then
assert_file_contains "$pre" "$precont"
# Drop pre condition indicator for next test
run "rm -f $pre"
fi
}
stopit()
{
conf=$1
post=$2
postcont=$3
if echo "$conf" |grep -q available; then
say 'Disable service & reload'
run "initctl disable serv"
run "initctl reload"
else
say 'Stop the service'
run "initctl stop serv"
fi
# Ensure service has stopped before checking for post condition
retry 'assert_num_children 0 serv'
# Verify post:script has run
if [ -n "$post" ]; then
assert_file_contains "$post" "$postcont"
# Drop post condition indicator for next test
run "rm -f $post"
fi
say "Done, drop $conf ..."
run "rm $conf"
run "initctl reload"
}
test_one() test_one()
{ {
pre=$1 pre=$1
@@ -23,31 +88,15 @@ test_one()
service=$3 service=$3
post=$4 post=$4
postcont=$5 postcont=$5
avail="$FINIT_RCSD/available/serv.conf"
say "Add service stanza '$service' to $FINIT_CONF ..." sep "Stage 1/2"
run "echo '$service' > $FINIT_CONF" startit "$service" "$FINIT_CONF" "$pre" "$precont"
stopit "$FINIT_CONF" "$post" "$postcont"
say 'Reload Finit' sep "Stage 2/2"
run "initctl reload" startit "$service" "$avail" "$pre" "$precont"
stopit "$avail" "$post" "$postcont"
retry 'assert_num_children 1 serv'
if [ -n "$pre" ]; then
assert_file_contains "$pre" "$precont"
run "rm -f $pre"
fi
say 'Stop the service'
run "initctl stop serv"
retry 'assert_num_children 0 serv'
if [ -n "$post" ]; then
assert_file_contains "$post" "$postcont"
run "rm -f $post"
fi
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+1
View File
@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
# Regression test for basic /etc/rc.local functionality # Regression test for basic /etc/rc.local functionality
# shellcheck disable=SC2317
set -eu set -eu
TEST_DIR=$(dirname "$0") TEST_DIR=$(dirname "$0")
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# Regression test for issue #351 - verify that a dirty run/task in # Regression test for issue #351 - verify that a dirty run/task in
# runlevel S is not restarted forever jus because it exits with a # runlevel S is not restarted forever just because it exits with a
# non-zero error code. # non-zero error code.
set -eu set -eu
+5 -1
View File
@@ -2,10 +2,14 @@ finitdir = $(finit_tmpfiles)
dist_finit_DATA = finit.conf dist_finit_DATA = finit.conf
tmpfilesdir = $(tmpfiles_path) tmpfilesdir = $(tmpfiles_path)
dist_tmpfiles_DATA = etc.conf legacy.conf var.conf x11.conf dist_tmpfiles_DATA = etc.conf legacy.conf var.conf
dist_tmpfiles_DATA += dnsmasq.conf frr.conf lldpd.conf openswan.conf \ dist_tmpfiles_DATA += dnsmasq.conf frr.conf lldpd.conf openswan.conf \
quagga.conf sshd.conf uuidd.conf quagga.conf sshd.conf uuidd.conf
if BUILD_TESTSERV_PLUGIN if BUILD_TESTSERV_PLUGIN
dist_tmpfiles_DATA += testserv.conf dist_tmpfiles_DATA += testserv.conf
endif endif
if BUILD_X11_COMMON_PLUGIN
dist_tmpfiles_DATA += x11.conf
endif