mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
47
Commits
4.0
..
debian-fixes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40042da8ff | ||
|
|
c251304146 | ||
|
|
c047e37a79 | ||
|
|
d2c57447f0 | ||
|
|
79e9dabc11 | ||
|
|
b04dc4d457 | ||
|
|
f86e7810be | ||
|
|
2018c82ea1 | ||
|
|
c27f3603e6 | ||
|
|
6f82b806ad | ||
|
|
cbb8935660 | ||
|
|
21ebbb942f | ||
|
|
988ecd95e3 | ||
|
|
3f3e70c686 | ||
|
|
073b040981 | ||
|
|
b1a058ccdd | ||
|
|
cbc7b8c3c7 | ||
|
|
13340e4200 | ||
|
|
0076c1f218 | ||
|
|
6fc71b7528 | ||
|
|
b42f1e99e2 | ||
|
|
afd6ad06a6 | ||
|
|
ea0bfaa2f3 | ||
|
|
5c3ec176c2 | ||
|
|
40425ee9ec | ||
|
|
424db825a3 | ||
|
|
b9cc4cd629 | ||
|
|
243b8f025b | ||
|
|
6c60b67588 | ||
|
|
910bb13711 | ||
|
|
add55cfc2a | ||
|
|
565820325b | ||
|
|
6bb4d67d92 | ||
|
|
534d50c03a | ||
|
|
9a42883a96 | ||
|
|
7c77e2c2b6 | ||
|
|
ea8c46cd30 | ||
|
|
fead3b0671 | ||
|
|
081990b49e | ||
|
|
6b89f8c6db | ||
|
|
373097040a | ||
|
|
a4ab75172c | ||
|
|
5cf9958957 | ||
|
|
b137e08e84 | ||
|
|
a1af8e8687 | ||
|
|
53c7ddcb22 | ||
|
|
3872077ff1 |
+36
-7
@@ -4,6 +4,41 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.1][UNRELEASED]
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Bug fix release.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* Change behavior on SIGUSR1 to be compatible with sysvinit and systemd.
|
||||||
|
Previously SIGUSR1 caused Finit to halt, like BusyBox init. This had
|
||||||
|
"interesting" side effects on Debian systems when coexisting with
|
||||||
|
sysvinit (upgrading/reinstalling causes scripts to `kill -USR1 1`)
|
||||||
|
* Change how `contrib/debian/install.sh` sets up a Grub boot entry for
|
||||||
|
finit. We now modify the $SUPPORTED_INITS variable in `10_linux`
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Stricter interface name validation in netlink plugin, modeled after
|
||||||
|
the kernel. Suggested by Coverity Scan
|
||||||
|
* The `contrib/*/install.sh` scripts failed to run from tarball
|
||||||
|
* Fix #170: detect loss of default route when interfaces go down. This
|
||||||
|
emulates the missing kernel netlink message to remove the condition
|
||||||
|
net/default/route to allow stopping dependent services
|
||||||
|
* Fix #171: restore automatic mount of `/dev/shm`, `/dev/pts`, `/run`
|
||||||
|
and `/tmp`, unless mounted already by `/etc/fstab`. This is what most
|
||||||
|
desktop systems expect PID 1 to do
|
||||||
|
* Fix #173: netlink plugin runs out of socket buffer space;
|
||||||
|
|
||||||
|
finit[1]: nl_callback():recv(): No buffer space available
|
||||||
|
|
||||||
|
Fixed by adding support for resync with kernel on `ENOBUFS`. See
|
||||||
|
netlink(7) for details. As a spin-off the plugin now supports any
|
||||||
|
number of interfaces and routes on a system. On resync, the following
|
||||||
|
message is now logged, as a warning:
|
||||||
|
|
||||||
|
finit[1]: nl_callback():busy system, resynchronizing with kernel.
|
||||||
|
|
||||||
|
|
||||||
[4.0][] - 2021-04-26
|
[4.0][] - 2021-04-26
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -875,7 +910,7 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/3.1...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.0...HEAD
|
||||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
[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.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||||
@@ -907,9 +942,3 @@ Major bug fix release.
|
|||||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
||||||
|
|
||||||
<!--
|
|
||||||
-- Local Variables:
|
|
||||||
-- mode: markdown
|
|
||||||
-- End:
|
|
||||||
-->
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ Some components are optional: runlevel(s), condition(s) and description,
|
|||||||
making it easy to create simple start scripts and still possible for more
|
making it easy to create simple start scripts and still possible for more
|
||||||
advanced uses as well:
|
advanced uses as well:
|
||||||
|
|
||||||
service sshd -D
|
service /usr/sbin/sshd -D
|
||||||
|
|
||||||
Dependencies are handled using [conditions](doc/conditions.md). One of
|
Dependencies are handled using [conditions](doc/conditions.md). One of
|
||||||
the most common conditions is to wait for basic networking to become
|
the most common conditions is to wait for basic networking to become
|
||||||
@@ -460,9 +460,6 @@ Commands:
|
|||||||
halt Halt system
|
halt Halt system
|
||||||
poweroff Halt and power off system
|
poweroff Halt and power off system
|
||||||
suspend Suspend system
|
suspend Suspend system
|
||||||
|
|
||||||
Bug report address: https://github.com/troglobit/finit/issues
|
|
||||||
Project homepage: https://troglobit.com/finit.html
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT(Finit, 4.0, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
AC_INIT(Finit, 4.1-rc1, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
||||||
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])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
@@ -8,7 +8,7 @@ AC_CONFIG_HEADER([config.h])
|
|||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
||||||
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile contrib/debian/grub.d/Makefile
|
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile
|
||||||
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fi
|
|||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
if [ -e alpine-release ]; then
|
if [ -e alpine-release ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
elif [ ! -e configure.ac ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = finit.d grub.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/debian
|
docsdir := @docdir@/contrib/debian
|
||||||
docs_DATA = README.md finit.conf os-release build.sh install.sh
|
docs_DATA = README.md finit.conf os-release build.sh install.sh
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ set up your system to run Finit:
|
|||||||
user@debian:~/finit$ contrib/debian/build.sh
|
user@debian:~/finit$ contrib/debian/build.sh
|
||||||
|
|
||||||
However, since `/sbin/init` already exists on your system, the script
|
However, since `/sbin/init` already exists on your system, the script
|
||||||
creates another entry in your GRUB config, in `/etc/grub.d/40_custom`,
|
creates another entry in your GRUB config by updating `$SUPPORTED_INITS`
|
||||||
where `init=/sbin/finit` is added to your kernel line. It is of course
|
in `/etc/grub.d/10_inux` and run `update-grub`. On reboot you will find
|
||||||
also possible to change the default init to Finit, if you do you can
|
a (finit) entry in the "Advanced options for Debian GNU/Linux" section.
|
||||||
remove the custom Grub entry:
|
It is of course also possible to change the default init to Finit:
|
||||||
|
|
||||||
user@debian:~/finit# cd /sbin
|
user@debian:~/finit# cd /sbin
|
||||||
user@debian:/sbin# sudo mv init oldinit
|
user@debian:/sbin# sudo mv init oldinit
|
||||||
@@ -51,7 +51,8 @@ If you want to use the X Window system, `sudo apt install elogind`
|
|||||||
(Bullseye and later). Followed by `initctl reload` (enabled by default)
|
(Bullseye and later). Followed by `initctl reload` (enabled by default)
|
||||||
and logout/login again. The elogind daemon ensures a regular non-root
|
and logout/login again. The elogind daemon ensures a regular non-root
|
||||||
user can start and interact with an X session, otherwise keyboard and
|
user can start and interact with an X session, otherwise keyboard and
|
||||||
mouse won't work.
|
mouse won't work. When you're happy, you can enable the lightdm.conf,
|
||||||
|
change the default runlevel to 3, and presto! you have a desktop again.
|
||||||
|
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/debian/finit.d
|
docsdir := @docdir@/contrib/debian/finit.d
|
||||||
d_LINKS = console-setup.conf elogind.conf getty.conf \
|
d_LINKS = acpid.conf apparmor.conf avahi-demon.conf \
|
||||||
keyboard-setup.conf modules.conf rsyslogd.conf \
|
bluetooth.conf console-setup.conf elogind.conf \
|
||||||
sshd.conf
|
getty.conf keyboard-setup.conf modules.conf \
|
||||||
|
rsyslogd.conf sshd.conf
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
docsdir := @docdir@/contrib/debian/finit.d/available
|
docsdir := @docdir@/contrib/debian/finit.d/available
|
||||||
docs_DATA = acpid.conf console-setup.conf elogind.conf getty.conf \
|
docs_DATA = acpid.conf apparmor.conf avahi-daemon.conf bluetooth.conf \
|
||||||
|
console-setup.conf elogind.conf getty.conf \
|
||||||
keyboard-setup.conf lightdm.conf modules.conf sntpd.conf \
|
keyboard-setup.conf lightdm.conf modules.conf sntpd.conf \
|
||||||
rsyslogd.conf sshd.conf syslogd.conf xdm.conf
|
rsyslogd.conf sshd.conf syslogd.conf xdm.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
task [2345] <sys/pwr/ac,pid/syslogd> halt:usr1 env:-/etc/default/anacron anacron -d -q $ANACRON_ARGS -- Anacron jobs
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
sysv [S] /etc/init.d/apparmor -- AppArmor initialization
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
service [2345] env:-/etc/default/avahi-daemon avahi-daemon -s $AVAHI_DAEMON_OPTS -- Avahi mDNS/DNS-SD Stack
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# To ignore errors like "org.freedesktop.hostname1", update the env file with
|
||||||
|
# "--noplugin=hostname", i.e. append to BLUETOOTHD_OPTS
|
||||||
|
service [2345] log:null env:-/etc/default/bluetooth /usr/libexec/bluetooth/bluetoothd -n $BLUETOOTHD_OPTS -- Bluetooth service
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
service [2345] <sys/pwr/ac,pid/syslogd> env:-/etc/default/cron cron -f $EXTRA_OPTS -- Background job processing daemon
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty [12345] /dev/tty1 linux noclear nowait
|
tty [12345] /dev/tty1 linux noclear nowait
|
||||||
tty [2345] /dev/tty2 linux noclear nowait
|
tty [2345] /dev/tty2 linux nowait
|
||||||
tty [2345] /dev/tty3 linux noclear nowait
|
tty [2345] /dev/tty3 linux nowait
|
||||||
|
tty [2345] /dev/tty4 linux nowait
|
||||||
|
tty [2345] /dev/tty5 linux nowait
|
||||||
|
tty [2345] /dev/tty6 linux nowait
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
exec tail -n +3 $0
|
|
||||||
# This file provides an easy way to add custom menu entries. Simply type the
|
|
||||||
# menu entries you want to add after this comment. Be careful not to change
|
|
||||||
# the 'exec tail' line above.
|
|
||||||
|
|
||||||
menuentry '$MENU with Finit' --class $TYPE --class gnu-linux --class gnu --class os --user {
|
|
||||||
insmod gzio
|
|
||||||
insmod part_msdos
|
|
||||||
insmod ext2
|
|
||||||
search --no-floppy --fs-uuid --set=root $BOOT
|
|
||||||
linux /vmlinuz root=UUID=$ROOT ro quiet init=/sbin/finit
|
|
||||||
initrd /initrd.img
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
docsdir := @docdir@/contrib/debian/grub.d
|
|
||||||
docs_DATA = 40_custom
|
|
||||||
EXTRA_DIST = $(docs_DATA)
|
|
||||||
@@ -11,7 +11,7 @@ fi
|
|||||||
grep -q Debian os-release 2>/dev/null
|
grep -q Debian os-release 2>/dev/null
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
elif [ ! -e configure.ac ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -23,7 +23,7 @@ echo "/sbin/finit - PID 1"
|
|||||||
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
||||||
echo "/etc/finit.conf - Finit configuration file"
|
echo "/etc/finit.conf - Finit configuration file"
|
||||||
echo "/etc/finit.d/ - Finit services"
|
echo "/etc/finit.d/ - Finit services"
|
||||||
echo "/etc/grub.d/40_custom - Add menu entry to the Grub boot loader"
|
echo "/etc/grub.d/10_linux - Add Finit to Grub's SUPPORTED_INITS"
|
||||||
echo
|
echo
|
||||||
read -p "Do you want to continue (y/N)? " yorn
|
read -p "Do you want to continue (y/N)? " yorn
|
||||||
echo
|
echo
|
||||||
@@ -38,12 +38,18 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
|||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
echo "*** Setting up a GRUB boot entry ..."
|
echo "*** Setting up a GRUB boot entry ..."
|
||||||
MENU=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/menuentry '\([^']*\).*/\1/"`
|
fn=/etc/grub.d/10_linux
|
||||||
TYPE=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/.*' --class \([a-z]*\).*/\1/"`
|
if [ -e $fn ]; then
|
||||||
BOOT=`grep set=root /boot/grub/grub.cfg |head -1 |sed 's/.* \([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
if `grep SUPPORTED_INITS $fn |head -1 |grep -q finit`; then
|
||||||
ROOT=`grep root=UUID /boot/grub/grub.cfg |head -1 |sed 's/.*UUID=\([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
echo "Already installed, done."
|
||||||
cat grub.d/40_custom | sed "s,\$BOOT,$BOOT,;s,\$ROOT,$ROOT,;s,\$TYPE,$TYPE,;s,\$MENU,$MENU," >/etc/grub.d/40_custom
|
else
|
||||||
update-grub
|
echo "Adding Finit to list of SUPPORTED_INITS ..."
|
||||||
|
sed -i 's/SUPPORTED_INITS="[^"]*/& finit:\/sbin\/finit/' $fn
|
||||||
|
update-grub
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Cannot find $fn, you'll have to set up your bootloader on your own."
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fi
|
|||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
if [ -e xbps ]; then
|
if [ -e xbps ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
elif [ ! -e configure.ac ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -26,12 +26,18 @@ Some of these are also registered in the issue tracker on GitHub.
|
|||||||
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
||||||
* Write man pages for finit and `finit.conf`, steal from the excellent
|
* Write man pages for finit and `finit.conf`, steal from the excellent
|
||||||
`pimd` man pages ...
|
`pimd` man pages ...
|
||||||
|
|
||||||
|
|
||||||
|
Initctl
|
||||||
|
-------
|
||||||
|
|
||||||
* Add support for timed shutdown in Finit, including cancelled shutdown:
|
* Add support for timed shutdown in Finit, including cancelled shutdown:
|
||||||
|
|
||||||
shutdown -h 03:35 "foobar was here"
|
shutdown -h 03:35 "foobar was here"
|
||||||
|
|
||||||
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
||||||
`initctl show --json`
|
`initctl show --json`
|
||||||
|
* Add support for `-s` to redirect all output to syslog, for scripting
|
||||||
|
|
||||||
|
|
||||||
Init
|
Init
|
||||||
|
|||||||
+17
-9
@@ -12,28 +12,36 @@ have been adopted:
|
|||||||
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
||||||
*.conf files in `/etc/finit.d/`
|
*.conf files in `/etc/finit.d/`
|
||||||
|
|
||||||
|
This also restarts the API (initctl) socket, like SysV init and systemd
|
||||||
|
does on USR1 with their FIFO/D-Bus.
|
||||||
|
|
||||||
|
|
||||||
`SIGUSR1`
|
`SIGUSR1`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
Since Finit 4.1 this signal causes Finit to restart its API (initctl)
|
||||||
processes, and unmounts all file systems. Then tells kernel to halt.
|
socket, like SysV init and systemd does on USR1 with their FIFO/D-Bus.
|
||||||
Most people these days want `SIGUSR2` though.
|
|
||||||
|
Finit <= 4.0 performed a system halt (like USR2 without power-off), but
|
||||||
|
this caused compatibility problems with systemd and sysvinit on desktop
|
||||||
|
systems. Hence, since Finit 4.1 it is no longer possible to halt a
|
||||||
|
system with a signal.
|
||||||
|
|
||||||
SysV init and systemd use this to re-open their FIFO/D-Bus.
|
|
||||||
|
|
||||||
`SIGUSR2`
|
`SIGUSR2`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Like SIGUSR1, but tell kernel to power-off the system, if ACPI or
|
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
||||||
similar exists to actually do this. If the kernel fails power-off,
|
processes, and unmounts all file systems. Then tells kernel to power
|
||||||
Finit falls back to halt.
|
off the system, if ACPI or similar exists to actually do this. If the
|
||||||
|
kernel fails power-off, Finit falls back to halt.
|
||||||
|
|
||||||
SysV init N/A, systemd dumps its internal state to log.
|
SysV init N/A, systemd dumps its internal state to log.
|
||||||
|
|
||||||
`SIGTERM`
|
`SIGTERM`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Like `SIGUSR1`, but tell kernel to reboot the system when done.
|
Like `SIGUSR2`, but tell kernel to reboot the system when done.
|
||||||
|
|
||||||
SysV init N/A, systemd rexecutes itself.
|
SysV init N/A, systemd rexecutes itself.
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@ AM_CPPFLAGS += $(lite_CFLAGS)
|
|||||||
|
|
||||||
if STATIC
|
if STATIC
|
||||||
noinst_LTLIBRARIES = libplug.la
|
noinst_LTLIBRARIES = libplug.la
|
||||||
libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c pidfile.c procps.c tty.c urandom.c usr.c
|
libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c pidfile.c procps.c sys.c tty.c urandom.c usr.c
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
libplug_la_SOURCES += alsa-utils.c
|
libplug_la_SOURCES += alsa-utils.c
|
||||||
@@ -34,7 +34,7 @@ libplug_la_SOURCES += resolvconf.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
else
|
else
|
||||||
pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la pidfile.la procps.la tty.la urandom.la usr.la
|
pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la pidfile.la procps.la sys.la tty.la urandom.la usr.la
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
pkglib_LTLIBRARIES += alsa-utils.la
|
pkglib_LTLIBRARIES += alsa-utils.la
|
||||||
|
|||||||
+12
-5
@@ -119,15 +119,16 @@ static void setup(void *arg)
|
|||||||
makedir("/var/lib/urandom",0755);
|
makedir("/var/lib/urandom",0755);
|
||||||
if (fisdir("/run")) {
|
if (fisdir("/run")) {
|
||||||
_d("System with new /run tmpfs ...");
|
_d("System with new /run tmpfs ...");
|
||||||
makedir("/run/lock", 1777);
|
if (!fisdir("/run/lock"))
|
||||||
|
makedir("/run/lock", 1777);
|
||||||
symlink("/run/lock", "/var/lock");
|
symlink("/run/lock", "/var/lock");
|
||||||
symlink("/dev/shm", "/run/shm");
|
symlink("/dev/shm", "/run/shm");
|
||||||
|
|
||||||
/* compat only, should really be set up by OS/dist */
|
/* compat only, should really be set up by OS/dist */
|
||||||
symlink("/run", "/var/run");
|
symlink("/run", "/var/run");
|
||||||
} else {
|
} else {
|
||||||
makedir("/var/lock", 1777);
|
makedir("/var/lock", 1777);
|
||||||
makedir("/var/run", 0755);
|
makedir("/var/run", 0755);
|
||||||
}
|
}
|
||||||
makedir("/var/log", 0755);
|
makedir("/var/log", 0755);
|
||||||
makedir("/var/mail", 0755);
|
makedir("/var/mail", 0755);
|
||||||
@@ -183,6 +184,12 @@ static void setup(void *arg)
|
|||||||
/* Void Linux has a uuidd that runs as uuid:uuid and needs /run/uuid */
|
/* Void Linux has a uuidd that runs as uuid:uuid and needs /run/uuid */
|
||||||
mksubsys("/var/run/uuidd", 0755, "uuidd", "uuidd");
|
mksubsys("/var/run/uuidd", 0755, "uuidd", "uuidd");
|
||||||
|
|
||||||
|
/* Debian has /run/sudo, ensure correct perms and SELinux label */
|
||||||
|
mksubsys("/var/run/sudo", 0711, "root", "root");
|
||||||
|
mksubsys("/var/run/sudo/ts", 0700, "root", "root");
|
||||||
|
if (whichp("restorecon"))
|
||||||
|
run("restorecon /var/run/sudo /var/run/sudo/ts");
|
||||||
|
|
||||||
umask(prev);
|
umask(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ static void setup(void *arg)
|
|||||||
remove("/var/run/dbus/pid");
|
remove("/var/run/dbus/pid");
|
||||||
|
|
||||||
/* Register service with Finit */
|
/* Register service with Finit */
|
||||||
snprintf(line, sizeof(line), "[S12345789] @%s:%s %s %s -- %s",
|
snprintf(line, sizeof(line), "[S12345789] cgroup.system @%s:%s %s %s -- %s",
|
||||||
DAEMONUSER, DAEMONUSER, cmd, ARGS, DESC);
|
DAEMONUSER, DAEMONUSER, cmd, ARGS, DESC);
|
||||||
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
||||||
_pe("Failed registering %s", DAEMON);
|
_pe("Failed registering %s", DAEMON);
|
||||||
|
|||||||
+3
-3
@@ -48,17 +48,17 @@ static void setup(void *arg)
|
|||||||
path = which("/lib/systemd/systemd-udevd");
|
path = which("/lib/systemd/systemd-udevd");
|
||||||
if (path) {
|
if (path) {
|
||||||
/* Register udevd as a monitored service */
|
/* Register udevd as a monitored service */
|
||||||
snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd name:udevd log %s "
|
snprintf(cmd, sizeof(cmd), "[S12345789] cgroup.system pid:udevd name:udevd log %s "
|
||||||
"-- Device event managing daemon", path);
|
"-- Device event managing daemon", path);
|
||||||
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
|
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
|
||||||
_pe("Failed registering %s", path);
|
_pe("Failed registering %s", path);
|
||||||
} else {
|
} else {
|
||||||
snprintf(cmd, sizeof(cmd), ":1 [S] <pid/udevd> log "
|
snprintf(cmd, sizeof(cmd), "cgroup.init :1 [S] <pid/udevd> log "
|
||||||
"udevadm trigger -c add -t devices "
|
"udevadm trigger -c add -t devices "
|
||||||
"-- Requesting device events");
|
"-- Requesting device events");
|
||||||
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), ":2 [S] <pid/udevd> log "
|
snprintf(cmd, sizeof(cmd), "cgroup.init :2 [S] <pid/udevd> log "
|
||||||
"udevadm trigger -c add -t subsystems "
|
"udevadm trigger -c add -t subsystems "
|
||||||
"-- Requesting subsystem events");
|
"-- Requesting subsystem events");
|
||||||
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||||
#endif
|
#endif
|
||||||
#define SERVICE_LINE \
|
#define SERVICE_LINE \
|
||||||
":%d name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s"
|
"cgroup.init :%d name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s"
|
||||||
|
|
||||||
static void load(void *arg)
|
static void load(void *arg)
|
||||||
{
|
{
|
||||||
@@ -71,8 +71,7 @@ static void load(void *arg)
|
|||||||
|
|
||||||
mod = strtok_r(mod, " ", &args);
|
mod = strtok_r(mod, " ", &args);
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), SERVICE_LINE,
|
snprintf(cmd, sizeof(cmd), SERVICE_LINE, index, mod, mod, args, mod);
|
||||||
index, mod, mod, args, mod);
|
|
||||||
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
|||||||
+227
-42
@@ -30,31 +30,35 @@
|
|||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "service.h"
|
||||||
|
|
||||||
static int nlmsg_validate(struct nlmsghdr *nh, size_t len)
|
#define NL_BUFSZ 4096
|
||||||
{
|
|
||||||
if (!NLMSG_OK(nh, len))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (nh->nlmsg_type == NLMSG_DONE) {
|
struct nl_request {
|
||||||
_d("Done with netlink messages.");
|
struct nlmsghdr nh;
|
||||||
return 1;
|
union {
|
||||||
}
|
struct rtmsg rtm;
|
||||||
|
struct ifinfomsg ifi;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if (nh->nlmsg_type == NLMSG_ERROR) {
|
static int nl_defidx;
|
||||||
_d("Netlink reports error.");
|
static int nl_ifdown;
|
||||||
return 1;
|
static char *nl_buf;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
|
char daddr[INET_ADDRSTRLEN];
|
||||||
|
char gaddr[INET_ADDRSTRLEN];
|
||||||
|
struct in_addr ind, ing;
|
||||||
struct rtmsg *r;
|
struct rtmsg *r;
|
||||||
struct rtattr *a;
|
struct rtattr *a;
|
||||||
|
int plen = 0;
|
||||||
|
int dst = 0;
|
||||||
|
int idx = 0;
|
||||||
|
int gw = 0;
|
||||||
int la;
|
int la;
|
||||||
int gw = 0, dst = 0, mask = 0, idx = 0;
|
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
||||||
_e("Packet too small or truncated!");
|
_e("Packet too small or truncated!");
|
||||||
@@ -80,8 +84,8 @@ static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
|
|
||||||
case RTA_DST:
|
case RTA_DST:
|
||||||
dst = *((int *)data);
|
dst = *((int *)data);
|
||||||
mask = r->rtm_dst_len;
|
plen = r->rtm_dst_len;
|
||||||
//_d("MASK: 0x%04x", mask);
|
//_d("Prefix LEN: 0x%04x", plen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTA_OIF:
|
case RTA_OIF:
|
||||||
@@ -93,11 +97,20 @@ static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
a = RTA_NEXT(a, la);
|
a = RTA_NEXT(a, la);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!dst && !mask) && (gw || idx)) {
|
ind.s_addr = dst;
|
||||||
if (nlmsg->nlmsg_type == RTM_DELROUTE)
|
ing.s_addr = gw;
|
||||||
|
inet_ntop(AF_INET, &ind, daddr, sizeof(daddr));
|
||||||
|
inet_ntop(AF_INET, &ing, gaddr, sizeof(gaddr));
|
||||||
|
_d("Got gw %s dst/len %s/%d ifindex %d", gaddr, daddr, plen, idx);
|
||||||
|
|
||||||
|
if ((!dst && !plen) && (gw || idx)) {
|
||||||
|
if (nlmsg->nlmsg_type == RTM_DELROUTE) {
|
||||||
cond_clear("net/route/default");
|
cond_clear("net/route/default");
|
||||||
else
|
nl_defidx = 0;
|
||||||
|
} else {
|
||||||
cond_set("net/route/default");
|
cond_set("net/route/default");
|
||||||
|
nl_defidx = idx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,14 +130,14 @@ static int validate_ifname(const char *ifname)
|
|||||||
if (!ifname || !ifname[0])
|
if (!ifname || !ifname[0])
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (strlen(ifname) >= IFNAMSIZ)
|
if (strnlen(ifname, IFNAMSIZ) == IFNAMSIZ)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (strstr(ifname, ".."))
|
if (!strcmp(ifname, ".") || !strcmp(ifname, ".."))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
while (*ifname) {
|
while (*ifname) {
|
||||||
if (*ifname == '/' || isspace(*ifname))
|
if (*ifname == '/' || *ifname == ':' || isspace(*ifname))
|
||||||
return 1;
|
return 1;
|
||||||
ifname++;
|
ifname++;
|
||||||
}
|
}
|
||||||
@@ -132,12 +145,25 @@ static int validate_ifname(const char *ifname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if this interface was associated with the default route
|
||||||
|
* previously, or if it's been removed. If so, trigger a recheck
|
||||||
|
* of the system default route.
|
||||||
|
*/
|
||||||
|
static void nl_check_default(char *ifname)
|
||||||
|
{
|
||||||
|
int idx = (int)if_nametoindex(ifname);
|
||||||
|
|
||||||
|
if ((nl_defidx > 0 && nl_defidx == idx) || (idx == 0 && errno == ENODEV))
|
||||||
|
nl_ifdown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
int la;
|
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
struct rtattr *a;
|
|
||||||
struct ifinfomsg *i;
|
struct ifinfomsg *i;
|
||||||
|
struct rtattr *a;
|
||||||
|
int la;
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
||||||
_e("Packet too small or truncated!");
|
_e("Packet too small or truncated!");
|
||||||
@@ -172,6 +198,8 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
net_cond_set(ifname, "exist", 1);
|
net_cond_set(ifname, "exist", 1);
|
||||||
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
||||||
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
||||||
|
if (!(i->ifi_flags & IFF_UP) || !(i->ifi_flags & IFF_RUNNING))
|
||||||
|
nl_check_default(ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
@@ -180,6 +208,7 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
net_cond_set(ifname, "exist", 0);
|
net_cond_set(ifname, "exist", 0);
|
||||||
net_cond_set(ifname, "up", 0);
|
net_cond_set(ifname, "up", 0);
|
||||||
net_cond_set(ifname, "running", 0);
|
net_cond_set(ifname, "running", 0);
|
||||||
|
nl_check_default(ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR:
|
||||||
@@ -197,26 +226,175 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl_callback(void *arg, int sd, int events)
|
static int nl_parse(int sd)
|
||||||
{
|
{
|
||||||
static char buf[4096];
|
while (1) {
|
||||||
struct nlmsghdr *nh;
|
struct nlmsghdr *nh;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
while ((len = recv(sd, nl_buf, NL_BUFSZ, 0)) < 0) {
|
||||||
len = recv(sd, buf, sizeof(buf), 0);
|
switch (errno) {
|
||||||
if (len < 0) {
|
case EAGAIN: /* Nothing more right now. */
|
||||||
if (errno != EINTR) /* Signal */
|
return 0;
|
||||||
_pe("recv()");
|
|
||||||
|
case EINTR: /* Signal */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case ENOBUFS: /* netlink(7) */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_pe("recv()");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_d("recv %lld bytes", len);
|
||||||
|
|
||||||
|
for (nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
||||||
|
struct nlmsgerr *nle;
|
||||||
|
|
||||||
|
switch (nh->nlmsg_type) {
|
||||||
|
case NLMSG_DONE:
|
||||||
|
_d("Done with netlink messages.");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case NLMSG_ERROR:
|
||||||
|
_d("Kernel netlink comm. error.");
|
||||||
|
nle = NLMSG_DATA(nh);
|
||||||
|
if (nle) {
|
||||||
|
errno = -nle->error;
|
||||||
|
_pe("Kernel netlink error %d", errno);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case RTM_NEWROUTE:
|
||||||
|
case RTM_DELROUTE:
|
||||||
|
_d("Netlink route ...");
|
||||||
|
nl_route(nh, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_NEWLINK:
|
||||||
|
case RTM_DELLINK:
|
||||||
|
_d("Netlink link ...");
|
||||||
|
nl_link(nh, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_w("unhandled netlink message, type %d", nh->nlmsg_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl_request(int sd, unsigned int seq, int type)
|
||||||
|
{
|
||||||
|
struct nl_request *nlr = (struct nl_request *)nl_buf;
|
||||||
|
|
||||||
|
memset(nlr, 0, sizeof(struct nl_request));
|
||||||
|
nlr->nh.nlmsg_type = type;
|
||||||
|
nlr->nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||||
|
nlr->nh.nlmsg_seq = seq;
|
||||||
|
nlr->nh.nlmsg_pid = 1;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RTM_GETROUTE:
|
||||||
|
_d("RTM_GETROUTE");
|
||||||
|
nlr->rtm.rtm_family = AF_INET;
|
||||||
|
nlr->rtm.rtm_table = RT_TABLE_MAIN;
|
||||||
|
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_GETLINK:
|
||||||
|
_d("RTM_GETLINK");
|
||||||
|
nlr->ifi.ifi_family = AF_UNSPEC;
|
||||||
|
nlr->ifi.ifi_change = 0xFFFFFFFF;
|
||||||
|
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_w("Cannot resync, unhandled message type %d", type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send(sd, nlr, nlr->nh.nlmsg_len, 0) < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return nl_parse(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_resync_routes(int sd, unsigned int seq)
|
||||||
|
{
|
||||||
|
if (nl_request(sd, seq, RTM_GETROUTE))
|
||||||
|
_pe("Failed netlink route request");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_resync_ifaces(int sd, unsigned int seq)
|
||||||
|
{
|
||||||
|
if (nl_request(sd, seq, RTM_GETLINK))
|
||||||
|
_pe("Failed netlink link request");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We've potentially lost netlink events, let's resync with kernel.
|
||||||
|
*/
|
||||||
|
static void nl_resync(int all)
|
||||||
|
{
|
||||||
|
unsigned int seq = 0;
|
||||||
|
int sd;
|
||||||
|
|
||||||
|
sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
|
if (sd < 0) {
|
||||||
|
_pe("netlink socket");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nh = (struct nlmsghdr *)buf; !nlmsg_validate(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
if (all) {
|
||||||
//_d("Well formed netlink message received. type %d ...", nh->nlmsg_type);
|
_d("============================ RESYNC =================================");
|
||||||
if (nh->nlmsg_type == RTM_NEWROUTE || nh->nlmsg_type == RTM_DELROUTE)
|
/* this doesn't update condtions, and thus does not stop services */
|
||||||
nl_route(nh, len);
|
cond_deassert("net/");
|
||||||
else
|
|
||||||
nl_link(nh, len);
|
nl_resync_ifaces(sd, seq++);
|
||||||
|
nl_resync_routes(sd, seq++);
|
||||||
|
|
||||||
|
/* delayed update after we've corrected things */
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
_d("=========================== RESYNCED ================================");
|
||||||
|
} else
|
||||||
|
nl_resync_routes(sd, seq++);
|
||||||
|
|
||||||
|
close(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_callback(void *arg, int sd, int events)
|
||||||
|
{
|
||||||
|
if (nl_parse(sd) < 0) {
|
||||||
|
if (errno == ENOBUFS) { /* netlink(7) */
|
||||||
|
_w("busy system, resynchronizing with kernel.");
|
||||||
|
nl_resync(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linux doesn't send route changes when interfaces go down, so
|
||||||
|
* we need to check ourselves, e.g. for loss of default route.
|
||||||
|
*/
|
||||||
|
if (nl_ifdown) {
|
||||||
|
_d("interface down, checking default route.");
|
||||||
|
if (nl_defidx > 0) {
|
||||||
|
nl_defidx = 0;
|
||||||
|
nl_resync(0);
|
||||||
|
if (nl_defidx <= 0) {
|
||||||
|
cond_clear("net/route/default");
|
||||||
|
nl_defidx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_ifdown = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +414,8 @@ static plugin_t plugin = {
|
|||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
int sd;
|
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
|
int sd;
|
||||||
|
|
||||||
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
@@ -247,7 +425,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.nl_family = AF_NETLINK;
|
sa.nl_family = AF_NETLINK;
|
||||||
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK; // | RTMGRP_NOTIFY | RTMGRP_IPV4_IFADDR;
|
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK;
|
||||||
sa.nl_pid = getpid();
|
sa.nl_pid = getpid();
|
||||||
|
|
||||||
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||||
@@ -256,6 +434,13 @@ PLUGIN_INIT(plugin_init)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nl_buf = malloc(NL_BUFSZ);
|
||||||
|
if (!nl_buf) {
|
||||||
|
_pe("malloc()");
|
||||||
|
close(sd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
plugin.io.fd = sd;
|
plugin.io.fd = sd;
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+197
@@ -0,0 +1,197 @@
|
|||||||
|
/* System condtion event monitor for the Finit condition engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 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
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <paths.h>
|
||||||
|
|
||||||
|
#include "finit.h"
|
||||||
|
#include "cond.h"
|
||||||
|
#include "pid.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "iwatch.h"
|
||||||
|
|
||||||
|
static struct iwatch iw_sys;
|
||||||
|
|
||||||
|
|
||||||
|
static int sys_add_path(struct iwatch *iw, char *path)
|
||||||
|
{
|
||||||
|
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_update_conds(char *dir, char *name, uint32_t mask)
|
||||||
|
{
|
||||||
|
char fn[PATH_MAX];
|
||||||
|
char *cond;
|
||||||
|
|
||||||
|
paste(fn, sizeof(fn), dir, name);
|
||||||
|
cond = strstr(fn, COND_BASE);
|
||||||
|
if (!cond)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond += strlen(COND_BASE) + 1;
|
||||||
|
_d("cond: %s set: %d", cond, mask & IN_CREATE ? 1 : 0);
|
||||||
|
cond_update(cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* synthesize events in case of new run dirs */
|
||||||
|
static void sys_scandir(struct iwatch *iw, char *dir, int len)
|
||||||
|
{
|
||||||
|
glob_t gl;
|
||||||
|
size_t i;
|
||||||
|
char path[len + 6];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/*", dir);
|
||||||
|
rc = glob(path, GLOB_NOSORT, NULL, &gl);
|
||||||
|
if (rc && rc != GLOB_NOMATCH)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
|
_d("scan found %s", gl.gl_pathv[i]);
|
||||||
|
sys_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
||||||
|
}
|
||||||
|
globfree(&gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create/remove sub-directory in monitored directory
|
||||||
|
*/
|
||||||
|
static void sys_handle_dir(struct iwatch *iw, char *dir, char *name, int mask)
|
||||||
|
{
|
||||||
|
char path[strlen(dir) + strlen(name) + 2];
|
||||||
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
paste(path, sizeof(path), dir, name);
|
||||||
|
_d("path: %s", path);
|
||||||
|
|
||||||
|
iwp = iwatch_find_by_path(iw, path);
|
||||||
|
|
||||||
|
if (mask & IN_CREATE) {
|
||||||
|
if (!iwp) {
|
||||||
|
if (!sys_add_path(iw, path))
|
||||||
|
sys_scandir(iw, path, sizeof(path));
|
||||||
|
}
|
||||||
|
} else if (mask & IN_DELETE) {
|
||||||
|
if (iwp)
|
||||||
|
iwatch_del(&iw_sys, iwp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_callback(void *arg, int fd, int events)
|
||||||
|
{
|
||||||
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
|
struct inotify_event *ev;
|
||||||
|
ssize_t sz;
|
||||||
|
size_t off;
|
||||||
|
|
||||||
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
|
if (sz <= 0) {
|
||||||
|
_pe("invalid inotify event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
|
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
||||||
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
if (off + sizeof(*ev) > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_d("name %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
|
if (!ev->mask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Find base path for this event */
|
||||||
|
iwp = iwatch_find_by_wd(&iw_sys, ev->wd);
|
||||||
|
if (!iwp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ev->mask & IN_ISDIR) {
|
||||||
|
sys_handle_dir(&iw_sys, iwp->path, ev->name, ev->mask);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->mask & (IN_CREATE | IN_DELETE))
|
||||||
|
sys_update_conds(iwp->path, ev->name, ev->mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_init(void *arg)
|
||||||
|
{
|
||||||
|
char sysdir[MAX_ARG_LEN];
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
if (mkpath(pid_runpath(_PATH_CONDSYS, sysdir, sizeof(sysdir)), 0755) && errno != EEXIST) {
|
||||||
|
_pe("Failed creating %s condition directory, %s", COND_SYS, _PATH_CONDSYS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = realpath(_PATH_CONDSYS, NULL);
|
||||||
|
if (!path) {
|
||||||
|
_pe("Cannot figure out real path to %s, aborting", _PATH_CONDSYS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iwatch_add(&iw_sys, path, IN_ONLYDIR))
|
||||||
|
iwatch_exit(&iw_sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = __FILE__,
|
||||||
|
.hook[HOOK_BASEFS_UP] = { .cb = sys_init },
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_INIT(plugin_init)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = iwatch_init(&iw_sys);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plugin.io.fd = fd;
|
||||||
|
plugin.io.cb = sys_callback;
|
||||||
|
plugin.io.flags = PLUGIN_IO_READ;
|
||||||
|
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_EXIT(plugin_exit)
|
||||||
|
{
|
||||||
|
iwatch_exit(&iw_sys);
|
||||||
|
plugin_unregister(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
.deps/*
|
.deps/*
|
||||||
finit
|
finit
|
||||||
initctl
|
initctl
|
||||||
|
keventd
|
||||||
logit
|
logit
|
||||||
reboot
|
reboot
|
||||||
sulogin
|
sulogin
|
||||||
|
|||||||
+9
-5
@@ -8,18 +8,22 @@ AM_LDFLAGS = -export-dynamic
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sbin_PROGRAMS = finit initctl
|
sbin_PROGRAMS = finit initctl
|
||||||
pkglibexec_PROGRAMS = logit sulogin
|
pkglibexec_PROGRAMS = keventd logit sulogin
|
||||||
|
if WATCHDOGD
|
||||||
|
pkglibexec_PROGRAMS += watchdogd
|
||||||
|
endif
|
||||||
|
|
||||||
finit_pkglibdir = $(pkglibdir)
|
finit_pkglibdir = $(pkglibdir)
|
||||||
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
||||||
|
|
||||||
|
keventd_SOURCES = keventd.c iwatch.c iwatch.h util.c util.h
|
||||||
|
keventd_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
|
keventd_LDADD = $(lite_LIBS)
|
||||||
|
|
||||||
sulogin_SOURCES = sulogin.c
|
sulogin_SOURCES = sulogin.c
|
||||||
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
sulogin_LDADD = -lcrypt
|
sulogin_LDADD = -lcrypt
|
||||||
|
|
||||||
if WATCHDOGD
|
|
||||||
pkglibexec_PROGRAMS += watchdogd
|
|
||||||
endif
|
|
||||||
|
|
||||||
logit_SOURCES = logit.c logrotate.c
|
logit_SOURCES = logit.c logrotate.c
|
||||||
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
logit_CFLAGS += $(lite_CFLAGS)
|
logit_CFLAGS += $(lite_CFLAGS)
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ int cgroup_service(char *name, int pid, struct cgroup *cg)
|
|||||||
if (!strcmp(cg->name, "root"))
|
if (!strcmp(cg->name, "root"))
|
||||||
return fnwrite(str("%d", pid), FINIT_CGPATH "/cgroup.procs");
|
return fnwrite(str("%d", pid), FINIT_CGPATH "/cgroup.procs");
|
||||||
|
|
||||||
|
if (!strcmp(cg->name, "init"))
|
||||||
|
return fnwrite(str("%d", pid), FINIT_CGPATH "/init/cgroup.procs");
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s", cg->name);
|
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s", cg->name);
|
||||||
if (fisdir(path))
|
if (fisdir(path))
|
||||||
group = cg->name;
|
group = cg->name;
|
||||||
|
|||||||
+52
-12
@@ -163,7 +163,7 @@ int cond_set_path(const char *path, enum cond_state next)
|
|||||||
return next != prev;
|
return next != prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should only be used by cond_set*(), cond_clear(), and usr plugin! */
|
/* Should only be used by cond_set*(), cond_clear(), and usr/sys plugins! */
|
||||||
void cond_update(const char *name)
|
void cond_update(const char *name)
|
||||||
{
|
{
|
||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
@@ -178,13 +178,22 @@ void cond_update(const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_set(const char *name)
|
int cond_set_noupdate(const char *name)
|
||||||
{
|
{
|
||||||
_d("%s", name);
|
_d("%s", name);
|
||||||
if (string_compare(name, "nop"))
|
if (string_compare(name, "nop"))
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
if (!cond_set_path(cond_path(name), COND_ON))
|
if (!cond_set_path(cond_path(name), COND_ON))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cond_set(const char *name)
|
||||||
|
{
|
||||||
|
_d("%s", name);
|
||||||
|
if (cond_set_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cond_update(name);
|
cond_update(name);
|
||||||
@@ -208,13 +217,22 @@ void cond_set_oneshot(const char *name)
|
|||||||
cond_update(name);
|
cond_update(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_clear(const char *name)
|
int cond_clear_noupdate(const char *name)
|
||||||
{
|
{
|
||||||
_d("%s", name);
|
_d("%s", name);
|
||||||
if (string_compare(name, "nop"))
|
if (string_compare(name, "nop"))
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
if (!cond_set_path(cond_path(name), COND_OFF))
|
if (!cond_set_path(cond_path(name), COND_OFF))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cond_clear(const char *name)
|
||||||
|
{
|
||||||
|
_d("%s", name);
|
||||||
|
if (cond_clear_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cond_update(name);
|
cond_update(name);
|
||||||
@@ -227,7 +245,7 @@ void cond_reload(void)
|
|||||||
cond_bump_reconf();
|
cond_bump_reconf();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
static int do_assert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw, int set)
|
||||||
{
|
{
|
||||||
char *nm;
|
char *nm;
|
||||||
|
|
||||||
@@ -239,25 +257,47 @@ static int reassert(const char *fpath, const struct stat *sb, int tflg, struct F
|
|||||||
|
|
||||||
nm = strstr((char *)fpath, COND_BASE);
|
nm = strstr((char *)fpath, COND_BASE);
|
||||||
if (!nm) {
|
if (!nm) {
|
||||||
_e("Incorrect condtion path %s, cannot reassert", fpath);
|
_e("Incorrect condtion path %s, cannot %sassert", fpath, set ? "re" : "de");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nm += strlen(COND_BASE);
|
nm += strlen(COND_BASE);
|
||||||
_d("Reasserting %s => %s", fpath, nm);
|
_d("%sasserting %s => %s", set ? "Re" : "De", fpath, nm);
|
||||||
cond_set(nm);
|
if (set)
|
||||||
|
cond_set(nm);
|
||||||
|
else
|
||||||
|
cond_clear_noupdate(nm); /* important, see netlink plugin! */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
||||||
|
{
|
||||||
|
return do_assert(fpath, sb, tflg, ftw, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int deassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
||||||
|
{
|
||||||
|
return do_assert(fpath, sb, tflg, ftw, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used only by netlink plugin atm.
|
* Used only by netlink plugin atm.
|
||||||
* type: is a one of pid/, net/, etc.
|
* type: is a one of pid/, net/, etc.
|
||||||
*/
|
*/
|
||||||
void cond_reassert(const char *type)
|
void cond_reassert(const char *pat)
|
||||||
{
|
{
|
||||||
_d("%s", type);
|
_d("%s", pat);
|
||||||
nftw(cond_path(type), reassert, 20, FTW_DEPTH);
|
nftw(cond_path(pat), reassert, 20, FTW_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used only by netlink plugin atm.
|
||||||
|
*/
|
||||||
|
void cond_deassert(const char *pat)
|
||||||
|
{
|
||||||
|
_d("%s", pat);
|
||||||
|
nftw(cond_path(pat), deassert, 20, FTW_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_init(void)
|
void cond_init(void)
|
||||||
|
|||||||
+10
-2
@@ -5,12 +5,14 @@
|
|||||||
#include <svc.h>
|
#include <svc.h>
|
||||||
|
|
||||||
#define COND_BASE "finit/cond"
|
#define COND_BASE "finit/cond"
|
||||||
#define COND_USR "usr/"
|
|
||||||
#define COND_PID "pid/"
|
#define COND_PID "pid/"
|
||||||
|
#define COND_SYS "sys/"
|
||||||
|
#define COND_USR "usr/"
|
||||||
|
|
||||||
#define _PATH_COND _PATH_VARRUN COND_BASE "/"
|
#define _PATH_COND _PATH_VARRUN COND_BASE "/"
|
||||||
#define _PATH_CONDUSR _PATH_COND COND_USR
|
|
||||||
#define _PATH_CONDPID _PATH_COND COND_PID
|
#define _PATH_CONDPID _PATH_COND COND_PID
|
||||||
|
#define _PATH_CONDSYS _PATH_COND COND_SYS
|
||||||
|
#define _PATH_CONDUSR _PATH_COND COND_USR
|
||||||
#define _PATH_RECONF _PATH_COND "reconf"
|
#define _PATH_RECONF _PATH_COND "reconf"
|
||||||
|
|
||||||
typedef enum cond_state {
|
typedef enum cond_state {
|
||||||
@@ -34,7 +36,13 @@ void cond_set (const char *name);
|
|||||||
void cond_set_oneshot (const char *name);
|
void cond_set_oneshot (const char *name);
|
||||||
void cond_clear (const char *name);
|
void cond_clear (const char *name);
|
||||||
void cond_reload (void);
|
void cond_reload (void);
|
||||||
|
|
||||||
|
int cond_set_noupdate (const char *name);
|
||||||
|
int cond_clear_noupdate(const char *name);
|
||||||
|
|
||||||
void cond_reassert (const char *pat);
|
void cond_reassert (const char *pat);
|
||||||
|
void cond_deassert (const char *pat);
|
||||||
|
|
||||||
void cond_init (void);
|
void cond_init (void);
|
||||||
|
|
||||||
#endif /* FINIT_COND_H_ */
|
#endif /* FINIT_COND_H_ */
|
||||||
|
|||||||
+73
-1
@@ -186,6 +186,69 @@ static void fs_remount_root(int fsckerr)
|
|||||||
}
|
}
|
||||||
#endif /* SYSROOT */
|
#endif /* SYSROOT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opinionated file system setup. Checks for critical mount points and
|
||||||
|
* mounts them as most users expect. All file systems are checked with
|
||||||
|
* /proc/mounts before mounting.
|
||||||
|
*
|
||||||
|
* Embedded systems, and other people who want full control, can set up
|
||||||
|
* their system with /etc/fstab, which is handled before this function
|
||||||
|
* is called. For systems like Debian/Ubuntu, who only have / and swap
|
||||||
|
* in their /etc/fstab, this function does all the magic necessary.
|
||||||
|
*/
|
||||||
|
static void fs_finalize(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Some systems rely on us to both create /dev/shm and, to mount
|
||||||
|
* a tmpfs there. Any system with dbus needs shared memory, so
|
||||||
|
* mount it, unless its already mounted, but not if listed in
|
||||||
|
* the /etc/fstab file already.
|
||||||
|
*/
|
||||||
|
if (!fismnt("/dev/shm")) {
|
||||||
|
makedir("/dev/shm", 0777);
|
||||||
|
mount("shm", "/dev/shm", "tmpfs", 0, "mode=0777");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modern systems use /dev/pts */
|
||||||
|
if (!fismnt("/dev/pts")) {
|
||||||
|
char opts[32];
|
||||||
|
int mode;
|
||||||
|
int gid;
|
||||||
|
|
||||||
|
gid = getgroup("tty");
|
||||||
|
if (gid == -1)
|
||||||
|
gid = 0;
|
||||||
|
|
||||||
|
/* 0600 is default on Debian, use 0620 to get mesg y by default */
|
||||||
|
mode = 0620;
|
||||||
|
snprintf(opts, sizeof(opts), "gid=%d,mode=%d,ptmxmode=0666", gid, mode);
|
||||||
|
|
||||||
|
makedir("/dev/pts", 0755);
|
||||||
|
mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modern systems use tmpfs for /run. Fallback to /var/run if
|
||||||
|
* /run doesn't exist is handled by the bootmisc plugin. It
|
||||||
|
* also sets up compat symlinks.
|
||||||
|
*
|
||||||
|
* The unconditional mount of /run/lock is for DoS prevention.
|
||||||
|
* To override any of this behavior, add entries to /etc/fstab
|
||||||
|
* for /run (and optionally /run/lock).
|
||||||
|
*/
|
||||||
|
if (fisdir("/run") && !fismnt("/run")) {
|
||||||
|
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 */
|
||||||
|
makedir("/run/lock", 1777);
|
||||||
|
mount("tmpfs", "/run/lock", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, "mode=0777,size=5252880");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modern systems use tmpfs for /tmp */
|
||||||
|
if (!fismnt("/tmp"))
|
||||||
|
mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV, "mode=1777");
|
||||||
|
}
|
||||||
|
|
||||||
static void fs_mount(void)
|
static void fs_mount(void)
|
||||||
{
|
{
|
||||||
if (!rescue)
|
if (!rescue)
|
||||||
@@ -201,6 +264,9 @@ static void fs_mount(void)
|
|||||||
plugin_run_hooks(HOOK_MOUNT_POST);
|
plugin_run_hooks(HOOK_MOUNT_POST);
|
||||||
|
|
||||||
run("swapon -ea");
|
run("swapon -ea");
|
||||||
|
|
||||||
|
_d("Finalize, ensure common file systems are available ...");
|
||||||
|
fs_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -524,10 +590,16 @@ int main(int argc, char *argv[])
|
|||||||
* Start built-in watchdogd as soon as possible, if enabled
|
* Start built-in watchdogd as soon as possible, if enabled
|
||||||
*/
|
*/
|
||||||
if (whichp(FINIT_LIBPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) {
|
if (whichp(FINIT_LIBPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) {
|
||||||
service_register(SVC_TYPE_SERVICE, "[123456789] name:watchdog :finit " FINIT_LIBPATH_ "/watchdogd -- Finit watchdog daemon", global_rlimit, NULL);
|
service_register(SVC_TYPE_SERVICE, "[123456789] cgroup.init name:watchdog :finit " FINIT_LIBPATH_ "/watchdogd -- Finit watchdog daemon", global_rlimit, NULL);
|
||||||
wdog = svc_find_by_nameid("watchdog", "finit");
|
wdog = svc_find_by_nameid("watchdog", "finit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start kernel event daemon as soon as possible, if enabled
|
||||||
|
*/
|
||||||
|
if (whichp(FINIT_LIBPATH_ "/keventd"))
|
||||||
|
service_register(SVC_TYPE_SERVICE, "[123456789] cgroup.init " FINIT_LIBPATH_ "/keventd -- Finit kernel event daemon", global_rlimit, NULL);
|
||||||
|
|
||||||
/* Base FS up, enable standard SysV init signals */
|
/* Base FS up, enable standard SysV init signals */
|
||||||
sig_setup(&loop);
|
sig_setup(&loop);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -345,7 +345,7 @@ static int do_cond_act(char *arg, int creat)
|
|||||||
if (symlink(_PATH_RECONF, oneshot) && errno != EEXIST)
|
if (symlink(_PATH_RECONF, oneshot) && errno != EEXIST)
|
||||||
err(1, "Failed asserting condition <%s>", &oneshot[off]);
|
err(1, "Failed asserting condition <%s>", &oneshot[off]);
|
||||||
} else {
|
} else {
|
||||||
if (erase(oneshot))
|
if (erase(oneshot) && errno != ENOENT)
|
||||||
err(1, "Failed deasserting condition <%s>", &oneshot[off]);
|
err(1, "Failed deasserting condition <%s>", &oneshot[off]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+278
@@ -0,0 +1,278 @@
|
|||||||
|
/* Listens to kernel events like AC power status and manages sys/ conditions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 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
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
#include "lite/lite.h"
|
||||||
|
|
||||||
|
#include "cond.h"
|
||||||
|
#include "pid.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define _PATH_SYSFS_PWR "/sys/class/power_supply"
|
||||||
|
|
||||||
|
static int num_ac_online;
|
||||||
|
static int num_ac;
|
||||||
|
|
||||||
|
int debug; /* debug in other modules as well */
|
||||||
|
|
||||||
|
void logit(int prio, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (!debug)
|
||||||
|
vsyslog(prio, fmt, ap);
|
||||||
|
else {
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
#define panic(fmt, args...) { logit(LOG_CRIT, fmt ":%s", ##args, strerror(errno)); exit(1); }
|
||||||
|
#define warn(fmt, args...) { logit(LOG_WARNING, fmt ":%s", ##args, strerror(errno)); }
|
||||||
|
|
||||||
|
static void sys_cond(char *cond, int set)
|
||||||
|
{
|
||||||
|
char oneshot[256];
|
||||||
|
|
||||||
|
snprintf(oneshot, sizeof(oneshot), "%s/%s", _PATH_CONDSYS, cond);
|
||||||
|
if (set) {
|
||||||
|
if (symlink(_PATH_RECONF, oneshot) && errno != EEXIST)
|
||||||
|
warn("failed asserting sys/%s", cond);
|
||||||
|
} else {
|
||||||
|
if (erase(oneshot) && errno != ENOENT)
|
||||||
|
warn("failed asserting sys/%s", cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fgetln(char *path, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(path, "r");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!fgets(buf, len, fp)) {
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
chomp(buf);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_online(char *online)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (!online)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
val = atoi(online);
|
||||||
|
logit(LOG_INFO, "AC %s", val ? "connected" : "disconnected");
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_ac(char *type)
|
||||||
|
{
|
||||||
|
char *types[] = {
|
||||||
|
"Mains",
|
||||||
|
"USB",
|
||||||
|
"BrickID",
|
||||||
|
"Wireless",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; types[i]; i++) {
|
||||||
|
if (!strncmp(type, types[i], strlen(types[i])))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init(void)
|
||||||
|
{
|
||||||
|
struct dirent **d = NULL;
|
||||||
|
char *cond_dirs[] = {
|
||||||
|
_PATH_CONDSYS,
|
||||||
|
_PATH_CONDSYS "/pwr",
|
||||||
|
};
|
||||||
|
char path[384];
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)NELEMS(cond_dirs); i++) {
|
||||||
|
if (mkpath(cond_dirs[i], 0755) && errno != EEXIST) {
|
||||||
|
_pe("Failed creating %s condition directory, %s", COND_SYS,
|
||||||
|
cond_dirs[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n = scandir(_PATH_SYSFS_PWR, &d, NULL, alphasort);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
char *nm = d[i]->d_name;
|
||||||
|
char buf[10];
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/%s/type", _PATH_SYSFS_PWR, nm);
|
||||||
|
if (!fgetln(path, buf, sizeof(buf)) && is_ac(buf)) {
|
||||||
|
num_ac++;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/%s/online", _PATH_SYSFS_PWR, nm);
|
||||||
|
if (!fgetln(path, buf, sizeof(buf))) {
|
||||||
|
if (check_online(buf))
|
||||||
|
num_ac_online++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(d[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
free(d);
|
||||||
|
|
||||||
|
/* if any power_supply is online, or none can be found */
|
||||||
|
if (num_ac == 0 || num_ac_online > 0)
|
||||||
|
sys_cond("pwr/ac", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Started by Finit as soon as possible when base filesystem is up,
|
||||||
|
* modules have been probed, or insmodded from /etc/finit.conf, so by
|
||||||
|
* now we should have /sys/class/power_supply/ available for probing.
|
||||||
|
* If none is found we assert /sys/pwr/ac condition anyway, this is what
|
||||||
|
* systemd does (ConditionACPower) and also makes most sense.
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct sockaddr_nl nls = { 0 };
|
||||||
|
struct pollfd pfd;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
if (!strcmp(argv[1], "-d"))
|
||||||
|
debug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!debug) {
|
||||||
|
openlog("keventd", LOG_CONS | LOG_PID, LOG_DAEMON);
|
||||||
|
setlogmask(LOG_UPTO(LOG_NOTICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
|
||||||
|
if (pfd.fd == -1)
|
||||||
|
panic("failed creating netlink socket");
|
||||||
|
|
||||||
|
nls.nl_family = AF_NETLINK;
|
||||||
|
nls.nl_pid = 0;
|
||||||
|
nls.nl_groups = -1;
|
||||||
|
if (bind(pfd.fd, (void *)&nls, sizeof(struct sockaddr_nl)))
|
||||||
|
panic("bind failed");
|
||||||
|
|
||||||
|
logit(LOG_DEBUG, "Waiting for events ...");
|
||||||
|
while (-1 != poll(&pfd, 1, -1)) {
|
||||||
|
char *path = NULL;
|
||||||
|
int ac = 0;
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT);
|
||||||
|
if (len == -1) {
|
||||||
|
switch (errno) {
|
||||||
|
case EINTR:
|
||||||
|
continue;
|
||||||
|
case ENOBUFS:
|
||||||
|
warn("lost events");
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
panic("unhandled");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip libusb events, focus on kernel events/changes */
|
||||||
|
if (strncmp(buf, "change@", 7))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* XXX: currently limited to monitoring this subsystem */
|
||||||
|
if (!strstr(buf, "power_supply"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < len) {
|
||||||
|
char *line = buf + i;
|
||||||
|
|
||||||
|
logit(LOG_DEBUG, "%s", line);
|
||||||
|
if (!strncmp(line, "DEVPATH=", 8)) {
|
||||||
|
path = &line[8];
|
||||||
|
logit(LOG_DEBUG, "Got path %s", path);
|
||||||
|
} else if (!strncmp(line, "POWER_SUPPLY_TYPE=", 18)) {
|
||||||
|
ac = is_ac(&line[18]);
|
||||||
|
} else if (!strncmp(line, "POWER_SUPPLY_ONLINE=", 20) && ac) {
|
||||||
|
if (check_online(&line[20])) {
|
||||||
|
if (!num_ac_online)
|
||||||
|
sys_cond("pwr/ac", 1);
|
||||||
|
num_ac_online++;
|
||||||
|
} else {
|
||||||
|
if (num_ac_online > 0)
|
||||||
|
num_ac_online--;
|
||||||
|
if (!num_ac_online)
|
||||||
|
sys_cond("pwr/ac", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i += strlen(line) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(pfd.fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
+1
-1
@@ -206,7 +206,7 @@ int reboot_main(int argc, char *argv[])
|
|||||||
|
|
||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
if (do_halt(NULL))
|
if (do_halt(NULL))
|
||||||
do_kill(SIGUSR1, msg);
|
do_kill(SIGUSR2, msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_POWEROFF:
|
case CMD_POWEROFF:
|
||||||
|
|||||||
@@ -1260,6 +1260,9 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
if (type == SVC_TYPE_SERVICE && manual)
|
if (type == SVC_TYPE_SERVICE && manual)
|
||||||
svc_stop(svc);
|
svc_stop(svc);
|
||||||
} else {
|
} else {
|
||||||
|
/* update type, may have changed from service -> task */
|
||||||
|
svc->type = type;
|
||||||
|
|
||||||
/* e.g., if missing cmd or env before */
|
/* e.g., if missing cmd or env before */
|
||||||
svc_unblock(svc);
|
svc_unblock(svc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,21 +31,24 @@
|
|||||||
* does on USR1 with their FIFO/D-Bus.
|
* does on USR1 with their FIFO/D-Bus.
|
||||||
*
|
*
|
||||||
* SIGUSR1
|
* SIGUSR1
|
||||||
* Calls shutdown hooks, including HOOK_SHUTDOWN, stops all running
|
* Restarts API (initctl) socket, like SysV init and systemd does
|
||||||
* processes, and unmounts all file systems. Then tells kernel to
|
* on USR1 with their FIFO/D-Bus.
|
||||||
* halt. Most people these days want SIGUSR2 though.
|
|
||||||
*
|
*
|
||||||
* (SysV init and systemd use this to re-open their FIFO/D-Bus.)
|
* Finit <= 4.0 used to perform a system halt on USR1. This caused
|
||||||
|
* some quite nasty problems on systems with both systemd/sysvinit
|
||||||
|
* installed alongside finit. For compatibility reasons Finit 4.1
|
||||||
|
* changed to partial SIGHUP (api_exit/init).
|
||||||
*
|
*
|
||||||
* SIGUSR2
|
* SIGUSR2
|
||||||
* Like SIGUSR1, but tell kernel to power-off the system, if ACPI
|
* Calls shutdown hooks, including HOOK_SHUTDOWN, stops all running
|
||||||
* or similar exists to actually do this. If the kernel fails
|
* processes, and unmounts all file systems. Then tells kernel to
|
||||||
* power-off, Finit falls back to halt.
|
* power-off the system, if ACPI or similar exists to actually do
|
||||||
|
* this. If the kernel fails power-off, Finit falls back to halt.
|
||||||
*
|
*
|
||||||
* (SysV init N/A, systemd dumps its internal state to log.)
|
* (SysV init N/A, systemd dumps its internal state to log.)
|
||||||
*
|
*
|
||||||
* SIGTERM
|
* SIGTERM
|
||||||
* Like SIGUSR1, but tell kernel to reboot the system when done.
|
* Like SIGUSR2, but tell kernel to reboot the system when done.
|
||||||
*
|
*
|
||||||
* (SysV init N/A, systemd rexecutes itself.)
|
* (SysV init N/A, systemd rexecutes itself.)
|
||||||
*
|
*
|
||||||
@@ -323,7 +326,7 @@ static void sigint_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SIGUSR1: BusyBox style halt
|
* SIGUSR1: SysV init/systemd API socket restart
|
||||||
*/
|
*/
|
||||||
static void sigusr1_cb(uev_t *w, void *arg, int events)
|
static void sigusr1_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
@@ -333,8 +336,9 @@ static void sigusr1_cb(uev_t *w, void *arg, int events)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
halt = SHUT_HALT;
|
/* Restart initctl API domain socket, similar to systemd/SysV init */
|
||||||
service_runlevel(0);
|
api_exit();
|
||||||
|
api_init(w->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -517,10 +521,14 @@ void sig_setup(uev_ctx_t *ctx)
|
|||||||
erase(SYNC_SHUTDOWN);
|
erase(SYNC_SHUTDOWN);
|
||||||
erase(SYNC_STOPPED);
|
erase(SYNC_STOPPED);
|
||||||
|
|
||||||
/* Standard SysV init calls ctrl-alt-delete handler */
|
/*
|
||||||
|
* Standard SysV init calls ctrl-alt-delete handler
|
||||||
|
* We need to disable kernel default so it sends us SIGINT
|
||||||
|
*/
|
||||||
|
reboot(RB_DISABLE_CAD);
|
||||||
uev_signal_init(ctx, &sigint_watcher, sigint_cb, NULL, SIGINT);
|
uev_signal_init(ctx, &sigint_watcher, sigint_cb, NULL, SIGINT);
|
||||||
|
|
||||||
/* BusyBox init style signals for halt, power-off and reboot. */
|
/* BusyBox/SysV init style signals for halt, power-off and reboot. */
|
||||||
uev_signal_init(ctx, &sigusr1_watcher, sigusr1_cb, NULL, SIGUSR1);
|
uev_signal_init(ctx, &sigusr1_watcher, sigusr1_cb, NULL, SIGUSR1);
|
||||||
uev_signal_init(ctx, &sigusr2_watcher, sigusr2_cb, NULL, SIGUSR2);
|
uev_signal_init(ctx, &sigusr2_watcher, sigusr2_cb, NULL, SIGUSR2);
|
||||||
uev_signal_init(ctx, &sigpwr_watcher, sigusr2_cb, NULL, SIGPWR);
|
uev_signal_init(ctx, &sigpwr_watcher, sigusr2_cb, NULL, SIGPWR);
|
||||||
|
|||||||
+44
@@ -154,6 +154,35 @@ char *str(char *fmt, ...)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fnread(char *buf, size_t len, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
va_list ap;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(path, sizeof(path), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (!buf || !len) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(path, &st))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (ssize_t)st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(path, "r");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len = fread(buf, sizeof(char), len, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return (int)len;
|
||||||
|
}
|
||||||
|
|
||||||
int fnwrite(char *value, char *fmt, ...)
|
int fnwrite(char *value, char *fmt, ...)
|
||||||
{
|
{
|
||||||
char path[256];
|
char path[256];
|
||||||
@@ -185,6 +214,21 @@ int fnwrite(char *value, char *fmt, ...)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fngetint(char *path, int *val)
|
||||||
|
{
|
||||||
|
char buf[10];
|
||||||
|
|
||||||
|
if (fnread(buf, sizeof(buf), path) <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
*val = strtoul(chomp(buf), NULL, 0);
|
||||||
|
if (errno)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* musl libc default to /dev/null/utmp and /dev/null/wtmp, respectively.
|
* musl libc default to /dev/null/utmp and /dev/null/wtmp, respectively.
|
||||||
* See https://www.openwall.com/lists/musl/2012/03/04/4 for reasoning.
|
* See https://www.openwall.com/lists/musl/2012/03/04/4 for reasoning.
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ extern char *prognm;
|
|||||||
char *progname (char *arg0);
|
char *progname (char *arg0);
|
||||||
|
|
||||||
char *str (char *fmt, ...);
|
char *str (char *fmt, ...);
|
||||||
|
int fnread (char *buf, size_t len, char *fmt, ...);
|
||||||
int fnwrite (char *value, char *fmt, ...);
|
int fnwrite (char *value, char *fmt, ...);
|
||||||
|
int fngetint (char *path, int *val);
|
||||||
|
|
||||||
int has_utmp (void);
|
int has_utmp (void);
|
||||||
int strtobytes (char *arg);
|
int strtobytes (char *arg);
|
||||||
|
|||||||
Reference in New Issue
Block a user