mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
240
Commits
4.6
...
reload-script
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce7d4cebab | ||
|
|
d5a47e2d8b | ||
|
|
020eefe732 | ||
|
|
14336bd407 | ||
|
|
bb841383b8 | ||
|
|
e49763d834 | ||
|
|
57545e1ab0 | ||
|
|
7ad802b092 | ||
|
|
e319a606b8 | ||
|
|
7d434b1eaa | ||
|
|
58d48b54b3 | ||
|
|
7d4603e13b | ||
|
|
d0c5d7be5b | ||
|
|
db840bdc19 | ||
|
|
3df3c51dae | ||
|
|
d37d241647 | ||
|
|
b18b21830a | ||
|
|
06daf2e4a5 | ||
|
|
eb13ccc227 | ||
|
|
0861373d14 | ||
|
|
1b9e69414e | ||
|
|
39f4aa3f2c | ||
|
|
dedb56a9d0 | ||
|
|
a27903c745 | ||
|
|
f24f76fc80 | ||
|
|
d95fc5f790 | ||
|
|
10a1257e47 | ||
|
|
a7b8e1b94d | ||
|
|
da83462731 | ||
|
|
1396177706 | ||
|
|
7cf0a293fd | ||
|
|
d0d9b83b66 | ||
|
|
76f8a18816 | ||
|
|
dc497bcd57 | ||
|
|
0da6bbe4a8 | ||
|
|
91f7a75bee | ||
|
|
f217d493b4 | ||
|
|
77404a2ea0 | ||
|
|
d42a1d438b | ||
|
|
1275f05343 | ||
|
|
61a92aa0b6 | ||
|
|
b38ff0cc79 | ||
|
|
168f5bf1d8 | ||
|
|
ffd00f646c | ||
|
|
5e2e273cad | ||
|
|
33f6697cd5 | ||
|
|
6f0ba22a0f | ||
|
|
ecb690c9ec | ||
|
|
0459bb432a | ||
|
|
2760616c73 | ||
|
|
62ab990129 | ||
|
|
0c2836d747 | ||
|
|
8be7a462e0 | ||
|
|
5993b4bb5d | ||
|
|
2957246092 | ||
|
|
a5710125f6 | ||
|
|
ff95ebeb91 | ||
|
|
1921b3f2c5 | ||
|
|
051ef81e53 | ||
|
|
90993c237a | ||
|
|
b0b4f7b2ba | ||
|
|
4d79d84fb8 | ||
|
|
d318aa00c3 | ||
|
|
9684127eb7 | ||
|
|
8d2cfd69fa | ||
|
|
4f252858e4 | ||
|
|
1ccd1d6926 | ||
|
|
b87c51209d | ||
|
|
6b7478ff43 | ||
|
|
6c4c16cbdb | ||
|
|
e539dbfe37 | ||
|
|
90c6bcd365 | ||
|
|
c9c268f218 | ||
|
|
3feff37ba5 | ||
|
|
c67d15e272 | ||
|
|
8984c655f8 | ||
|
|
1a7b26bac3 | ||
|
|
1f47718012 | ||
|
|
fa13cddc28 | ||
|
|
185a72bd14 | ||
|
|
cd32c623cf | ||
|
|
ac4b9c2f93 | ||
|
|
5e9591d0a8 | ||
|
|
e3bcf9bf16 | ||
|
|
84fd3196b0 | ||
|
|
994e51e34f | ||
|
|
0a7814b391 | ||
|
|
73f72b39cf | ||
|
|
02e0aa7383 | ||
|
|
6528628b5c | ||
|
|
1480657982 | ||
|
|
33e378a345 | ||
|
|
b695b46a9d | ||
|
|
0e61ed727f | ||
|
|
e9d60a6c04 | ||
|
|
5e9edf9deb | ||
|
|
8ed2751ae1 | ||
|
|
7fec66dc09 | ||
|
|
75fa868a4b | ||
|
|
7b321de339 | ||
|
|
1691ebb292 | ||
|
|
c371c10455 | ||
|
|
a23e152f6b | ||
|
|
9210f2851e | ||
|
|
617609cbc5 | ||
|
|
b022916758 | ||
|
|
9a357b7aab | ||
|
|
ffd01b0276 | ||
|
|
2c95f091ee | ||
|
|
b75b107d6d | ||
|
|
1f2c1d2109 | ||
|
|
f328d24d01 | ||
|
|
211293a83d | ||
|
|
446f5bc8b8 | ||
|
|
0c6f748f2c | ||
|
|
a677b94ad9 | ||
|
|
6552cda605 | ||
|
|
3add682be3 | ||
|
|
abac31682d | ||
|
|
cfe915e6d5 | ||
|
|
ecf65ce44b | ||
|
|
0d742d6ae8 | ||
|
|
cf201a43df | ||
|
|
9245869e18 | ||
|
|
0f4a487328 | ||
|
|
f1b5b42919 | ||
|
|
f546129baf | ||
|
|
27451ac3f2 | ||
|
|
0a8f3a6250 | ||
|
|
70c4e7d774 | ||
|
|
5265eee25d | ||
|
|
4b06e1a49f | ||
|
|
6b9aa21509 | ||
|
|
990307fbc9 | ||
|
|
9d8a9b7fba | ||
|
|
bbc83eaa64 | ||
|
|
23d034f521 | ||
|
|
9a3148a49d | ||
|
|
8560103a24 | ||
|
|
7a75e34808 | ||
|
|
4d4fc10d57 | ||
|
|
003faae9e9 | ||
|
|
01a01d65c0 | ||
|
|
048302f06a | ||
|
|
74f0fcfccd | ||
|
|
3cfe0a33b8 | ||
|
|
465bc17ca4 | ||
|
|
d4889b435d | ||
|
|
49c0557ced | ||
|
|
6be16f2f6d | ||
|
|
bc8118d515 | ||
|
|
0c0e880f3f | ||
|
|
119e66a7e9 | ||
|
|
46ffa81f5c | ||
|
|
54701422a5 | ||
|
|
9d463e3823 | ||
|
|
56e558c960 | ||
|
|
dfaf351da1 | ||
|
|
a8433fcb7f | ||
|
|
2daa953bee | ||
|
|
3e3e9aadf5 | ||
|
|
dc873c6548 | ||
|
|
29bd7a504e | ||
|
|
a0685219cf | ||
|
|
13b107b7b1 | ||
|
|
409d68d05b | ||
|
|
ab62b5282b | ||
|
|
d02d65feeb | ||
|
|
9a0dea6aef | ||
|
|
7481505b1a | ||
|
|
8251f1a422 | ||
|
|
e269176a79 | ||
|
|
612f5a9385 | ||
|
|
4a2381eb6f | ||
|
|
0cae7d44dd | ||
|
|
340cae4afd | ||
|
|
6a89e60fc8 | ||
|
|
840d612fc2 | ||
|
|
60c676ab2d | ||
|
|
deada0fa89 | ||
|
|
7b501f255b | ||
|
|
052136cb99 | ||
|
|
742b8b72cc | ||
|
|
c37037c015 | ||
|
|
c32b5a749a | ||
|
|
7701718d7b | ||
|
|
eb4eca9607 | ||
|
|
cab94b81e8 | ||
|
|
5913217808 | ||
|
|
b49f55ab3d | ||
|
|
bf4a584e2e | ||
|
|
90a4df8d12 | ||
|
|
146bf55122 | ||
|
|
c1ed373398 | ||
|
|
5998342b3e | ||
|
|
9dc7b8a6b0 | ||
|
|
c221823654 | ||
|
|
248f7d3110 | ||
|
|
fe90ba5781 | ||
|
|
71c87734b7 | ||
|
|
cd060e8af3 | ||
|
|
33a7f123d7 | ||
|
|
d15e28ea6b | ||
|
|
836bfff08b | ||
|
|
59152b557c | ||
|
|
293b0ffa79 | ||
|
|
d5d9cd5645 | ||
|
|
2f281665af | ||
|
|
b00e7394f8 | ||
|
|
d5a5fffa52 | ||
|
|
4d24c34b28 | ||
|
|
355265651e | ||
|
|
41093df2a9 | ||
|
|
0a816d1fa4 | ||
|
|
3bfc0f0fca | ||
|
|
0aa6ee895c | ||
|
|
b1526fb2d6 | ||
|
|
b2624ac160 | ||
|
|
2c340f83ce | ||
|
|
337ee003bb | ||
|
|
791df0c986 | ||
|
|
f29e92be21 | ||
|
|
379a63fce4 | ||
|
|
b1f9a11809 | ||
|
|
2d9c63e48e | ||
|
|
d66455496a | ||
|
|
77cf72cb40 | ||
|
|
6cc587068b | ||
|
|
cc96e8908a | ||
|
|
adb25d52cd | ||
|
|
7d09567ec8 | ||
|
|
9130af1c77 | ||
|
|
cbea83b369 | ||
|
|
42cd8d284b | ||
|
|
72ebc92622 | ||
|
|
06adecaaea | ||
|
|
efc0592961 | ||
|
|
ed88469276 | ||
|
|
cbf96a1de0 | ||
|
|
cc979f27f1 |
@@ -24,7 +24,8 @@ the maintainer(s) and make it easier for them to include your code.
|
|||||||
Coding Style
|
Coding Style
|
||||||
------------
|
------------
|
||||||
|
|
||||||
> **Tip:** Always submit code that follows the style of surrounding code!
|
> [!TIP]
|
||||||
|
> Always submit code that follows the style of surrounding code!
|
||||||
|
|
||||||
First of all, lines are allowed to be longer than 72 characters these
|
First of all, lines are allowed to be longer than 72 characters these
|
||||||
days. In fact, there exist no enforced maximum, but keeping it around
|
days. In fact, there exist no enforced maximum, but keeping it around
|
||||||
|
|||||||
@@ -21,26 +21,26 @@ jobs:
|
|||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
env:
|
env:
|
||||||
MAKEFLAGS: -j3
|
|
||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
|
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Static Finit
|
- name: Static Finit
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix= --enable-static
|
./configure --prefix= --enable-static
|
||||||
make V=1
|
make -j3 V=1
|
||||||
- name: Regular Finit
|
- name: Regular Finit
|
||||||
run: |
|
run: |
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
--with-keventd
|
--with-keventd \
|
||||||
make clean
|
CFLAGS="-fsanitize=address -ggdb"
|
||||||
make V=1
|
make -j3 clean
|
||||||
|
make -j3 V=1
|
||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
@@ -57,11 +57,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo /tmp/sbin/finit -h
|
sudo /tmp/sbin/finit -h
|
||||||
sudo /tmp/sbin/initctl -h
|
sudo /tmp/sbin/initctl -h
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: |
|
run: |
|
||||||
make check || (cat test/test-suite.log; false)
|
make check || (cat test/test-suite.log; false)
|
||||||
- name: Upload Test Results
|
- name: Upload Test Results
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: finit-test-${{ matrix.compiler }}
|
name: finit-test-${{ matrix.compiler }}
|
||||||
path: test/*.log
|
path: test/*.log
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'dev'
|
- 'dev'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: finit
|
PROJECT_NAME: finit
|
||||||
@@ -15,22 +16,39 @@ jobs:
|
|||||||
coverity:
|
coverity:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v3
|
- name: Fetch latest Coverity Scan MD5
|
||||||
id: coverity-toolchain-cache
|
id: var
|
||||||
with:
|
|
||||||
path: cov-analysis-linux64
|
|
||||||
key: ${{ runner.os }}-coverity
|
|
||||||
- name: Download Coverity Scan
|
|
||||||
if: steps.coverity-toolchain-cache.outputs.cache-hit != 'true'
|
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
|
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
||||||
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
||||||
|
-O coverity-latest.tar.gz.md5
|
||||||
|
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
id: cache
|
||||||
|
with:
|
||||||
|
path: coverity-latest.tar.gz
|
||||||
|
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
||||||
|
${{ runner.os }}-coverity-
|
||||||
|
${{ runner.os }}-coverity
|
||||||
|
- name: Download Coverity Scan
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ ! -f coverity-latest.tar.gz ]; then
|
||||||
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
||||||
-O cov-analysis-linux64.tar.gz
|
-O coverity-latest.tar.gz
|
||||||
mkdir cov-analysis-linux64
|
else
|
||||||
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
|
echo "Latest Coverity Scan available from cache :-)"
|
||||||
|
md5sum coverity-latest.tar.gz
|
||||||
|
fi
|
||||||
|
mkdir coverity
|
||||||
|
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
@@ -42,13 +60,15 @@ jobs:
|
|||||||
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
|
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
- name: Build
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
|
- name: Build
|
||||||
|
run: |
|
||||||
|
export PATH=`pwd`/coverity/bin:$PATH
|
||||||
cov-build --dir cov-int make
|
cov-build --dir cov-int make
|
||||||
- name: Submit result to Coverity Scan
|
- name: Submit results to Coverity Scan
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
@@ -61,3 +81,8 @@ jobs:
|
|||||||
--form version=trunk \
|
--form version=trunk \
|
||||||
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
||||||
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
||||||
|
- name: Upload build.log
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverity-build.log
|
||||||
|
path: cov-int/build-log.txt
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
MAKEFLAGS: -j3
|
MAKEFLAGS: -j3
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Installing dependencies ...
|
- name: Installing dependencies ...
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
@@ -39,6 +39,9 @@ jobs:
|
|||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
--with-keventd
|
--with-keventd
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Build release ...
|
- name: Build release ...
|
||||||
run: |
|
run: |
|
||||||
make release || (cat test/test-suite.log; false)
|
make release || (cat test/test-suite.log; false)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
run: ${{ steps.check.outputs.run }}
|
run: ${{ steps.check.outputs.run }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Check for any commits since last week
|
- name: Check for any commits since last week
|
||||||
id: schedule
|
id: schedule
|
||||||
run: |
|
run: |
|
||||||
@@ -25,14 +25,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
distcheck:
|
distcheck:
|
||||||
needs: schedule
|
needs: schedule
|
||||||
if: ${{ needs.schedule.outputs.run }}
|
if: ${{ needs.schedule.outputs.run == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Base run
|
- name: Base run
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
@@ -41,6 +41,9 @@ jobs:
|
|||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
|
- name: Enable unprivileged userns (unshare)
|
||||||
|
run: |
|
||||||
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Check dist tarball
|
- name: Check dist tarball
|
||||||
run: |
|
run: |
|
||||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ GTAGS
|
|||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/ar-lib
|
/ar-lib
|
||||||
|
/backup/
|
||||||
/compile
|
/compile
|
||||||
/config.cache
|
/config.cache
|
||||||
/config.h
|
/config.h
|
||||||
@@ -36,6 +37,9 @@ GTAGS
|
|||||||
/test-driver
|
/test-driver
|
||||||
/test-suite.log
|
/test-suite.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
/.gdb_history
|
||||||
|
|
||||||
# TroglOS build system
|
# TroglOS build system
|
||||||
/.config
|
/.config
|
||||||
/.stamp
|
/.stamp
|
||||||
|
|||||||
+173
-3
@@ -4,6 +4,170 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.12][] - 2025-04-28
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Improve notify:s6 readiness compatibility, by Aaron Andersen
|
||||||
|
- Update `runparts` usage text
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix variable overloading in urandom plugin
|
||||||
|
- Fix buffer overwrite in urandom plugin, reported by Aaron Andersen
|
||||||
|
|
||||||
|
|
||||||
|
[4.11][] - 2025-03-27
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Update documentation regarding transition from runlevel S to 2, how
|
||||||
|
run/tasks must "complete" before Finit can move to the next runlevel
|
||||||
|
- Improve argument handling in bundled getty when launching login
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #432: allow services in `setup` state to be stopped. This fixes
|
||||||
|
a serious blocker introduced in 4.10 that prevented systems from
|
||||||
|
being rebooted when any service was in this state
|
||||||
|
- Fix fallback `SIGKILL` when stopping a service with `SIGTERM` does
|
||||||
|
not work. This fixes a serious issue with services not responding to
|
||||||
|
the default `SIGTERM`
|
||||||
|
- Fix pre/post/ready/cleanup script execution if service has an
|
||||||
|
optional `env:file` (leading `-`)
|
||||||
|
- Fix blocked signals for pre/post/ready/cleanup scripts preventing
|
||||||
|
normal shutdown when a service/sysv is stopped in its setup state
|
||||||
|
- Fix issue where a pre:script creates a PID file in `/run` cause the
|
||||||
|
service to move from setup state to running. Any `svc_t` in setup,
|
||||||
|
teardown, or cleanup state should be ignored in the pidfile plugin
|
||||||
|
|
||||||
|
|
||||||
|
[4.10][] - 2025-03-03
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add support for `cleanup:[0-3600,]script`, runs before service is
|
||||||
|
removed, unlike `post:script` that runs when service is stopped
|
||||||
|
- Improved entropy gathering in tertiary fallback of urandom plugin
|
||||||
|
- Reclassify `sysv` from run/task class to `service`
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #427: using an external getty with custom login program cause
|
||||||
|
Finit to use login program as the getty command
|
||||||
|
- Fix #428: allow `sysctl` path to be set at build time
|
||||||
|
- Fix #429: regression in v4.9 causing Finit to segfault at shutdown
|
||||||
|
- Fix possible memory leak when sourcing a service `env:file`
|
||||||
|
- Finit now waits until all `post:scripts` have run before returning
|
||||||
|
OK to `initctl <reload|runlevel>`. This also applies to the new
|
||||||
|
`cleanup:scripts` introduced in this release
|
||||||
|
- RFC3154 conformance formatting fix for `/dev/kmsg` fallback logging
|
||||||
|
|
||||||
|
|
||||||
|
[4.9][] - 2025-02-15
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> This release changes how Finit reacts to the exit status of `pre:`
|
||||||
|
> scripts. Finit will now no longer start the main process if its
|
||||||
|
> `pre:` script fails for any reason. So, if you have pre scripts that,
|
||||||
|
> e.g., create directories, make sure they are idempotent.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add individual timeout (optional) support for pre/post/ready scripts
|
||||||
|
- Add support for systems with broken RTC, i.e., those that at power-on
|
||||||
|
may reset the RTC to a random date instead of zero, issue #418
|
||||||
|
- Add support for detecting "in-container" when in `systemd-nspawn`
|
||||||
|
- Check exit status of `pre:` scripts, on failure drive service/sysv to
|
||||||
|
`crashed` state. (The exit code of `post:` scripts remain ignored)
|
||||||
|
- All pre/post/ready scripts are now also searched for in `$PATH`
|
||||||
|
- Reset color attributes and clear screen when starting up. This is
|
||||||
|
for boot loaders like GRUB, which leave background color artifacts
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #415: only mark reverse-dependencies "dirty" if the main service
|
||||||
|
does not support SIGHUP. This helps avoid unnecessary restarts of
|
||||||
|
services that depend on a service that supports SIGHUP
|
||||||
|
- Fix #417: leaking inotify watchers in the cgroup subsystem
|
||||||
|
- Fix #421: add support for `nofail` mount option in `/etc/fstab`
|
||||||
|
- Fix #425: ordering bug in detecting .conf file changes to services
|
||||||
|
and `initctl reload`, or runlevel changes
|
||||||
|
- Fix `initctl touch` of template services, previously marking a
|
||||||
|
service created from a template as "dirty" did not take
|
||||||
|
- Fix unintended restart of template "siblings". I.e., `initctl touch`
|
||||||
|
of instantiated template service A affected B from same template
|
||||||
|
- Fix buggy `--with-rtc-date=DATE` configure option
|
||||||
|
- Fix kill on timeout of pre/post/ready scripts
|
||||||
|
|
||||||
|
|
||||||
|
[4.8][] - 2024-10-13
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Avoid remounting already mounted `/run` and `/tmp` directories. This
|
||||||
|
extends the existing support for detecting mounted directories to
|
||||||
|
include complex mount hierarchies are in use, overlayfs and tmpfs
|
||||||
|
mounts. Feature by Mathias Thore, Atlas Copco
|
||||||
|
- getty: trigger /etc/issue compat mode for Alpine Linux
|
||||||
|
- tmpfiles.d: skip `x11.conf` unless X11 common plugin is enabled
|
||||||
|
- tmpfiles.d: ignore x/X command, nos support for cleanup at runtime
|
||||||
|
- Drop debug mode `-D` from `udevd` in `hotplug.conf.in`, allow the
|
||||||
|
user to set this in `/etc/default/udevd` instead
|
||||||
|
- Certain initctl APIs at bootstrap are not supported, update warning
|
||||||
|
log to include command (number) for troubleshooting, issue #398
|
||||||
|
- Add support for hwrng to urandom plugin and check for empty seed
|
||||||
|
- Add `runparts -b` (batch mode) support, disables escape sequences
|
||||||
|
- New configure `--without-rc-local`, disables `/etc/rc.local` support
|
||||||
|
- New configure `--disable-cgroup` option, disables cgroup v2 detection
|
||||||
|
- `initctl show template@foo.conf` now shows how an enabled template
|
||||||
|
service has been evaluated by Finit, issue #411
|
||||||
|
- Extend `initctl` timeout connecting and waiting for Finit reply. The
|
||||||
|
previous 2 + 2 second poll timeout has proved to be too short on more
|
||||||
|
complex systems. Now a 15 + 15 second timeout is applied which should
|
||||||
|
be more resistant to temporary overload scenarios, issue #407
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #397: system shutdown/reboot can block on console input if action
|
||||||
|
is started remotely (ssh). Caused by legacy TTY screen size probing,
|
||||||
|
removed from both bootstrap and shutdown/reboot
|
||||||
|
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
||||||
|
either mount or `fsck` errors. Problem caused by unresolved status
|
||||||
|
from pipe, calling `pclose()` without extracting exit status
|
||||||
|
- Fix #402: `initctl touch` does not respect `-n` (no error) flag
|
||||||
|
- Fix #403: `initctl touch` does not support template services
|
||||||
|
- Fix #404: possible undefined behavior when `--with-fstab=no` is set
|
||||||
|
- Fix #405: `@console` getty does not work with `tty0 ttyS0`
|
||||||
|
- Fix #409: prevent tmpfiles from following symlinks for `L+` and `R`,
|
||||||
|
otherwise symlink targets would also be removed. Found and fixed by
|
||||||
|
Mathias Thore and Ming Liu, Atlas Copco
|
||||||
|
- Fix #414: Frr Zebra immediately restarts on `initctl stop zebra`.
|
||||||
|
The fix likely works for all Frr/Quagga services due to the way they
|
||||||
|
create and delete their pid file
|
||||||
|
- Cosmetic issue with `[ OK ]` messages being printed out of order at
|
||||||
|
shutdown/reboot. Caused by nested calls to `service_stop()`
|
||||||
|
- Cosmetic issue with duplicate "Restoring RTC" message at bootstrap
|
||||||
|
|
||||||
|
|
||||||
|
[4.7][] - 2024-01-07
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Silence "not available" messages for run/task/service with `nowarn`
|
||||||
|
- Update docs, `cgroup.root` workaround for `SCHED_RR` tasks
|
||||||
|
- Drop runlevels 0 and 6 from `keventd`, not needed at reboot/poweroff
|
||||||
|
- Mount `/dev/shm` with mode 1777 (sticky bit)
|
||||||
|
- Mount `/dev/mqueue` if available, inspiration from Alpine Linux
|
||||||
|
- Update Alpine Linux installer and configuration files, tested on
|
||||||
|
Alpine v3.19, some assembly still required
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix confusing warning message when tmpfiles.d fails to install symlink
|
||||||
|
- Fix tmpfiles.d legacy `/run/lock/subsys`, ordering
|
||||||
|
- Add missing `/var/tmp` and `/var/lock -> /run/lock` (tmpfiles.d)
|
||||||
|
- Fix #388: log redirection broken unless Finit runs in debug mode.
|
||||||
|
Found and fixed by Ryan Rorison
|
||||||
|
- Fix #389: must libc requires `libgen.h` for `basename()` function.
|
||||||
|
Reported and worked around with new `basenm()` function by Stargirl
|
||||||
|
- Fix #392: `service/foo/ready` condition reasserted on pidfile removal
|
||||||
|
|
||||||
|
|
||||||
[4.6][] - 2023-11-13
|
[4.6][] - 2023-11-13
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -219,7 +383,7 @@ All relevant changes are documented in this file.
|
|||||||
`/etc/finit.conf`.
|
`/etc/finit.conf`.
|
||||||
|
|
||||||
For the complete experience a new top-level configuration file directive
|
For the complete experience a new top-level configuration file directive
|
||||||
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
|
`rcsd PATH` has also been added. It in turn can be used by `factory.conf`
|
||||||
as follows to override `/etc/finit.d`:
|
as follows to override `/etc/finit.d`:
|
||||||
|
|
||||||
rcsd /etc/factory.d
|
rcsd /etc/factory.d
|
||||||
@@ -802,7 +966,7 @@ make sure to read the whole change log when upgrading.
|
|||||||
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
||||||
various distro packed udevd and other hotplugging tools
|
various distro packed udevd and other hotplugging tools
|
||||||
* A proper rescue mode has been added. It is started extremely early
|
* A proper rescue mode has been added. It is started extremely early
|
||||||
and is protected with a bundled `suslogin`. Exiting rescue mode now
|
and is protected with a bundled `sulogin`. Exiting rescue mode now
|
||||||
brings up the system as a normal boot, as one expects
|
brings up the system as a normal boot, as one expects
|
||||||
* Support for `sysv` start/stop scripts as well as monitoring forking
|
* Support for `sysv` start/stop scripts as well as monitoring forking
|
||||||
services, stared using `sysv` or `service` stanza
|
services, stared using `sysv` or `service` stanza
|
||||||
@@ -1633,7 +1797,13 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.6...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.11...HEAD
|
||||||
|
[4.12]: https://github.com/troglobit/finit/compare/4.11...4.12
|
||||||
|
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
||||||
|
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
||||||
|
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
||||||
|
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
||||||
|
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
[4.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
|
||||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+12
-1
@@ -1,5 +1,5 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = man plugins src system test tmpfiles.d
|
SUBDIRS = man plugins src system tmpfiles.d
|
||||||
doc_DATA = README.md LICENSE contrib/finit.conf
|
doc_DATA = README.md LICENSE contrib/finit.conf
|
||||||
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
||||||
|
|
||||||
@@ -9,6 +9,17 @@ endif
|
|||||||
if DOC
|
if DOC
|
||||||
SUBDIRS += doc
|
SUBDIRS += doc
|
||||||
endif
|
endif
|
||||||
|
if LIBSYSTEMD
|
||||||
|
SUBDIRS += libsystemd
|
||||||
|
endif
|
||||||
|
|
||||||
|
if LIBSYSTEMD
|
||||||
|
SUBDIRS += test
|
||||||
|
# Explicit dependency to ensure libsystemd is built before test
|
||||||
|
test: libsystemd
|
||||||
|
else
|
||||||
|
SUBDIRS += test
|
||||||
|
endif
|
||||||
|
|
||||||
if BASH
|
if BASH
|
||||||
bashdir = $(BASH_DIR)
|
bashdir = $(BASH_DIR)
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ Introduction
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Fast init for Linux systems. Reverse engineered from the [EeePC
|
Fast init for Linux systems. Reverse engineered from the [EeePC
|
||||||
fastinit][] over ten years ago by [Claudio Matsuoka][] — "gaps filled
|
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
||||||
with frog DNA …"
|
|
||||||
|
|
||||||

|

|
||||||
*Figure 1: Screenshot showing Finit booting [Alpine Linux](https://www.alpinelinux.org/).*
|
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
|
||||||
|
|
||||||
Features include:
|
Features include:
|
||||||
|
|
||||||
@@ -62,10 +61,13 @@ distributions:
|
|||||||
* [Alpine Linux](contrib/alpine/), and
|
* [Alpine Linux](contrib/alpine/), and
|
||||||
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
||||||
|
|
||||||
> **Note:** support for various Linux distributions does not mean Finit
|
> [!NOTE]
|
||||||
> installs easily on all architectures. The bundled install scripts are
|
> Support for various Linux distributions does not mean Finit installs
|
||||||
> examples for standard installations, tested on amd64 (x86_64) systems.
|
> easily on all architectures. The bundled install scripts are examples
|
||||||
> Custom setups, for embedded systems, can be found in [myLinux][].
|
> for standard installations, tested on amd64 (x86_64) systems. Custom
|
||||||
|
> setups, e.g., for embedded systems, can be found in the following
|
||||||
|
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
||||||
|
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -77,9 +79,10 @@ be placed in `/etc/finit.d/available` and enabled by an operator using
|
|||||||
the [initctl](#commands--status) tool. See the above mentioned Linux
|
the [initctl](#commands--status) tool. See the above mentioned Linux
|
||||||
distributions, or [myLinux][].
|
distributions, or [myLinux][].
|
||||||
|
|
||||||
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
|
> [!TIP]
|
||||||
> standard UNIX continuation character (`\`), also trailing comments are
|
> As of Finit v4.4, `.conf` lines can be broken up using the standard
|
||||||
> now supported. The latter means you need to escape any hashes used in
|
> UNIX continuation character (`\`), trailing comments are now also
|
||||||
|
> supported. The latter means you need to escape any hashes used in
|
||||||
> directives and descriptions (`\#`). For more on this and examples,
|
> directives and descriptions (`\#`). For more on this and examples,
|
||||||
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
||||||
|
|
||||||
@@ -248,7 +251,7 @@ All services in runlevel S) are started first, followed by the desired
|
|||||||
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
||||||
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
||||||
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
||||||
`intictl` tool.
|
[`initctl`](#commands--status) tool.
|
||||||
|
|
||||||
|
|
||||||
**Conditions**
|
**Conditions**
|
||||||
@@ -284,6 +287,7 @@ run [S] /path/to/ident --
|
|||||||
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> Notice the trick with an empty description to hide the call to `ident`
|
> Notice the trick with an empty description to hide the call to `ident`
|
||||||
> in the Finit progress output.
|
> in the Finit progress output.
|
||||||
|
|
||||||
@@ -366,9 +370,10 @@ The `initctl` tool has three commands to help debug and optimize the
|
|||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
||||||
commands for details.
|
commands for details.
|
||||||
|
|
||||||
> **Note:** systems that do not support cgroups, specifically version 2,
|
> [!NOTE]
|
||||||
> are automatically detected. On such systems the above functionality
|
> Systems that do not support cgroups, specifically version 2, are
|
||||||
> is disabled early at boot.
|
> automatically detected. On such systems the above functionality is
|
||||||
|
> disabled early at boot.
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
Runparts & /etc/rc.local
|
||||||
@@ -404,8 +409,7 @@ The event loop is the whole thing which Finit is built around, except
|
|||||||
for runlevel S, which remains a slow procession through a lot of set up,
|
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
|
||||||
@@ -573,9 +577,10 @@ file must be used to tell Finit to stop and start it on `reload` and
|
|||||||
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
|
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
|
||||||
these will also affect how a service is maintained.
|
these will also affect how a service is maintained.
|
||||||
|
|
||||||
> **Note:** even though it is possible to start services not belonging in
|
> [!NOTE]
|
||||||
> the current runlevel these services will not be respawned automatically
|
> Even though it is possible to start services not belonging in the
|
||||||
> by Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
> current runlevel these services will not be respawned automatically by
|
||||||
|
> Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
||||||
> Dropbear SSH service will not be restarted if it is killed or exits.
|
> Dropbear SSH service will not be restarted if it is killed or exits.
|
||||||
|
|
||||||
The `status` command is the default, it displays a quick overview of all
|
The `status` command is the default, it displays a quick overview of all
|
||||||
@@ -705,6 +710,8 @@ and proposed extensions.
|
|||||||
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
||||||
[Joachim Wiberg]: https://troglobit.com
|
[Joachim Wiberg]: https://troglobit.com
|
||||||
|
[Buildroot]: https://buildroot.org
|
||||||
|
[Infix]: https://kernelkit.github.io
|
||||||
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
||||||
[License]: https://en.wikipedia.org/wiki/MIT_License
|
[License]: https://en.wikipedia.org/wiki/MIT_License
|
||||||
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
||||||
|
|||||||
@@ -1,7 +1,33 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Run test suite with the correct configure params
|
# Run test suite with the correct configure params
|
||||||
|
run_make=1
|
||||||
|
jobs=17
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-n|--no-make)
|
||||||
|
run_make=0
|
||||||
|
;;
|
||||||
|
-j|--jobs)
|
||||||
|
shift
|
||||||
|
jobs="$1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [--no-make] [-j N]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$run_make" -eq 1 ]; then
|
||||||
make distclean
|
make distclean
|
||||||
|
fi
|
||||||
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --with-watchdog --with-keventd
|
--enable-x11-common-plugin --with-watchdog --with-keventd \
|
||||||
make -j17 clean check
|
CFLAGS='-fsanitize=address -ggdb'
|
||||||
|
|
||||||
|
if [ "$run_make" -eq 1 ]; then
|
||||||
|
make -j"$jobs" clean check
|
||||||
|
fi
|
||||||
|
|||||||
+48
-9
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([Finit], [4.6], [https://github.com/troglobit/finit/issues],
|
AC_INIT([Finit], [4.13-pre], [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])
|
||||||
@@ -12,6 +12,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/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
|
||||||
|
libsystemd/Makefile libsystemd/libsystemd.pc
|
||||||
man/Makefile
|
man/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
@@ -67,10 +68,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])
|
||||||
@@ -160,6 +169,10 @@ AC_ARG_WITH(watchdog,
|
|||||||
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Enable built-in watchdog, default: /dev/watchdog]),
|
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Enable built-in watchdog, default: /dev/watchdog]),
|
||||||
[watchdog=$withval], [with_watchdog=no watchdog=])
|
[watchdog=$withval], [with_watchdog=no watchdog=])
|
||||||
|
|
||||||
|
AC_ARG_WITH(libsystemd,
|
||||||
|
AS_HELP_STRING([--with-libsystemd], [Build replacement libsystemd library, default: yes]),
|
||||||
|
[with_libsystemd=$withval], [with_libsystemd=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(hook-scripts-path,
|
AC_ARG_WITH(hook-scripts-path,
|
||||||
AS_HELP_STRING([--with-hook-scripts-path=DIR], [Base directory for hook scripts, default $libexecdir/finit/hook]),
|
AS_HELP_STRING([--with-hook-scripts-path=DIR], [Base directory for hook scripts, default $libexecdir/finit/hook]),
|
||||||
[hook_scripts_path=$withval], [hook_scripts_path=yes])
|
[hook_scripts_path=$withval], [hook_scripts_path=yes])
|
||||||
@@ -169,9 +182,13 @@ AC_ARG_WITH(plugin-path,
|
|||||||
[plugin_path=$withval], [plugin_path=yes])
|
[plugin_path=$withval], [plugin_path=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-date,
|
AC_ARG_WITH(rtc-date,
|
||||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM", default "2000-01-01 00:00"]),
|
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
|
||||||
[rtc_date=$withval], [rtc_date=no])
|
[rtc_date=$withval], [rtc_date=no])
|
||||||
|
|
||||||
|
AC_ARG_WITH(rtc-file,
|
||||||
|
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
|
||||||
|
[rtc_file=$withval], [rtc_file=no])
|
||||||
|
|
||||||
### Enable features ###########################################################################
|
### Enable features ###########################################################################
|
||||||
|
|
||||||
# Create config.h from selected features and fallback defaults
|
# Create config.h from selected features and fallback defaults
|
||||||
@@ -181,6 +198,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 +250,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"], [
|
||||||
@@ -265,9 +287,16 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
|||||||
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
||||||
|
|
||||||
AS_IF([test "x$rtc_date" != "xno"], [
|
AS_IF([test "x$rtc_date" != "xno"], [
|
||||||
AC_DEFINE(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
||||||
rtc_date=""])
|
rtc_date=""])
|
||||||
|
|
||||||
|
AS_IF([test "x$rtc_file" != "xno"], [
|
||||||
|
AS_IF([test "x$rtc_file" = "xyes"], [
|
||||||
|
rtc_file=/var/lib/misc/rtc])
|
||||||
|
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
|
||||||
|
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
|
||||||
|
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
|
||||||
|
|
||||||
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
||||||
|
|
||||||
AS_IF([test "x$with_sulogin" != "xno"], [
|
AS_IF([test "x$with_sulogin" != "xno"], [
|
||||||
@@ -284,6 +313,9 @@ AS_IF([test "x$with_watchdog" != "xno"], [
|
|||||||
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
||||||
watchdog=])
|
watchdog=])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_libsystemd" != "xno"], [
|
||||||
|
AC_DEFINE(HAVE_LIBSYSTEMD, 1, [Build replacement libsystemd library support])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_hook_scripts_plugin" != "xno"], [
|
AS_IF([test "x$enable_hook_scripts_plugin" != "xno"], [
|
||||||
AS_IF([test "x$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
AS_IF([test "x$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
||||||
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
||||||
@@ -300,6 +332,7 @@ AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
|||||||
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
||||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
||||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||||
|
AM_CONDITIONAL(LIBSYSTEMD, [test "x$with_libsystemd" != "xno"])
|
||||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
||||||
@@ -355,15 +388,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
|
||||||
@@ -373,6 +407,7 @@ Behavior:
|
|||||||
Boot heading..........: $heading
|
Boot heading..........: $heading
|
||||||
Plugins...............: $plugins
|
Plugins...............: $plugins
|
||||||
RTC restore date......: $RTC_DATE
|
RTC restore date......: $RTC_DATE
|
||||||
|
RTC fallback file.....: $rtc_file
|
||||||
|
|
||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
@@ -382,6 +417,10 @@ 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
|
||||||
|
Replacement libsystemd: $with_libsystemd
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4-3.6
|
HowTo: Finit on Alpine Linux 3.4...3.19
|
||||||
====================================
|
=======================================
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
||||||
|
|
||||||
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
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,
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/alpine/finit.d
|
docsdir := @docdir@/contrib/alpine/finit.d
|
||||||
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
||||||
keymap.conf modules.conf ntpd.conf \
|
keymap.conf modules.conf ntpd.conf syslogd.conf
|
||||||
klogd.conf syslogd.conf
|
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
docsdir := @docdir@/contrib/alpine/finit.d/available
|
docsdir := @docdir@/contrib/alpine/finit.d/available
|
||||||
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
||||||
lxdm.conf modules.conf ntpd.conf syslog.conf watchdog.conf
|
lxdm.conf modules.conf ntpd.conf syslogd.conf watchdog.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
#module evdev
|
#module evdev
|
||||||
#module mousedev
|
#module mousedev
|
||||||
#module 8139cp
|
#module 8139cp
|
||||||
module softdog
|
#module softdog
|
||||||
|
|||||||
+35
-29
@@ -1,45 +1,53 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ "x`id -u`" != "x0" ]; then
|
if [ "$(id -u)" != "0" ]; then
|
||||||
echo
|
printf "\n\e[1m*** This script must run as root\e[0m\n\n"
|
||||||
echo "*** This script must run as root"
|
|
||||||
echo
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC3037,SC3045,SC2154
|
||||||
|
yorn()
|
||||||
|
{
|
||||||
|
printf "\e[1m> %s (y/N)?\e[0m " "$*"
|
||||||
|
read -rn1 yorn
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ "$yorn" = "y" ] || [ "$yorn" = "Y" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
grep -q alpine Makefile 2>/dev/null
|
if grep -q contrib/alpine Makefile 2>/dev/null; then
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e configure.ac ]; then
|
fi
|
||||||
echo "*** Please run this script from the Finit base directory."
|
|
||||||
|
if [ ! -e configure.ac ]; then
|
||||||
|
printf "\n\e[1m*** Please run this script from the Finit base directory.\e[0m\n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
printf "\n\e[1mInstall Finit on Alpine Linux\n"
|
||||||
echo "*** Install Finit on Alpine Linux"
|
printf "========================================================================\e[0m\n"
|
||||||
echo "========================================================================"
|
printf "/sbin/finit - PID 1\n"
|
||||||
echo "/sbin/finit - PID 1"
|
printf "/lib/finit/plugins/* - All enabled Finit plugins\n"
|
||||||
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
printf "/etc/finit.conf - Finit configuration file\n"
|
||||||
echo "/etc/finit.conf - Finit configuration file"
|
printf "/etc/finit.d/ - Finit services\n"
|
||||||
echo "/etc/finit.d/ - Finit services"
|
|
||||||
echo
|
|
||||||
read -p "Do you want to continue (y/N)? " yorn
|
|
||||||
|
|
||||||
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
if yorn "Do you want to continue"; then
|
||||||
echo
|
printf "\n\e[1m*** Installing Finit files ...\e[0m\n"
|
||||||
echo "*** Installing Finit files ..."
|
|
||||||
make install
|
make install
|
||||||
cd /usr/share/doc/finit/contrib/alpine
|
cd /usr/share/doc/finit/contrib/alpine || exit 1
|
||||||
for file in finit.conf rc.local; do
|
for file in finit.conf rc.local; do
|
||||||
install -vbD $file /etc/$file
|
install -vbD $file /etc/$file
|
||||||
done
|
done
|
||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
read -p "*** Install Finit as the system default Init (y/N)? " yorn
|
if yorn "Install Finit as the system default Init"; then
|
||||||
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
printf "\e[1m*** Updating /sbin/init symlink --> finit ...\e[0m\n"
|
||||||
echo "*** Updating /sbin/init symlink --> finit ..."
|
cd /sbin || exit 1
|
||||||
cd /sbin
|
|
||||||
rm init
|
rm init
|
||||||
ln -s finit init
|
ln -s finit init
|
||||||
|
|
||||||
@@ -48,10 +56,8 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
|||||||
ln -s reboot shutdown
|
ln -s reboot shutdown
|
||||||
ln -s reboot suspend
|
ln -s reboot suspend
|
||||||
fi
|
fi
|
||||||
echo "*** Done"
|
printf "\n\e[1m*** Done\e[0m\n"
|
||||||
echo
|
echo
|
||||||
else
|
else
|
||||||
echo
|
printf "\n\e[1m*** Aborting install.\e[0m\n\n"
|
||||||
echo "*** Aborting install."
|
|
||||||
echo
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ tools pre-systemd work as intended.
|
|||||||
|
|
||||||
root@debian:~# apt install initscripts console-setup
|
root@debian:~# apt install initscripts console-setup
|
||||||
|
|
||||||
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
|
> [!TIP]
|
||||||
> the main section of Debian. So just install the -dev packages :)
|
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
||||||
|
> section of Debian. So just install the -dev packages :)
|
||||||
|
|
||||||
The following script can then be used to configure, build, install and
|
The following script can then be used to configure, build, install and
|
||||||
set up your system to run Finit:
|
set up your system to run Finit:
|
||||||
@@ -47,7 +48,8 @@ comands to `initctl`, followed by `reload` to activate your changes.
|
|||||||
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
||||||
and initialization like keyboard language etc.
|
and initialization like keyboard language etc.
|
||||||
|
|
||||||
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
> [!NOTE]
|
||||||
|
> For the X Window system, you may need to `sudo apt install elogind`
|
||||||
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
||||||
> is enabled by default), and logout/login again. The elogind daemon
|
> is enabled by default), and logout/login again. The elogind daemon
|
||||||
> ensures a regular non-root user can start and interact with an X
|
> ensures a regular non-root user can start and interact with an X
|
||||||
|
|||||||
+25
-19
@@ -1,5 +1,5 @@
|
|||||||
Building
|
Building Finit
|
||||||
========
|
==============
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Configure](#configure)
|
* [Configure](#configure)
|
||||||
@@ -17,14 +17,15 @@ optional plugins to enable. It depends on two external libraries:
|
|||||||
- [libuEv][], the event loop
|
- [libuEv][], the event loop
|
||||||
- [libite][] (-lite), much needed frog DNA
|
- [libite][] (-lite), much needed frog DNA
|
||||||
|
|
||||||
**NOTE:** Most free/open source software that uses `configure` default
|
> [!IMPORTANT]
|
||||||
to install to `/usr/local`. However, some Linux distributions do no
|
> Most free/open source software packages that use `configure` default
|
||||||
longer search that path for installed software, e.g. Fedora and Alpine
|
> to install to `/usr/local`. However, some Linux distributions do no
|
||||||
Linux. To get finit's configure script to find its dependencies you
|
> longer search that path for installed software, e.g. Fedora and Alpine
|
||||||
have to help the `pkg-config` tool a bit if you do not change the
|
> Linux. To get finit's configure script to find its dependencies you
|
||||||
default prefix path:
|
> have to help the `pkg-config` tool a bit if you do not change the
|
||||||
|
> default prefix path:
|
||||||
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
>
|
||||||
|
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||||
|
|
||||||
The configure script checks for all dependencies, including the correct
|
The configure script checks for all dependencies, including the correct
|
||||||
version of the above mentioned libraries. Currently required versions:
|
version of the above mentioned libraries. Currently required versions:
|
||||||
@@ -71,7 +72,8 @@ Below are a few of the main switches to configure:
|
|||||||
|
|
||||||
For more configure flags, see <kbd>./configure --help</kbd>
|
For more configure flags, see <kbd>./configure --help</kbd>
|
||||||
|
|
||||||
> **Note:** the configure script is not available in the GIT sources. It is
|
> [!NOTE]
|
||||||
|
> The configure script is not available in the GIT sources. It is
|
||||||
> however included in (officially supported) released tarballs. The
|
> however included in (officially supported) released tarballs. The
|
||||||
> idea is that you should not need GNU autotools to build, only the
|
> idea is that you should not need GNU autotools to build, only the
|
||||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||||
@@ -115,10 +117,11 @@ Linux config to:
|
|||||||
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||||
|
|
||||||
**Note:** If you run into problems starting Finit, take a look at
|
> [!TIP]
|
||||||
`finit.c`. One of the most common problems is a custom Linux kernel
|
> If you run into problems starting Finit, take a look at `finit.c`.
|
||||||
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
> One of the most common problems is a custom Linux kernel build that
|
||||||
system `/etc/fstab`.
|
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
||||||
|
> `/etc/fstab`.
|
||||||
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
@@ -157,8 +160,10 @@ enabled. The default Finit rescue mode configuration is installed into
|
|||||||
|
|
||||||
By default the a root shell, without login, is started.
|
By default the a root shell, without login, is started.
|
||||||
|
|
||||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
> [!IMPORTANT]
|
||||||
> force `reboot`, `shutdown`, or `poweroff`.
|
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
||||||
|
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
||||||
|
> versions of these commands. Use the `-f` flag to force the action.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -187,8 +192,9 @@ kernel usually reboots: `configure --enable-emergency-shell`. However,
|
|||||||
the behavior of Finit is severely limited when this is enabled, so use
|
the behavior of Finit is severely limited when this is enabled, so use
|
||||||
it only for debugging start up issues when Finit crashes.
|
it only for debugging start up issues when Finit crashes.
|
||||||
|
|
||||||
**NOTE:** Neither of these options should be enabled on production
|
> [!CAUTION]
|
||||||
systems since they can potentially give a user root access.
|
> None of these options should be enabled on production systems since
|
||||||
|
> they can potentially give a user root access.
|
||||||
|
|
||||||
|
|
||||||
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
||||||
|
|||||||
+6
-4
@@ -4,10 +4,11 @@ Tips & Tricks with the kernel cmdline
|
|||||||
This document summarizes the different boot parameters that can be
|
This document summarizes the different boot parameters that can be
|
||||||
passed on the Linux kernel command line. Not limited to Finit.
|
passed on the Linux kernel command line. Not limited to Finit.
|
||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
> [!IMPORTANT]
|
||||||
|
> Remember to use `--` to separate kernel parameters from parameters to
|
||||||
|
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||||
|
|
||||||
> **NOTE:** remember to use `--` to separate kernel parameters from
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
|
||||||
|
|
||||||
* `debug`: Enable kernel debug. Debug messages are printed to the
|
* `debug`: Enable kernel debug. Debug messages are printed to the
|
||||||
console until Finit starts up, unless `loglevel=7` (below) is used.
|
console until Finit starts up, unless `loglevel=7` (below) is used.
|
||||||
@@ -30,7 +31,8 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
Very useful for selecting different boot modes, e.g. manufacturing test,
|
||||||
firmware upgrade, or rescue mode.
|
firmware upgrade, or rescue mode.
|
||||||
|
|
||||||
> Note: `<boot/...>` conditions cannot be cleared with `initctl`!
|
> [!NOTE]
|
||||||
|
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||||
|
|
||||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
* `finit.config=/path/to/alternative/finit.conf`: override the
|
||||||
compile-time bootstrap config file, default:
|
compile-time bootstrap config file, default:
|
||||||
|
|||||||
+19
-11
@@ -47,9 +47,10 @@ both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
|||||||
`pid/` condition is satisfied by the corresponding service's PID file
|
`pid/` condition is satisfied by the corresponding service's PID file
|
||||||
being created, i.e., the service's default readiness notification.
|
being created, i.e., the service's default readiness notification.
|
||||||
|
|
||||||
**NOTE:** Conditions also stop services when a condition is no longer
|
> [!IMPORTANT]
|
||||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
> Conditions also stop services when a condition is no longer asserted.
|
||||||
will also stop or restart.
|
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
||||||
|
> stop or restart.
|
||||||
|
|
||||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||||
also see optional sourcing of arguments from an environment file:
|
also see optional sourcing of arguments from an environment file:
|
||||||
@@ -106,11 +107,16 @@ on this, see [Internals](#internals).) Thus, after a reconfiguration it
|
|||||||
is up to the "owner" of the condition to convey the new (or possibly
|
is up to the "owner" of the condition to convey the new (or possibly
|
||||||
unchanged) state of it.
|
unchanged) state of it.
|
||||||
|
|
||||||
> **Note:** For `pid/` conditions it is expected that services "touch"
|
|
||||||
> or recreate their PID file on `SIGHUP`.
|
|
||||||
|
|
||||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> For `pid/` conditions it is expected that the service reassert, i.e.,
|
||||||
|
> "touch" or recreate, their PID file on `SIGHUP`. This can be done by
|
||||||
|
> calling `utimensat()` on the PID file. Provided, of course, that the
|
||||||
|
> service supports reloading on `SIGHUP`, otherwise it will be restarted
|
||||||
|
> by Finit when they instead exit on the signal. For such services, use
|
||||||
|
> `<!>` to tell Finit the service does not support `SIGHUP`.
|
||||||
|
|
||||||
|
|
||||||
Built-in Conditions
|
Built-in Conditions
|
||||||
-------------------
|
-------------------
|
||||||
@@ -171,9 +177,10 @@ Built-in conditions:
|
|||||||
- `boot/arg`
|
- `boot/arg`
|
||||||
- `dev/node` and `dev/dir/node`
|
- `dev/node` and `dev/dir/node`
|
||||||
|
|
||||||
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
> [!NOTE]
|
||||||
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
difference is that `running` tells if the NIC has link.
|
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
|
> difference is that `running` tells if the NIC has link.
|
||||||
|
|
||||||
|
|
||||||
Composition
|
Composition
|
||||||
@@ -205,8 +212,9 @@ the service stanza for the daemon. It is far from optimal since any
|
|||||||
synchronization of depending services may fail due to the daemon not
|
synchronization of depending services may fail due to the daemon not
|
||||||
having reinitialized/created their IPC sockets, or similar.
|
having reinitialized/created their IPC sockets, or similar.
|
||||||
|
|
||||||
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
> [!NOTE]
|
||||||
> called 'svc' conditions, and they were far more complex.
|
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
||||||
|
> conditions, and they were far more complex.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
|
|||||||
+176
-111
@@ -18,8 +18,8 @@ Finit Configuration
|
|||||||
* [Alternate rcS.d/](#alternate-rcs-d-)
|
* [Alternate rcS.d/](#alternate-rcs-d-)
|
||||||
* [Resource Limits](#resource-limits)
|
* [Resource Limits](#resource-limits)
|
||||||
* [Runlevels](#runlevels)
|
* [Runlevels](#runlevels)
|
||||||
* [One-shot Commands (sequence)](#one-shot-commands--sequence-)
|
* [One-shot Commands (sequence)](#one-shot-commands-sequence)
|
||||||
* [One-shot Commands (parallel)](#one-shot-commands--parallel-)
|
* [One-shot Commands (parallel)](#one-shot-commands-parallel)
|
||||||
* [SysV Init Scripts](#sysv-init-scripts)
|
* [SysV Init Scripts](#sysv-init-scripts)
|
||||||
* [Services](#services)
|
* [Services](#services)
|
||||||
* [Run-parts Scripts](#run-parts-scripts)
|
* [Run-parts Scripts](#run-parts-scripts)
|
||||||
@@ -46,8 +46,9 @@ Plugins start at [hook points](plugins.md#hooks) and can run various set
|
|||||||
up, or install event handlers that later provide runtime services, e.g.,
|
up, or install event handlers that later provide runtime services, e.g.,
|
||||||
PID file monitoring, or [conditions](conditions.md).
|
PID file monitoring, or [conditions](conditions.md).
|
||||||
|
|
||||||
> **Tip:** see [SysV Init Compatibility](#sysv-init-compatibility) for
|
> [!TIP]
|
||||||
> help to quickly get going with an existing SysV or BusyBox init setup.
|
> See [SysV Init Compatibility](#sysv-init-compatibility) for help to
|
||||||
|
> quickly get going with an existing SysV or BusyBox init setup.
|
||||||
|
|
||||||
|
|
||||||
### Configuration Files
|
### Configuration Files
|
||||||
@@ -127,8 +128,9 @@ properties of the `run` statement. For an example on the relation of
|
|||||||
`service` and `run` statements, and dependency handling between them,
|
`service` and `run` statements, and dependency handling between them,
|
||||||
see [Conditional Loading](#conditional-loading), below.
|
see [Conditional Loading](#conditional-loading), below.
|
||||||
|
|
||||||
> **Note:** the `finit.conf` and `finit.d/` names are only defaults.
|
> [!NOTE]
|
||||||
> They can be changed at compile-time with two `configure` options:
|
> The names `finit.conf` and `finit.d/` are only defaults. They can be
|
||||||
|
> changed at compile-time with two `configure` options:
|
||||||
> `--with-config=/etc/foo.conf` and `--with-rcsd=/var/foo.d`.
|
> `--with-config=/etc/foo.conf` and `--with-rcsd=/var/foo.d`.
|
||||||
>
|
>
|
||||||
> They can also be overridden from the [kernel command line](cmdline.md)
|
> They can also be overridden from the [kernel command line](cmdline.md)
|
||||||
@@ -187,8 +189,9 @@ above, provided their respective mount point exists.
|
|||||||
|
|
||||||
With all filesystems mounted, Finit calls `swapon`.
|
With all filesystems mounted, Finit calls `swapon`.
|
||||||
|
|
||||||
> **Tip:** to see what happens when all filesystems are mounted, have a
|
> [!TIP]
|
||||||
> look at the [`bootmisc.so` plugin](plugins.md).
|
> To see what happens when all filesystems are mounted, have a look at
|
||||||
|
> the [`bootmisc.so` plugin](plugins.md).
|
||||||
|
|
||||||
At shutdown, and after having stopped all services and other lingering
|
At shutdown, and after having stopped all services and other lingering
|
||||||
processes have been killed, filesystems are unmounted in the reverse
|
processes have been killed, filesystems are unmounted in the reverse
|
||||||
@@ -198,6 +201,18 @@ order, and `swapoff` is called.
|
|||||||
|
|
||||||
### Runlevels
|
### Runlevels
|
||||||
|
|
||||||
|
Finit supports runlevels, but unlike other init systems runlevels are
|
||||||
|
declared per service/run/task/sysv command. When booting up a system
|
||||||
|
Finit pass through three phases:
|
||||||
|
|
||||||
|
1. Setting up the console, parsing any command line options, and other
|
||||||
|
housekeeping tasks like mounting all filesystems, and calling `fsck`
|
||||||
|
2. Starting all run/task/services in runlevel S, then waiting for all
|
||||||
|
services to have started, and all run/tasks to have completed
|
||||||
|
3. Go to runlevel 2, or whatever the user has set in the configuration
|
||||||
|
|
||||||
|
Available runlevels:
|
||||||
|
|
||||||
- ` S`: bootStrap
|
- ` S`: bootStrap
|
||||||
- ` 1`: Single user mode
|
- ` 1`: Single user mode
|
||||||
- `2-5`: traditional multi-user mode
|
- `2-5`: traditional multi-user mode
|
||||||
@@ -205,37 +220,40 @@ order, and `swapoff` is called.
|
|||||||
- `7-9`: multi-user mode (extra)
|
- `7-9`: multi-user mode (extra)
|
||||||
- ` 0`: shutdown
|
- ` 0`: shutdown
|
||||||
|
|
||||||
Runlevels are declared per service/run/task/sysv command. Starting in
|
Runlevel S (bootStrap), is for tasks supposed to run once at boot, and
|
||||||
runlevel S (bootStrap), usually only for tasks supposed to run once at
|
services like `syslogd`, which need to start early and run throughout
|
||||||
boot, and services like `syslogd`, which you need to start and run
|
the lifetime of your system.
|
||||||
throughout the whole time your system is up.
|
|
||||||
|
|
||||||
Before `S` is started, however, Finit performs a lot of housekeeping
|
Example:
|
||||||
tasks like mounting all filesystems, calling `fsck` if needed, and
|
|
||||||
making sure the everything is OK.
|
|
||||||
|
|
||||||
task [S] /lib/console-setup/console-setup.sh
|
task [S] /lib/console-setup/console-setup.sh
|
||||||
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
|
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
|
||||||
|
|
||||||
After runlevel S, Finit proceeds to runlevel 2. This can be changed in
|
When bootstrap has completed, Finit moves to runlevel 2. This can be
|
||||||
`/etc/finit.conf` using the `runlevel N` directive, or by a script
|
changed in `/etc/finit.conf` using the `runlevel N` directive, or by a
|
||||||
running in runlevel S that calls, e.g., `initctl runlevel 9`. The
|
script running in runlevel S that calls, e.g., `initctl runlevel 9`.
|
||||||
latter is useful if startup scripts detect problems outside of Finit's
|
The latter is useful if startup scripts detect problems outside of
|
||||||
control, e.g., critical services/devices missing or hardware problems.
|
Finit's control, e.g., critical services/devices missing or hardware
|
||||||
|
problems.
|
||||||
|
|
||||||
Before starting the services in runlevel 2, Finit first stops everything
|
Each runlevel must be allowed to "complete". Meaning, all services in
|
||||||
that is not allowed to run in 2, and then brings up networking.
|
runlevel S must have started and all run/tasks have been started and
|
||||||
Networking is expected to be available in all runlevels except: S, 1
|
collected (exited). Finit waits 120 seconds for all run/tasks in S to
|
||||||
(single user level), 6, and 0. Networking is enabled either by the
|
complete before proceeding to 2.
|
||||||
`network script` directive, or if you have an `/etc/network/interfaces`
|
|
||||||
file, Finit calls `ifup -a` -- at the very least the loopback interface
|
|
||||||
is brought up.
|
|
||||||
|
|
||||||
> **Note:** when moving from runlevel S to 2, all run/task/services that
|
Finit first stops everything that is not allowed to run in 2, and then
|
||||||
> were constrained to runlevel S only are dropped from bookkeeping. So
|
brings up networking. Networking is expected to be available in all
|
||||||
> when reaching the prompt, `initctl` will not show these run/tasks.
|
runlevels except: S, 1 (single user level), 6, and 0. Networking is
|
||||||
> This is a safety mechanism to prevent bootstrap-only tasks from
|
enabled either by the `network script` directive, or if you have an
|
||||||
> accidentally being run again. E.g., `console-setup.sh` above.
|
`/etc/network/interfaces` file, Finit calls `ifup -a` -- at the very
|
||||||
|
least the loopback interface is brought up.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> When moving from runlevel S to 2, all run/task/services that were
|
||||||
|
> constrained to runlevel S only are dropped from bookkeeping. So when
|
||||||
|
> reaching the prompt, `initctl` will not show these run/tasks. This is
|
||||||
|
> a safety mechanism to prevent bootstrap-only tasks from accidentally
|
||||||
|
> being run again. E.g., `console-setup.sh` above.
|
||||||
|
|
||||||
|
|
||||||
### Managing Services
|
### Managing Services
|
||||||
@@ -322,7 +340,8 @@ the `ps` command we can see that the process is started with:
|
|||||||
|
|
||||||
foo -n --extra-arg=bar -s -x
|
foo -n --extra-arg=bar -s -x
|
||||||
|
|
||||||
> **Note:** the leading `-` determines if Finit should treat a missing
|
> [!NOTE]
|
||||||
|
> The leading `-` in `env:` determines if Finit should treat a missing
|
||||||
> environment file as blocking the start of the service or not. When
|
> environment file as blocking the start of the service or not. When
|
||||||
> `-` is used, a missing environment file does *not* block the start.
|
> `-` is used, a missing environment file does *not* block the start.
|
||||||
|
|
||||||
@@ -374,7 +393,7 @@ like this:
|
|||||||
|
|
||||||
The `notify:none` syntax is for completeness in systems which run in
|
The `notify:none` syntax is for completeness in systems which run in
|
||||||
`readiness pid` mode (default). Services declared with `notify:none`
|
`readiness pid` mode (default). Services declared with `notify:none`
|
||||||
will assert ready condition as soon as Finit has started them, e.g.,
|
will transition to ready as soon as Finit has started them, e.g.,
|
||||||
`service/qux/ready`.
|
`service/qux/ready`.
|
||||||
|
|
||||||
To synchronize two services the following condition can be used:
|
To synchronize two services the following condition can be used:
|
||||||
@@ -384,22 +403,23 @@ To synchronize two services the following condition can be used:
|
|||||||
|
|
||||||
For details on the syntax and options, see below.
|
For details on the syntax and options, see below.
|
||||||
|
|
||||||
> **Note:** on `initctl reload` conditions are normally set in "flux",
|
> [!NOTE]
|
||||||
> while figuring out which to stop, start or restart. Services that
|
> On `initctl reload` conditions are set in "flux", while figuring out
|
||||||
> need to be restarted have their `ready` condition removed prior to
|
> which services to stop, start or restart. Services that need to be
|
||||||
> Finit sending them SIGHUP (if they support that), or stop-starting
|
> restarted have their `ready` condition removed before Finit issue a
|
||||||
> them. A daemon is expected to reassert its readiness, e.g. systemd
|
> SIGHUP (if they support that), or stop-starting them. A daemon is
|
||||||
> style daemons to write `READY=1\n`.
|
> expected to reassert its readiness, e.g. systemd style daemons to
|
||||||
|
> write `READY=1\n`.
|
||||||
>
|
>
|
||||||
> However, the s6 notify mode does not support this because in s6 you
|
> However, the s6 notify mode does not support this because in s6 you
|
||||||
> are expected to close your notify descriptor after having written
|
> are expected to close your notify descriptor after having written
|
||||||
> `\n`. This means s6 style daemons currently must be stop-started.
|
> `\n`. This means s6 style daemons currently must be stop-started.
|
||||||
> (Declare the service with `<!>` in its condition statement.)
|
> (Declare the service with `<!>` in its condition statement.)
|
||||||
>
|
>
|
||||||
> For native PID file style readiness notification a daemon is expected
|
> For default, PID file style readiness notification, daemons are
|
||||||
> to either create its PID file, if it does not exist yet, or touch it
|
> expected to either create their PID files, or touch it using
|
||||||
> using `utimensat()` or similar. This triggers both the `<pid/>` and
|
> `utimensat()` to reassert readiness. Triggering both the `<pid/>`
|
||||||
> `<.../ready>` conditions.
|
> and `<.../ready>` conditions.
|
||||||
|
|
||||||
|
|
||||||
Service Wrapper Scripts
|
Service Wrapper Scripts
|
||||||
@@ -429,9 +449,10 @@ example employs a wrapper script in `/etc/start.d`.
|
|||||||
# Execute the program
|
# Execute the program
|
||||||
exec /usr/bin/program $OPTIONS
|
exec /usr/bin/program $OPTIONS
|
||||||
|
|
||||||
> **Note:** the example sets `<!>` to denote that it doesn't support
|
> [!NOTE]
|
||||||
> `SIGHUP`. That way Finit will stop/start the service
|
> The example sets `<!>` to denote that it doesn't support `SIGHUP`.
|
||||||
> instead of sending SIGHUP at restart/reload events.
|
> That way Finit will stop/start the service instead of sending SIGHUP
|
||||||
|
> at restart/reload events.
|
||||||
|
|
||||||
|
|
||||||
Templating
|
Templating
|
||||||
@@ -459,7 +480,7 @@ Cgroups
|
|||||||
|
|
||||||
There are three major cgroup configuration directives:
|
There are three major cgroup configuration directives:
|
||||||
|
|
||||||
1. Global top-level group: init, system, user, or a custom group
|
1. Global top-level group: `init`, `system`, `user`, or a custom group
|
||||||
2. Selecting a top-level group for a set of run/task/services
|
2. Selecting a top-level group for a set of run/task/services
|
||||||
3. Per run/task/service limits
|
3. Per run/task/service limits
|
||||||
|
|
||||||
@@ -510,6 +531,11 @@ except for expanding the shorthand `mem.` to `memory.`, if the file is
|
|||||||
not available, either the cgroup controller is not available in your
|
not available, either the cgroup controller is not available in your
|
||||||
Linux kernel, or the name is misspelled.
|
Linux kernel, or the name is misspelled.
|
||||||
|
|
||||||
|
A daemon using `SCHED_RR` currently need to run outside the default cgroups.
|
||||||
|
|
||||||
|
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
> Linux cgroups and details surrounding values are not explained in the
|
> Linux cgroups and details surrounding values are not explained in the
|
||||||
> Finit documentation. The Linux admin-guide cover this well:
|
> Finit documentation. The Linux admin-guide cover this well:
|
||||||
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||||
@@ -535,12 +561,9 @@ service name:sysklogd [S123456789] \
|
|||||||
```
|
```
|
||||||
|
|
||||||
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
|
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
|
||||||
following directives:
|
following directives. Some directives have restrictions, e.g., only
|
||||||
|
available at bootstrap, runlevel `S`, see [Limitations](#limitations)
|
||||||
|
below for details.
|
||||||
> **Note:** not all directives are available in `/etc/finit.d/*.conf`
|
|
||||||
> and some directives are only available at bootstrap, runlevel `S`,
|
|
||||||
> see [Limitations](#limitations) below for details.
|
|
||||||
|
|
||||||
|
|
||||||
### Hostname
|
### Hostname
|
||||||
@@ -552,7 +575,8 @@ the contents of that file is used.
|
|||||||
|
|
||||||
Deprecated. We recommend using `/etc/hostname` instead.
|
Deprecated. We recommend using `/etc/hostname` instead.
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S (bootstrap).
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Kernel Modules
|
### Kernel Modules
|
||||||
@@ -570,7 +594,8 @@ BusyBox mdev tool, add to `/etc/mdev.conf`:
|
|||||||
|
|
||||||
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S (bootstrap).
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Networking
|
### Networking
|
||||||
@@ -583,7 +608,8 @@ Deprecated. We recommend using dedicated task/run stanzas per runlevel,
|
|||||||
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
|
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
|
||||||
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
|
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S (bootstrap).
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Alternate finit.d/
|
### Alternate finit.d/
|
||||||
@@ -604,8 +630,9 @@ another set of .conf files, e.g.:
|
|||||||
|
|
||||||
rcsd /etc/factory.d
|
rcsd /etc/factory.d
|
||||||
|
|
||||||
> **Note:** this directive is only available from the top-level
|
> [!NOTE]
|
||||||
> bootstrap .conf file.
|
> This directive is only available from the top-level bootstrap .conf
|
||||||
|
> file, usually `/etc/finit.conf`.
|
||||||
|
|
||||||
### Resource Limits
|
### Resource Limits
|
||||||
|
|
||||||
@@ -638,16 +665,18 @@ stanzas can share the same rlimits if they are in the same .conf.
|
|||||||
|
|
||||||
**Syntax:** `runlevel <N>`
|
**Syntax:** `runlevel <N>`
|
||||||
|
|
||||||
The system runlevel to go to after bootstrap (S) has completed. `N`
|
The system runlevel to go to after bootstrap (S) has completed. `N` is
|
||||||
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
|
the runlevel number 0-9, where 6 is reserved for reboot and 0 for halt.
|
||||||
halt.
|
Completed in this context means all services have been started and all
|
||||||
|
run/tasks have been started and collected.
|
||||||
|
|
||||||
It is recommended to keep runlevel 1 as single-user mode, because
|
It is recommended to keep runlevel 1 as single-user mode, because
|
||||||
Finit disables networking in this mode.
|
Finit disables networking in this mode.
|
||||||
|
|
||||||
*Default:* 2
|
*Default:* 2
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S (bootstrap).
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### One-shot Commands (sequence)
|
### One-shot Commands (sequence)
|
||||||
@@ -661,10 +690,11 @@ optional arguments and description. `run` commands are guaranteed to be
|
|||||||
completed before running the next command. Useful when serialization is
|
completed before running the next command. Useful when serialization is
|
||||||
required.
|
required.
|
||||||
|
|
||||||
> **Warning:** try to avoid the `run` command. It blocks much of the
|
> [!WARNING]
|
||||||
> functionality in Finit, like (re)starting other (perhaps crashing)
|
> Try to avoid the `run` command. It blocks much of the functionality
|
||||||
> services while a `run` task is executing. Use other synchronization
|
> in Finit, like (re)starting other (perhaps crashing) services while a
|
||||||
> mechanisms instead, like conditions.
|
> `run` task is executing. Use other synchronization mechanisms
|
||||||
|
> instead, like conditions.
|
||||||
|
|
||||||
Incomplete list of unsupported `initctl` commands in `run` tasks:
|
Incomplete list of unsupported `initctl` commands in `run` tasks:
|
||||||
|
|
||||||
@@ -704,7 +734,7 @@ non-trivial constructs are better placed in a separate shell script.
|
|||||||
|
|
||||||
Similar to `task` is the `sysv` stanza, which can be used to call SysV
|
Similar to `task` is the `sysv` stanza, which can be used to call SysV
|
||||||
style scripts. The primary intention for this command is to be able to
|
style scripts. The primary intention for this command is to be able to
|
||||||
re-use much of existing setup and init scripts in Linux distributions.
|
reuse much of existing setup and init scripts in Linux distributions.
|
||||||
|
|
||||||
When entering an allowed runlevel, Finit calls `init-script start`, when
|
When entering an allowed runlevel, Finit calls `init-script start`, when
|
||||||
entering a disallowed runlevel, Finit calls `init-script stop`, and if
|
entering a disallowed runlevel, Finit calls `init-script stop`, and if
|
||||||
@@ -719,7 +749,8 @@ file, but rather watch that file for the resulting forked-off PID. This
|
|||||||
syntax also works for forking daemons that do not have a command line
|
syntax also works for forking daemons that do not have a command line
|
||||||
option to run it in the foreground, more on this below in `service`.
|
option to run it in the foreground, more on this below in `service`.
|
||||||
|
|
||||||
> **Tip:** see also [SysV Init Compatibility](#sysv-init-compatibility).
|
> [!TIP]
|
||||||
|
> See also [SysV Init Compatibility](#sysv-init-compatibility).
|
||||||
|
|
||||||
|
|
||||||
### Services
|
### Services
|
||||||
@@ -727,13 +758,13 @@ option to run it in the foreground, more on this below in `service`.
|
|||||||
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
|
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
|
||||||
|
|
||||||
Service, or daemon, to be monitored and automatically restarted if it
|
Service, or daemon, to be monitored and automatically restarted if it
|
||||||
exits prematurely. Finit tries to restart services that die, by
|
exits prematurely. Finit tries to restart services that die, by default
|
||||||
default 10 times before giving up and marking them as *crashed*.
|
10 times before giving up and marking them as *crashed*. After which
|
||||||
After which they have to be manually restarted with `initctl restart
|
they have to be manually restarted with `initctl restart NAME`. The
|
||||||
NAME`. The limits controling this are configurable, see the options
|
limits controlling this are configurable, see the options below.
|
||||||
below.
|
|
||||||
|
|
||||||
> **Tip:** to allow endless restarts, see below option `respawn`
|
> [!TIP]
|
||||||
|
> To allow endless restarts, see below option `respawn`
|
||||||
|
|
||||||
For daemons that support it, we recommend appending `--foreground`,
|
For daemons that support it, we recommend appending `--foreground`,
|
||||||
`--no-background`, `-n`, `-F`, or similar command line argument to
|
`--no-background`, `-n`, `-F`, or similar command line argument to
|
||||||
@@ -882,37 +913,67 @@ configurable with the following options:
|
|||||||
endless restarts. Useful in many use-cases, but not what `service`
|
endless restarts. Useful in many use-cases, but not what `service`
|
||||||
was originally designed for so not the default behavior
|
was originally designed for so not the default behavior
|
||||||
* `oncrash:reboot` -- when all retries have failed, and the service
|
* `oncrash:reboot` -- when all retries have failed, and the service
|
||||||
has *crashed*, if this option is set the system is rebooted.
|
has *crashed*, if this option is set the system is rebooted
|
||||||
* `oncrash:script` -- similarly, but instead of rebooting, call the
|
* `oncrash:script` -- similarly, but instead of rebooting, call the
|
||||||
`post:script` action if set, see below.
|
`post:script` action with exit code `crashed`, see below
|
||||||
|
* `reload:script [args]` -- some services do not support `SIGHUP` but
|
||||||
|
may have other ways to update the configuration of a running daemon.
|
||||||
|
When `reload:script` is defined it is preferred over `SIGHUP`
|
||||||
|
* `stop:script [args]` -- some services may require alternate methods
|
||||||
|
to be stopped. When `stop:script` is defined it is preferred over
|
||||||
|
`SIGTERM` and `stop`, for `service` and `sysv` stanzas, respectively
|
||||||
|
|
||||||
When stopping a service (run/task/sysv/service), either manually or
|
> [!CAUTION]
|
||||||
when moving to another runlevel, Finit starts by sending `SIGTERM`, to
|
> Both `reload:script` and `stop:script` are called as PID 1, without
|
||||||
allow the process to shut down gracefully. If the process has not
|
> any timeout! Meaning, it is up to you to ensure the script is not
|
||||||
been collected within 3 seconds, Finit sends `SIGKILL`. To halt the
|
> blocking for seconds at a time or never terminates.
|
||||||
process using a different signal, use the option `halt:SIGNAL`, e.g.,
|
|
||||||
`halt:SIGPWR`. To change the delay between your halt signal and KILL,
|
|
||||||
use the option `kill:SEC`, e.g., `kill:10` to wait 10 seconds before
|
|
||||||
sending `SIGKILL`.
|
|
||||||
|
|
||||||
Services support `pre:script` and `post:script` actions as well. These
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
run as the same `@USER:GROUP` as the service itself, with any `env:file`
|
moving to another runlevel, Finit starts by sending `SIGTERM`, to allow
|
||||||
sourced. The scripts must use an absolute path, but are executed from
|
the process to shut down gracefully. However, if the process has not
|
||||||
the `$HOME` of the given user. The scripts are not called with any
|
been collected within 3 seconds, Finit will send `SIGKILL`. To stop the
|
||||||
argument (currently), but both get the `SERVICE_IDENT=foo` environment
|
process using a different signal than `SIGTERM`, use `halt:SIGNAL`,
|
||||||
variable set. Here `foo` denotes the identity of the service, which if
|
e.g., `halt:SIGPWR`. To change the delay between the stop signal and
|
||||||
there are multiple services named `foo`, may be `foo:1`, or any unique
|
KILL, use the option `kill:<1-60>`, e.g., `kill:10` to wait 10 seconds
|
||||||
identifier specified in the .conf file. The `post:script` is called
|
before sending `SIGKILL`.
|
||||||
with an additional set of environment variables:
|
|
||||||
|
|
||||||
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
|
Services, including the `sysv` variant, support pre/post/ready and
|
||||||
|
cleanup scripts:
|
||||||
|
|
||||||
|
* `pre:[0-3600,]script` -- called before the sysv/service is stated
|
||||||
|
* `post:[0-3600,]script` -- called after the sysv/service has stopped
|
||||||
|
* `ready:[0-3600,]script` -- called when the sysv/service is ready
|
||||||
|
* `cleanup:[0-3600,]script` -- called when run/task/sysv/service is removed
|
||||||
|
|
||||||
|
The optional number (0-3600) is the timeout before Finit kills the
|
||||||
|
script, it defaults to the kill delay value and can be disabled by
|
||||||
|
setting it to zero. These scripts run as the same `@USER:GROUP` as the
|
||||||
|
service itself, with any `env:file` sourced. The scripts are executed
|
||||||
|
from the `$HOME` of the given user. The scripts are not called with any
|
||||||
|
argument, but get a set of environment variables:
|
||||||
|
|
||||||
|
* `SERVICE_IDENT=foo:1`
|
||||||
|
* `SERVICE_NAME=foo`
|
||||||
|
* `SERVICE_ID=1`
|
||||||
|
|
||||||
|
The `post:script` is called with an additional set of environment
|
||||||
|
variables. Yes, the text is correct, the naming was an accident:
|
||||||
|
|
||||||
|
- `EXIT_CODE=[exited,signal,crashed]`: normal exit, signaled, or
|
||||||
|
crashed
|
||||||
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
||||||
the program, if it exited normally, or the signal name (`HUP`,
|
the program, if it exited normally, or the signal name (`HUP`,
|
||||||
`TERM`, etc.) if it exited due to signal
|
`TERM`, etc.) if it exited due to signal
|
||||||
|
|
||||||
These script actions *must terminate*, so they have a default execution
|
When a run/task/sys/service is removed (disable + reload) it is first
|
||||||
time of 3 seconds before they are SIGKILLed, this can be adjusted using
|
stopped and then removed from the runlevel. The `post:script` always
|
||||||
the above `kill:SEC` syntax.
|
runs when the process has stopped, and the `cleanup:script` runs when
|
||||||
|
the the stanza has been removed from the runlevel.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> These script actions are intended for setup, cleanup, and readiness
|
||||||
|
> notification. It is up to the user to ensure the scripts terminate.
|
||||||
|
|
||||||
|
|
||||||
#### Conditional Loading
|
#### Conditional Loading
|
||||||
|
|
||||||
@@ -1011,8 +1072,9 @@ before continuing. None of them can issue commands to start, stop, or
|
|||||||
restart other services. Also, ensure all your services and programs
|
restart other services. Also, ensure all your services and programs
|
||||||
either terminate or start in the background or you will block Finit.
|
either terminate or start in the background or you will block Finit.
|
||||||
|
|
||||||
> **Note:** `runparts` scrips are only read and executed in runlevel S.
|
> [!NOTE]
|
||||||
> See [hook scripts](plugins.md#hooks) for other ways to run scripts at
|
> `runparts` scripts are only read and executed in runlevel S. See
|
||||||
|
> [hook scripts](plugins.md#hooks) for other ways to run scripts at
|
||||||
> certain points during the complete lifetime of the system.
|
> certain points during the complete lifetime of the system.
|
||||||
|
|
||||||
**Recommendations:**
|
**Recommendations:**
|
||||||
@@ -1285,8 +1347,9 @@ This rescue mode can be disabled at configure time using:
|
|||||||
|
|
||||||
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
||||||
|
|
||||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
> [!NOTE]
|
||||||
> force `reboot`, `shutdown`, or `poweroff`.
|
> In this mode `initctl` will not work. Use the `-f` flag to force
|
||||||
|
> `reboot`, `shutdown`, or `poweroff`.
|
||||||
|
|
||||||
|
|
||||||
### Traditional
|
### Traditional
|
||||||
@@ -1298,11 +1361,12 @@ program is used instead. If a successful login is made, or if the user
|
|||||||
exits (Ctrl-D), the rescue mode is ended and the system boots up
|
exits (Ctrl-D), the rescue mode is ended and the system boots up
|
||||||
normally.
|
normally.
|
||||||
|
|
||||||
> **Note:** the bundled sulogin in Finit can at configure time be given
|
> [!WARNING]
|
||||||
> another user than the default (root). If the sulogin user does not
|
> The bundled sulogin in Finit can at configure time be given another
|
||||||
> have a password, or __the account is locked__, the user is presented
|
> user than the default (root). If the sulogin user does not have a
|
||||||
> with a password-less `"Press enter to enter maintenance mode."`,
|
> password, or __the account is locked__, the user is presented with a
|
||||||
> prompt which opens up a root shell.
|
> prompt: `"Press enter to enter maintenance mode."`, which will open
|
||||||
|
> up a root shell *without prompting for password*!
|
||||||
|
|
||||||
|
|
||||||
### Fallback
|
### Fallback
|
||||||
@@ -1350,10 +1414,11 @@ These can now also be set in any `.conf` file in `/etc/finit.d`.
|
|||||||
There is, however, nothing preventing you from having all configuration
|
There is, however, nothing preventing you from having all configuration
|
||||||
settings in `/etc/finit.conf`.
|
settings in `/etc/finit.conf`.
|
||||||
|
|
||||||
> **Note:** The `/etc/finit.d` directory was previously the default
|
> [!IMPORTANT]
|
||||||
> Finit [runparts](#run-parts-scripts) directory. Finit >=v4.0
|
> The default `rcsd`, i.e., `/etc/finit.d`, was previously the Finit
|
||||||
> no longer has a default `runparts` directory, make sure to
|
> [runparts](#run-parts-scripts) directory. Finit >=v4.0 no longer has
|
||||||
> update your setup, or the finit configuration, accordingly.
|
> a default `runparts` directory, make sure to update your setup, or the
|
||||||
|
> finit configuration, accordingly.
|
||||||
|
|
||||||
|
|
||||||
Watchdog
|
Watchdog
|
||||||
|
|||||||
+3
-2
@@ -34,8 +34,9 @@ build time:
|
|||||||
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** remember `--prefix` et al as well, the default is likely
|
> [!IMPORTANT]
|
||||||
> *not* what you want. See the [build docs][1] for details.
|
> Remember `--prefix` et al as well, the default is likely *not* what
|
||||||
|
> you want. See the [build docs][1] for details.
|
||||||
|
|
||||||
The resulting directory structure is depicted below. Please notice how
|
The resulting directory structure is depicted below. Please notice how
|
||||||
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
||||||
|
|||||||
+19
-14
@@ -35,9 +35,10 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
files distributed with Finit. It is read first but can be overridden
|
files distributed with Finit. It is read first but can be overridden
|
||||||
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
||||||
|
|
||||||
> **Note:** On an embedded system both `/var` and `/run` can be `tmpfs`
|
> [!NOTE]
|
||||||
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
||||||
> in the `/etc/fstab` file and in the Linux kernel config.
|
> disks and `/dev` is usually a `devtmpfs`. This must be defined in
|
||||||
|
> the `/etc/fstab` file and in the Linux kernel config.
|
||||||
|
|
||||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
@@ -63,6 +64,7 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
Enabled by default.
|
Enabled by default.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> See the [Services](config.md#services) section in the configuration
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
@@ -89,16 +91,17 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
set index 1234
|
set index 1234
|
||||||
|
|
||||||
**Note:** unlike the traditional .conf `module` directive, which load
|
Since these tasks run in the background, they return `[ OK ]` at boot,
|
||||||
any listed module immediately, this plugin creates a background `task`
|
unless the modprobe tool does not exist. Check syslog for warnings
|
||||||
which load the module(s) in the background. The program is modprobe,
|
and the actual status of the operation using `initctl`.
|
||||||
`/sbin/modprobe`, which you can override per .conf file:
|
|
||||||
|
|
||||||
set modprobe /path/to/maybe-a-modprobe-wrapper
|
> [!IMPORTANT]
|
||||||
|
> Unlike the traditional .conf `module` directive, which load any listed
|
||||||
Since these tasks run in the background, they usually return `[ OK ]`
|
> module immediately, this plugin creates a background `task` which load
|
||||||
at boot, unless the modprobe tool does not exist. Check syslog for
|
> the module(s) in the background. The program is modprobe,
|
||||||
warnings and the actual status of the operation using `initctl`.
|
> `/sbin/modprobe`, which you can override per .conf file:
|
||||||
|
>
|
||||||
|
> set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||||
|
|
||||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
||||||
interfaces. These events are then sent to the Finit service monitor
|
interfaces. These events are then sent to the Finit service monitor
|
||||||
@@ -158,8 +161,10 @@ hook points:
|
|||||||
EOF
|
EOF
|
||||||
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
||||||
|
|
||||||
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
|
> [!IMPORTANT]
|
||||||
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
|
> To use hook scripts, even for pre-bootstrap and pre-shutdown tasks,
|
||||||
|
> you must build with `configure --enable-hook-scripts-plugin`.
|
||||||
|
|
||||||
|
|
||||||
### Bootstrap Hooks
|
### Bootstrap Hooks
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -22,8 +22,9 @@ Finit can *not* start and monitor a daemon that:
|
|||||||
| ✔ | No | No | Yes, optionally |
|
| ✔ | No | No | Yes, optionally |
|
||||||
| ✘ | Yes | No | No |
|
| ✘ | Yes | No | No |
|
||||||
|
|
||||||
> **Note:** PID files is one mechanism used to assert conditions to
|
> [!NOTE]
|
||||||
> synchronize the start and stop of other, dependent, services.
|
> PID files is one mechanism used to assert conditions to synchronize
|
||||||
|
> the start and stop of other, dependent, services.
|
||||||
|
|
||||||
### Forks to Background w/ PID File
|
### Forks to Background w/ PID File
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 320 KiB |
+2
-2
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 814 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,7 @@
|
|||||||
|
.deps/*
|
||||||
|
.libs/*
|
||||||
|
.dirstamp
|
||||||
|
*.lo
|
||||||
|
libsystemd.*
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# libsystemd replacement library
|
||||||
|
lib_LTLIBRARIES = libsystemd.la
|
||||||
|
libsystemd_la_SOURCES = sd-daemon.c sd-daemon.h
|
||||||
|
libsystemd_la_LDFLAGS = -version-info 0:0:0
|
||||||
|
|
||||||
|
# pkg-config support
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = libsystemd.pc
|
||||||
|
|
||||||
|
# Install header to systemd/ subdirectory
|
||||||
|
systemddir = $(includedir)/systemd
|
||||||
|
systemd_HEADERS = sd-daemon.h
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libsystemd
|
||||||
|
Description: Finit replacement for systemd notification library
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Libs: -L${libdir} -lsystemd
|
||||||
|
Cflags: -I${includedir}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT-0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* systemd notify protocol, supporting readiness notification on startup
|
||||||
|
* and reloading, according to the protocol defined at:
|
||||||
|
* https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
||||||
|
*
|
||||||
|
* This protocol is guaranteed to be stable as per:
|
||||||
|
* https://systemd.io/PORTABILITY_AND_STABILITY/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "sd-daemon.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: As per spec., this function does not return POSIX OK(0) but
|
||||||
|
* rather "a positive value", i.e., 1.
|
||||||
|
*/
|
||||||
|
int sd_notify(int unset_environment, const char *state)
|
||||||
|
{
|
||||||
|
struct sockaddr_un sun = {
|
||||||
|
.sun_family = AF_UNIX,
|
||||||
|
};
|
||||||
|
size_t len, sun_len;
|
||||||
|
const char *path;
|
||||||
|
ssize_t written;
|
||||||
|
int sd;
|
||||||
|
|
||||||
|
if (!state)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len = strlen(state);
|
||||||
|
if (len == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* If the variable is not set, the protocol is a noop */
|
||||||
|
path = getenv("NOTIFY_SOCKET");
|
||||||
|
if (!path)
|
||||||
|
return 0; /* Not set? Nothing to do */
|
||||||
|
|
||||||
|
/* Only AF_UNIX is supported, with path or abstract sockets */
|
||||||
|
if (path[0] != '/' && path[0] != '@')
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
|
||||||
|
/* Ensure there is room for NUL byte */
|
||||||
|
sun_len = strlen(path);
|
||||||
|
if (sun_len >= sizeof(sun.sun_path))
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
|
||||||
|
if (sun.sun_path[0] == '@')
|
||||||
|
sun.sun_path[0] = 0;
|
||||||
|
|
||||||
|
sd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||||
|
if (sd == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (connect(sd, (struct sockaddr *)&sun, offsetof(struct sockaddr_un, sun_path) + sun_len) == -1) {
|
||||||
|
close(sd);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unset_environment)
|
||||||
|
unsetenv("NOTIFY_SOCKET");
|
||||||
|
|
||||||
|
written = write(sd, state, len);
|
||||||
|
if (written != (ssize_t) len) {
|
||||||
|
close(sd);
|
||||||
|
return written < 0 ? -errno : -EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Printf-style notification function
|
||||||
|
*/
|
||||||
|
int sd_notifyf(int unset_environment, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *state;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ret = vasprintf(&state, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = sd_notify(unset_environment, state);
|
||||||
|
free(state);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PID-specific notification function
|
||||||
|
*/
|
||||||
|
int sd_pid_notify(pid_t pid, int unset_environment, const char *state)
|
||||||
|
{
|
||||||
|
char path[256], *env;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!state)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len = strlen(state);
|
||||||
|
if (len == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
pid = getpid();
|
||||||
|
|
||||||
|
env = getenv("NOTIFY_SOCKET");
|
||||||
|
if (env) {
|
||||||
|
env = strdup(env);
|
||||||
|
if (!env)
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "@run/finit/notify/%d", pid);
|
||||||
|
setenv("NOTIFY_SOCKET", path, 1);
|
||||||
|
|
||||||
|
ret = sd_notify(unset_environment, state);
|
||||||
|
|
||||||
|
if (env) {
|
||||||
|
setenv("NOTIFY_SOCKET", env, 1);
|
||||||
|
free(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PID-specific printf-style notification function
|
||||||
|
*/
|
||||||
|
int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *state;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ret = vasprintf(&state, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = sd_pid_notify(pid, unset_environment, state);
|
||||||
|
free(state);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Socket activation stub - Finit doesn't support socket activation yet
|
||||||
|
* Returns 0 (no file descriptors passed)
|
||||||
|
*/
|
||||||
|
int sd_listen_fds(int unset_environment)
|
||||||
|
{
|
||||||
|
if (unset_environment) {
|
||||||
|
unsetenv("LISTEN_PID");
|
||||||
|
unsetenv("LISTEN_FDS");
|
||||||
|
unsetenv("LISTEN_FDNAMES");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Watchdog stub - Finit doesn't support watchdog yet
|
||||||
|
* Returns 0 (no watchdog enabled)
|
||||||
|
*/
|
||||||
|
int sd_watchdog_enabled(int unset_environment, uint64_t *usec)
|
||||||
|
{
|
||||||
|
if (unset_environment) {
|
||||||
|
unsetenv("WATCHDOG_PID");
|
||||||
|
unsetenv("WATCHDOG_USEC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usec)
|
||||||
|
*usec = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System detection function
|
||||||
|
* Returns 1 to indicate systemd compatibility (trick applications)
|
||||||
|
*/
|
||||||
|
int sd_booted(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef SD_DAEMON_H_
|
||||||
|
#define SD_DAEMON_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define SD_LISTEN_FDS_START 3
|
||||||
|
|
||||||
|
/* systemd logging defines for stderr parsing by Finit */
|
||||||
|
#define SD_EMERG "<0>" /* system is unusable */
|
||||||
|
#define SD_ALERT "<1>" /* action must be taken immediately */
|
||||||
|
#define SD_CRIT "<2>" /* critical conditions */
|
||||||
|
#define SD_ERR "<3>" /* error conditions */
|
||||||
|
#define SD_WARNING "<4>" /* warning conditions */
|
||||||
|
#define SD_NOTICE "<5>" /* normal but significant condition */
|
||||||
|
#define SD_INFO "<6>" /* informational */
|
||||||
|
#define SD_DEBUG "<7>" /* debug-level messages */
|
||||||
|
|
||||||
|
/* Basic notification function */
|
||||||
|
int sd_notify(int unset_environment, const char *state);
|
||||||
|
|
||||||
|
/* Printf-style notification functions */
|
||||||
|
int sd_notifyf(int unset_environment, const char *format, ...);
|
||||||
|
|
||||||
|
/* PID-specific notification functions */
|
||||||
|
int sd_pid_notify(pid_t pid, int unset_environment, const char *state);
|
||||||
|
int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...);
|
||||||
|
|
||||||
|
/* Socket activation stubs */
|
||||||
|
int sd_listen_fds(int unset_environment);
|
||||||
|
|
||||||
|
/* Watchdog stub */
|
||||||
|
int sd_watchdog_enabled(int unset_environment, uint64_t *usec);
|
||||||
|
|
||||||
|
/* System detection */
|
||||||
|
int sd_booted(void);
|
||||||
|
|
||||||
|
#endif /* SD_DAEMON_H_ */
|
||||||
+38
-24
@@ -175,12 +175,12 @@ task [s] echo "foo" | cat >/tmp/bar
|
|||||||
.Ed
|
.Ed
|
||||||
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
||||||
Similar to
|
Similar to
|
||||||
.Cm task
|
.Cm service
|
||||||
is the
|
is the
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
stanza, which can be used to call SysV style start/stop scripts. The
|
stanza, which can be used to call SysV style start/stop scripts. The
|
||||||
primary intention for this command is to be able to re-use much of
|
primary intention for this command is to be able to re-use traditional
|
||||||
existing setup and init scripts in Linux distributions.
|
SysV init scripts in Linux distributions.
|
||||||
.Pp
|
.Pp
|
||||||
When entering an allowed runlevel, Finit calls
|
When entering an allowed runlevel, Finit calls
|
||||||
.Cm init-script start ,
|
.Cm init-script start ,
|
||||||
@@ -434,30 +434,42 @@ e.g.,
|
|||||||
.Cm kill:10
|
.Cm kill:10
|
||||||
to wait 10 seconds before sending SIGKILL.
|
to wait 10 seconds before sending SIGKILL.
|
||||||
.Pp
|
.Pp
|
||||||
Services support the
|
Services, including the
|
||||||
.Cm pre:script
|
.Cm sysv
|
||||||
and
|
variant, support pre/post/ready and cleanup scripts:
|
||||||
.Cm post:script
|
.Bl -tag -width 1n
|
||||||
command actions as well. These run as the same
|
.It Cm pre:[0-3600,]script
|
||||||
|
called before the sysv/service is stated
|
||||||
|
.It Cm post:[0-3600,]script
|
||||||
|
called after the sysv/service has stopped
|
||||||
|
.It Cm ready:[0-3600,]script
|
||||||
|
called when the sysv/service is ready
|
||||||
|
.It Cm cleanup:[0-3600,]script
|
||||||
|
called when run/task/sysv/service is removed
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The optional number (0-3600) is the timeout before Finit kills the
|
||||||
|
script, it defaults to the kill delay value and can be disabled by
|
||||||
|
setting it to zero. These scripts run as the same
|
||||||
.Cm @USER:GROUP
|
.Cm @USER:GROUP
|
||||||
as the service itself, with any
|
as the service itself, with any
|
||||||
.Cm env:file
|
.Cm env:file
|
||||||
sourced. The scripts must use an absolute path, but are executed from
|
sourced. The scripts must use an absolute path, but are executed from
|
||||||
the
|
the
|
||||||
.Cm $HOME
|
.Cm $HOME
|
||||||
of the given user. The scripts are not called with any argument
|
of the given user. The scripts are not called with any argument, but
|
||||||
(currently), but both get the
|
both get a set of environment variables:
|
||||||
.Cm SERVICE_IDENT=foo
|
.Pp
|
||||||
environment variable set. Here
|
.Bl -tag -width 1n -compact
|
||||||
.Cm foo
|
.It Cm SERVICE_IDENT=foo:1
|
||||||
denotes the identity of the service, which if there are multiple
|
.It Cm SERVICE_NAME=foo
|
||||||
services named
|
.It Cm SERVICE_ID=1
|
||||||
.Cm foo ,
|
.El
|
||||||
may be
|
.Pp
|
||||||
.Cm foo:1 ,
|
The
|
||||||
or any unique identifier specified in the .conf file. The
|
|
||||||
.Cm post:script
|
.Cm post:script
|
||||||
is called with an additional set of environment variables:
|
is called with an additional set of environment variables, and yes the
|
||||||
|
naming looks like it should be swapped:
|
||||||
.Bl -tag -offset indent -width 1n
|
.Bl -tag -offset indent -width 1n
|
||||||
.It Cm EXIT_CODE=[exited,signal,crashed]
|
.It Cm EXIT_CODE=[exited,signal,crashed]
|
||||||
set to one of
|
set to one of
|
||||||
@@ -471,10 +483,12 @@ set to one of exit status code from the program, if it exited normally,
|
|||||||
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The scripts have a default execution time of 3 seconds before they are
|
When a run/task/sys/service is removed (disable + reload) it is first
|
||||||
SIGKILLed, this can be adjusted using the
|
stopped and then removed from the runlevel. The
|
||||||
.Cm kill:SEC
|
.Cm post:script
|
||||||
modifier syntax.
|
always runs when the process has stopped, and the
|
||||||
|
.Cm cleanup:script
|
||||||
|
runs when the the stanza has been removed from the runlevel.
|
||||||
.It Cm runparts Aq DIR
|
.It Cm runparts Aq DIR
|
||||||
Call
|
Call
|
||||||
.Xr run-parts 8
|
.Xr run-parts 8
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore ALSA sound settings using alsactl
|
/* Save and restore ALSA sound settings using alsactl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -65,12 +65,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "tmpfiles.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
|
||||||
@@ -163,7 +162,7 @@ static void setup(void *arg)
|
|||||||
kernel_links();
|
kernel_links();
|
||||||
|
|
||||||
/* Create all system tmpfiles.d(5) */
|
/* Create all system tmpfiles.d(5) */
|
||||||
tmpfilesd();
|
run_interactive(_PATH_TMPFILES " --create", "Creating required directories and files");
|
||||||
|
|
||||||
/* Set BOOT_TIME UTMP entry */
|
/* Set BOOT_TIME UTMP entry */
|
||||||
utmp_set_boot();
|
utmp_set_boot();
|
||||||
@@ -178,12 +177,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "pidfile" },
|
.depends = { "pidfile" },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and start system message bus, D-Bus
|
/* Setup and start system message bus, D-Bus
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -166,12 +166,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,12 +99,12 @@ static plugin_t plugin = {
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-6
@@ -1,6 +1,6 @@
|
|||||||
/* Coldplug modules using modalias magic
|
/* Coldplug modules using modalias magic
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -132,11 +132,10 @@ static FILE *maybe_fopen_alias(const char *file, const char *path)
|
|||||||
{
|
{
|
||||||
const char *basename;
|
const char *basename;
|
||||||
|
|
||||||
basename = rindex(path, '/');
|
basename = basenm(path);
|
||||||
if (!basename)
|
if (!strcmp(basename, path))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
basename++;
|
|
||||||
if (strcmp(file, basename))
|
if (strcmp(file, basename))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -233,12 +232,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", }
|
.depends = { "bootmisc", }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
*
|
*
|
||||||
* Please note, the :ID is there for your benefit, it ensures that tasks
|
* Please note, the :ID is there for your benefit, it ensures that tasks
|
||||||
* in Finit are unique. If you have two tasks with the same name and ID
|
* in Finit are unique. If you have two tasks with the same name and ID
|
||||||
* (or no ID), the last one read replaces any preceeding one!
|
* (or no ID), the last one read replaces any preceding one!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -216,12 +216,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -2,7 +2,7 @@
|
|||||||
/* Netlink plugin for IFUP/IFDN and GW events
|
/* Netlink plugin for IFUP/IFDN and GW events
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
||||||
* Copyright (C) 2009-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (C) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
|
#include "log.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
@@ -414,7 +415,7 @@ static plugin_t plugin = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
int sd;
|
int sd;
|
||||||
@@ -447,7 +448,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
close(plugin.io.fd);
|
close(plugin.io.fd);
|
||||||
|
|||||||
+34
-8
@@ -1,7 +1,7 @@
|
|||||||
/* Simple pidfile event monitor for the Finit condition engine
|
/* Simple pidfile event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -52,7 +52,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
|
|||||||
ptr = slash++;
|
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,33 @@ 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);
|
switch (svc->state) {
|
||||||
|
case SVC_TEARDOWN_STATE:
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
|
case SVC_SETUP_STATE:
|
||||||
|
/*
|
||||||
|
* E.g., a setup script for a container may run in lieu
|
||||||
|
* of crun, trying to fetch a container image from the
|
||||||
|
* network. This script may want to advertise its PID
|
||||||
|
* to the system for clean and swift reboots.
|
||||||
|
*/
|
||||||
|
dbg("%s[%d]: ignoring any PID file changes in CLEANUP/TEARDOWN/SETUP",
|
||||||
|
svc_ident(svc, NULL, 0), svc->pid);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
@@ -123,11 +148,12 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
if (svc->notify == SVC_NOTIFY_PID)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
cond_set(cond);
|
cond_set(cond);
|
||||||
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);
|
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);
|
service_ready(svc, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +268,7 @@ static void pidfile_reconf(void *arg)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (svc->notify == SVC_NOTIFY_PID)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
service_ready(svc);
|
service_ready(svc, 1);
|
||||||
|
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
if (cond_get(cond) == COND_ON)
|
if (cond_get(cond) == COND_ON)
|
||||||
@@ -312,7 +338,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "netlink" }, /* bootmisc depends on us */
|
.depends = { "netlink" }, /* bootmisc depends on us */
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -327,7 +353,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_pidfile);
|
iwatch_exit(&iw_pidfile);
|
||||||
|
|||||||
+10
-4
@@ -1,6 +1,6 @@
|
|||||||
/* Set kernel variables from /etc/sysctl.conf et al
|
/* Set kernel variables from /etc/sysctl.conf et al
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,6 +31,12 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifndef SYSCTL_PATH
|
||||||
|
#define SYSCTL_PATH "/sbin/sysctl"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
@@ -54,7 +60,7 @@ static void setup(void *arg)
|
|||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
char cmd[160];
|
char cmd[160];
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
snprintf(cmd, sizeof(cmd), "%s -e -p %s >/dev/null", SYSCTL_PATH, gl.gl_pathv[i]);
|
||||||
run(cmd, "sysctl");
|
run(cmd, "sysctl");
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
@@ -70,12 +76,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary files for resolvconf
|
/* Setup necessary files for resolvconf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -57,12 +57,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+187
-66
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore RTC using hwclock
|
/* Save and restore RTC using hwclock
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -35,9 +35,19 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "private.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/* Kernel RTC driver validates against this date for sanity check */
|
/*
|
||||||
|
* Kernel RTC driver validates against this date for sanity check. The
|
||||||
|
* on NTP sync the driver can also update the RTC every 11 mins. We use
|
||||||
|
* the same update interval to handle manual time set and file save.
|
||||||
|
*/
|
||||||
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
||||||
|
#define RTC_FMT "%Y-%m-%d %H:%M:%S"
|
||||||
|
#define RTC_PERIOD (11 * 60 * 1000)
|
||||||
|
|
||||||
#ifdef RTC_TIMESTAMP_CUSTOM
|
#ifdef RTC_TIMESTAMP_CUSTOM
|
||||||
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
||||||
#else
|
#else
|
||||||
@@ -45,6 +55,10 @@ static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
|||||||
#endif
|
#endif
|
||||||
static time_t rtc_date_fallback = 946684800LL;
|
static time_t rtc_date_fallback = 946684800LL;
|
||||||
|
|
||||||
|
static char *rtc_file = RTC_FILE;
|
||||||
|
static uev_t rtc_timer;
|
||||||
|
|
||||||
|
|
||||||
static void tz_set(char *tz, size_t len)
|
static void tz_set(char *tz, size_t len)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@@ -68,6 +82,125 @@ static void tz_restore(char *tz)
|
|||||||
tzset();
|
tzset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int time_set(struct tm *tm)
|
||||||
|
{
|
||||||
|
struct tm fallback = { 0 };
|
||||||
|
struct timeval tv = { 0 };
|
||||||
|
char tz[128];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
tz_set(tz, sizeof(tz));
|
||||||
|
|
||||||
|
if (!tm) {
|
||||||
|
logit(LOG_NOTICE, "Resetting system clock to kernel default, %s.", rtc_timestamp);
|
||||||
|
tm = &fallback;
|
||||||
|
|
||||||
|
/* Attempt to set RTC to a sane value ... */
|
||||||
|
tv.tv_sec = rtc_date_fallback;
|
||||||
|
if (!gmtime_r(&tv.tv_sec, tm)) {
|
||||||
|
rc = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tm->tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||||
|
tv.tv_sec = mktime(tm);
|
||||||
|
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = 2;
|
||||||
|
} else {
|
||||||
|
if (settimeofday(&tv, NULL) == -1)
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
tz_restore(tz);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int time_get(struct tm *tm)
|
||||||
|
{
|
||||||
|
struct timeval tv = { 0 };
|
||||||
|
char tz[128];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
tz_set(tz, sizeof(tz));
|
||||||
|
|
||||||
|
rc = gettimeofday(&tv, NULL);
|
||||||
|
if (rc < 0 || tv.tv_sec < rtc_date_fallback)
|
||||||
|
rc = 2;
|
||||||
|
else
|
||||||
|
gmtime_r(&tv.tv_sec, tm);
|
||||||
|
|
||||||
|
tz_restore(tz);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_save(void *arg)
|
||||||
|
{
|
||||||
|
struct tm tm = { 0 };
|
||||||
|
int rc = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!rtc_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fp = fopen(rtc_file, "w");
|
||||||
|
if (!fp) {
|
||||||
|
logit(LOG_WARNING, "Failed saving system clock to %s, code %d: %s",
|
||||||
|
rtc_file, errno, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = time_get(&tm))) {
|
||||||
|
logit(LOG_WARNING, "System clock invalid, before %s, not saving", rtc_timestamp);
|
||||||
|
print_desc(NULL, "System clock invalid, skipping");
|
||||||
|
} else {
|
||||||
|
char buf[32] = { 0 };
|
||||||
|
|
||||||
|
print_desc(NULL, "Saving system clock to file");
|
||||||
|
strftime(buf, sizeof(buf), RTC_FMT, &tm);
|
||||||
|
fprintf(fp, "%s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(rc, NULL);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void file_restore(void *arg)
|
||||||
|
{
|
||||||
|
struct tm tm = { 0 };
|
||||||
|
int rc = 1;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (!rtc_file) {
|
||||||
|
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_desc(NULL, "Restoring system clock from backup");
|
||||||
|
|
||||||
|
fp = fopen(rtc_file, "r");
|
||||||
|
if (fp) {
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
chomp(buf);
|
||||||
|
strptime(buf, RTC_FMT, &tm);
|
||||||
|
rc = time_set(&tm);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else
|
||||||
|
logit(LOG_WARNING, "Missing %s", rtc_file);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
time_set(NULL);
|
||||||
|
rc = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(rc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtc_open(void)
|
static int rtc_open(void)
|
||||||
{
|
{
|
||||||
char *alt[] = {
|
char *alt[] = {
|
||||||
@@ -91,10 +224,8 @@ static int rtc_open(void)
|
|||||||
|
|
||||||
static void rtc_save(void *arg)
|
static void rtc_save(void *arg)
|
||||||
{
|
{
|
||||||
struct timeval tv = { 0 };
|
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
char tz[128];
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
@@ -105,38 +236,26 @@ static void rtc_save(void *arg)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
if ((rc = time_get(&tm))) {
|
||||||
rc = gettimeofday(&tv, NULL);
|
|
||||||
if (rc < 0 || tv.tv_sec < rtc_date_fallback) {
|
|
||||||
print_desc(NULL, "System clock invalid, not saving to RTC");
|
print_desc(NULL, "System clock invalid, not saving to RTC");
|
||||||
invalid:
|
} else {
|
||||||
logit(LOG_ERR, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
print_desc(NULL, "Saving system clock (UTC) to RTC");
|
||||||
|
rc = ioctl(fd, RTC_SET_TIME, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc && errno == EINVAL) {
|
||||||
|
logit(LOG_WARNING, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
||||||
rc = 2;
|
rc = 2;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc(NULL, "Saving system time (UTC) to RTC");
|
|
||||||
|
|
||||||
gmtime_r(&tv.tv_sec, &tm);
|
|
||||||
if (ioctl(fd, RTC_SET_TIME, &tm) < 0) {
|
|
||||||
if (EINVAL == errno)
|
|
||||||
goto invalid;
|
|
||||||
rc = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
tz_restore(tz);
|
|
||||||
print(rc, NULL);
|
print(rc, NULL);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_restore(void *arg)
|
static void rtc_restore(void *arg)
|
||||||
{
|
{
|
||||||
struct timeval tv = { 0 };
|
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
char tz[128];
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
@@ -145,82 +264,84 @@ static void rtc_restore(void *arg)
|
|||||||
|
|
||||||
fd = rtc_open();
|
fd = rtc_open();
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
file_restore(arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
if ((rc = ioctl(fd, RTC_RD_TIME, &tm)) < 0) {
|
||||||
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
|
|
||||||
char msg[120];
|
char msg[120];
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
|
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
|
||||||
EINVAL == errno ? "RTC time is too old" :
|
EINVAL == errno ? "RTC time is too old" :
|
||||||
ENOENT == errno ? "RTC has no saved time" : "see log for details");
|
ENOENT == errno ? "RTC has no saved time" : "see log for details");
|
||||||
print_desc(NULL, msg);
|
print_desc(NULL, msg);
|
||||||
|
} else {
|
||||||
invalid:
|
|
||||||
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
|
||||||
if (EINVAL == errno)
|
|
||||||
logit(LOG_ERR, "RTC time is too old (before %s)", rtc_timestamp);
|
|
||||||
else if (ENOENT == errno)
|
|
||||||
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
|
|
||||||
else
|
|
||||||
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
|
|
||||||
|
|
||||||
/* Been here already? */
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Attempt to set RTC to a sane value ... */
|
|
||||||
tv.tv_sec = rtc_date_fallback;
|
|
||||||
if (!gmtime_r(&tv.tv_sec, &tm))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
logit(LOG_NOTICE, "Resetting RTC to kernel default, %s.", rtc_timestamp);
|
|
||||||
rc = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||||
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
rc = time_set(&tm);
|
||||||
tv.tv_sec = mktime(&tm);
|
|
||||||
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
|
||||||
errno = EINVAL;
|
|
||||||
goto invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settimeofday(&tv, NULL) == -1)
|
if (rc) {
|
||||||
rc = 1;
|
logit(LOG_WARNING, "Failed restoring system clock from RTC.");
|
||||||
|
if (EINVAL == errno)
|
||||||
|
logit(LOG_WARNING, "RTC time is too old (before %s)", rtc_timestamp);
|
||||||
|
else if (ENOENT == errno)
|
||||||
|
logit(LOG_WARNING, "RTC has no previously saved (valid) time.");
|
||||||
|
else
|
||||||
|
logit(LOG_WARNING, "RTC error code %d: %s", errno, strerror(errno));
|
||||||
|
|
||||||
|
print(2, NULL);
|
||||||
|
|
||||||
|
/* Try restoring from last save game */
|
||||||
|
if (rtc_file)
|
||||||
|
file_restore(arg);
|
||||||
|
} else
|
||||||
|
print(0, NULL);
|
||||||
|
|
||||||
out:
|
|
||||||
tz_restore(tz);
|
|
||||||
print(rc, NULL);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void save(void *arg)
|
||||||
|
{
|
||||||
|
rtc_save(arg);
|
||||||
|
file_save(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update(uev_t *w, void *arg, int events)
|
||||||
|
{
|
||||||
|
save(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.cb = rtc_restore
|
.cb = rtc_restore
|
||||||
},
|
},
|
||||||
.hook[HOOK_SHUTDOWN] = {
|
.hook[HOOK_SHUTDOWN] = {
|
||||||
.cb = rtc_save
|
.cb = save
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
|
|
||||||
if (!strptime(rtc_timestamp, "%Y-%m-%d %H:%M", &tm))
|
if (!strptime(rtc_timestamp, RTC_FMT, &tm)) {
|
||||||
rtc_date_fallback = mktime(&tm);
|
logit(LOG_WARNING, "Invalid restore date '%s', reverting to '%s'",
|
||||||
else
|
rtc_timestamp, RTC_TIMESTAMP_BEGIN_2000);
|
||||||
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
} else
|
||||||
|
rtc_date_fallback = mktime(&tm);
|
||||||
|
|
||||||
|
uev_timer_init(ctx, &rtc_timer, update, NULL, RTC_PERIOD, RTC_PERIOD);
|
||||||
|
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
|
uev_timer_stop(&rtc_timer);
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
/* System condition event monitor for the Finit condition engine
|
/* System condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -184,7 +184,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_sys);
|
iwatch_exit(&iw_sys);
|
||||||
|
|||||||
+4
-3
@@ -1,7 +1,7 @@
|
|||||||
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
||||||
* Copyright (c) 2013-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void tty_watcher(void *arg, int fd, int events);
|
static void tty_watcher(void *arg, int fd, int events);
|
||||||
|
|
||||||
@@ -108,13 +109,13 @@ static void tty_watcher(void *arg, int fd, int events)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
setup();
|
setup();
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
if (plugin.io.fd)
|
if (plugin.io.fd)
|
||||||
|
|||||||
+58
-14
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and save random seed at boot/shutdown
|
/* Setup and save random seed at boot/shutdown
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h> /* gettimeofday() */
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/resource.h> /* getrusage() */
|
||||||
#ifdef _LIBITE_LITE
|
#ifdef _LIBITE_LITE
|
||||||
# include <libite/lite.h>
|
# include <libite/lite.h>
|
||||||
#else
|
#else
|
||||||
@@ -37,16 +38,51 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef RANDOM_BYTES
|
#ifndef RANDOM_BYTES
|
||||||
#define RANDOM_BYTES (32*1024)
|
#define RANDOM_BYTES (32*1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RANDOMSEED
|
||||||
|
/*
|
||||||
|
* This is the fallback seed function, please make sure you have drivers
|
||||||
|
* enabling /dev/hwrng instead.
|
||||||
|
*/
|
||||||
|
static void fallback(FILE *fp)
|
||||||
|
{
|
||||||
|
unsigned long seed;
|
||||||
|
struct timeval tv;
|
||||||
|
struct rusage ru;
|
||||||
|
int iter = 128;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
getrusage(RUSAGE_SELF, &ru);
|
||||||
|
|
||||||
|
/* Mix multiple sources of "randomness" */
|
||||||
|
seed = tv.tv_sec ^ (tv.tv_usec << 16);
|
||||||
|
seed ^= ru.ru_utime.tv_sec ^ (ru.ru_utime.tv_usec << 16);
|
||||||
|
seed ^= ru.ru_stime.tv_sec ^ (ru.ru_stime.tv_usec << 16);
|
||||||
|
seed ^= getpid() << 8;
|
||||||
|
|
||||||
|
srandom(seed);
|
||||||
|
while (iter--) {
|
||||||
|
uint32_t i, prng = random();
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(prng); i++)
|
||||||
|
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
#ifdef RANDOMSEED
|
#ifdef RANDOMSEED
|
||||||
struct rand_pool_info *rpi;
|
struct rand_pool_info *rpi;
|
||||||
|
unsigned char *rpi_buf;
|
||||||
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 +91,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 +100,23 @@ 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 num;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(prng); i++)
|
num = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
||||||
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
if (num == 0)
|
||||||
|
fallback(fp);
|
||||||
|
else
|
||||||
|
fwrite(buf, sizeof(buf[0]), num, fp);
|
||||||
|
|
||||||
|
fclose(hw);
|
||||||
|
} else {
|
||||||
|
fallback(fp);
|
||||||
}
|
}
|
||||||
ret = fclose(fp);
|
ret = fclose(fp);
|
||||||
}
|
}
|
||||||
@@ -98,10 +141,11 @@ static void setup(void *arg)
|
|||||||
goto fallback;
|
goto fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpi_buf = (unsigned char *)rpi->buf;
|
||||||
do {
|
do {
|
||||||
ssize_t num;
|
ssize_t num;
|
||||||
|
|
||||||
num = read(fd, &rpi->buf[len], RANDOM_BYTES - len);
|
num = read(fd, &rpi_buf[len], RANDOM_BYTES - len);
|
||||||
if (num <= 0) {
|
if (num <= 0) {
|
||||||
if (num == -1 && errno == EINTR)
|
if (num == -1 && errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -130,7 +174,7 @@ static void setup(void *arg)
|
|||||||
close(fd);
|
close(fd);
|
||||||
free(rpi);
|
free(rpi);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
logit(LOG_ERR, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
logit(LOG_WARNING, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
||||||
print_result(rc < 0);
|
print_result(rc < 0);
|
||||||
return;
|
return;
|
||||||
fallback:
|
fallback:
|
||||||
@@ -164,12 +208,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", }
|
.depends = { "bootmisc", }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
/* User-defined condition event monitor for the Finit condition engine
|
/* User-defined condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -108,7 +108,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_usr);
|
iwatch_exit(&iw_usr);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Console setup (for X)
|
/* Console setup (for X)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
@@ -50,12 +52,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ logit
|
|||||||
reboot
|
reboot
|
||||||
runparts
|
runparts
|
||||||
sulogin
|
sulogin
|
||||||
|
tmpfiles
|
||||||
watchdogd
|
watchdogd
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
|
|||||||
+7
-2
@@ -8,7 +8,8 @@ AM_LDFLAGS = -export-dynamic
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sbin_PROGRAMS = finit initctl
|
sbin_PROGRAMS = finit initctl
|
||||||
pkglibexec_PROGRAMS = getty logit runparts
|
pkglibexec_PROGRAMS = getty logit runparts tmpfiles
|
||||||
|
|
||||||
if SULOGIN
|
if SULOGIN
|
||||||
pkglibexec_PROGRAMS += sulogin
|
pkglibexec_PROGRAMS += sulogin
|
||||||
endif
|
endif
|
||||||
@@ -43,6 +44,11 @@ sulogin_SOURCES = sulogin.c
|
|||||||
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
sulogin_LDADD = -lcrypt
|
sulogin_LDADD = -lcrypt
|
||||||
|
|
||||||
|
tmpfiles_SOURCES = tmpfiles.c util.c util.h log.h
|
||||||
|
tmpfiles_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
|
tmpfiles_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
||||||
|
tmpfiles_LDADD = $(lite_LIBS) $(uev_LIBS)
|
||||||
|
|
||||||
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)
|
||||||
@@ -66,7 +72,6 @@ finit_SOURCES = api.c cgroup.c cgroup.h \
|
|||||||
sig.c sig.h \
|
sig.c sig.h \
|
||||||
sm.c sm.h \
|
sm.c sm.h \
|
||||||
svc.c svc.h \
|
svc.c svc.h \
|
||||||
tmpfiles.c tmpfiles.h \
|
|
||||||
tty.c tty.h \
|
tty.c tty.h \
|
||||||
util.c util.h \
|
util.c util.h \
|
||||||
utmp-api.c utmp-api.h
|
utmp-api.c utmp-api.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "sm.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -59,6 +60,8 @@ static int call(int (*action)(svc_t *, void *), char *buf, size_t len)
|
|||||||
|
|
||||||
static int stop(svc_t *svc, void *user_data)
|
static int stop(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -72,6 +75,8 @@ static int stop(svc_t *svc, void *user_data)
|
|||||||
|
|
||||||
static int start(svc_t *svc, void *user_data)
|
static int start(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -105,6 +110,8 @@ static int restart(svc_t *svc, void *user_data)
|
|||||||
|
|
||||||
static int reload(svc_t *svc, void *user_data)
|
static int reload(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -149,6 +156,8 @@ static int missing(char *job, char *id, void *user_data)
|
|||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!job)
|
if (!job)
|
||||||
job = "";
|
job = "";
|
||||||
if (!id)
|
if (!id)
|
||||||
@@ -228,6 +237,8 @@ struct wq emergency = { .cb = bypass_shutdown };
|
|||||||
|
|
||||||
static void bypass_shutdown(void *unused)
|
static void bypass_shutdown(void *unused)
|
||||||
{
|
{
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
||||||
do_shutdown(halt);
|
do_shutdown(halt);
|
||||||
}
|
}
|
||||||
@@ -265,19 +276,19 @@ static int do_reboot(int cmd, int timeout, char *buf, size_t len)
|
|||||||
case INIT_CMD_REBOOT:
|
case INIT_CMD_REBOOT:
|
||||||
dbg("reboot");
|
dbg("reboot");
|
||||||
halt = SHUT_REBOOT;
|
halt = SHUT_REBOOT;
|
||||||
service_runlevel(6);
|
sm_runlevel(6);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
dbg("halt");
|
dbg("halt");
|
||||||
halt = SHUT_HALT;
|
halt = SHUT_HALT;
|
||||||
service_runlevel(0);
|
sm_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
dbg("poweroff");
|
dbg("poweroff");
|
||||||
halt = SHUT_OFF;
|
halt = SHUT_OFF;
|
||||||
service_runlevel(0);
|
sm_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_SUSPEND:
|
case INIT_CMD_SUSPEND:
|
||||||
@@ -306,7 +317,7 @@ typedef struct {
|
|||||||
} ev_t;
|
} ev_t;
|
||||||
|
|
||||||
ev_t ev_list[] = {
|
ev_t ev_list[] = {
|
||||||
{ "RELOAD", service_reload_dynamic },
|
{ "RELOAD", sm_reload },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -332,6 +343,19 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
int sd, lvl;
|
int sd, lvl;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): api socket %d invalid.", __func__, w->fd);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: refactor to use accept4() and a new uev handler for the
|
||||||
|
* client socket instead of risking blocking PID 1 if the client
|
||||||
|
* is misbehaving.
|
||||||
|
*/
|
||||||
|
// sd = accept4(w->fd, NULL, NULL, SOCK_NONBLOCK);
|
||||||
sd = accept(w->fd, NULL, NULL);
|
sd = accept(w->fd, NULL, NULL);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
err(1, "Failed serving API request");
|
err(1, "Failed serving API request");
|
||||||
@@ -377,7 +401,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:
|
||||||
@@ -412,7 +438,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
if (runlevel == INIT_LEVEL)
|
if (runlevel == INIT_LEVEL)
|
||||||
cfglevel = lvl;
|
cfglevel = lvl;
|
||||||
else
|
else
|
||||||
service_runlevel(lvl);
|
sm_runlevel(lvl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -428,7 +454,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
||||||
dbg("reload");
|
dbg("reload");
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_START_SVC:
|
case INIT_CMD_START_SVC:
|
||||||
@@ -546,20 +572,6 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel);
|
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_NOTIFY_SOCKET:
|
|
||||||
svc = svc_find_by_pid(rq.runlevel);
|
|
||||||
if (!svc) {
|
|
||||||
errx(1, "Unknown PID, cannot register notify socket");
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
|
|
||||||
err(1, "Falied initializing %s readiness notifier", svc_ident(svc, NULL, 0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return; /* Don't close sd, used for notify */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dbg("Unsupported cmd: %d", rq.cmd);
|
dbg("Unsupported cmd: %d", rq.cmd);
|
||||||
break;
|
break;
|
||||||
@@ -576,8 +588,6 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
close(sd);
|
close(sd);
|
||||||
if (UEV_ERROR == events)
|
|
||||||
goto error;
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
api_exit();
|
api_exit();
|
||||||
@@ -596,7 +606,7 @@ int api_init(uev_ctx_t *ctx)
|
|||||||
int sd;
|
int sd;
|
||||||
|
|
||||||
dbg("Setting up external API socket ...");
|
dbg("Setting up external API socket ...");
|
||||||
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||||
if (-1 == sd) {
|
if (-1 == sd) {
|
||||||
err(1, "Failed starting external API socket");
|
err(1, "Failed starting external API socket");
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+22
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "service.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -86,6 +88,12 @@ static void cgset(const char *path, char *ctrl, char *prop)
|
|||||||
}
|
}
|
||||||
*val++ = 0;
|
*val++ = 0;
|
||||||
|
|
||||||
|
/* unquote value, if quoted */
|
||||||
|
if (unquote(&val, NULL)) {
|
||||||
|
errx(1, "Syntax error, unterminated quote in %s/%s.%s=%s", path, ctrl, prop, val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* disallow sneaky relative paths */
|
/* disallow sneaky relative paths */
|
||||||
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
||||||
errx(1, "Possible security violation; '..' not allowed in cgroup config!");
|
errx(1, "Possible security violation; '..' not allowed in cgroup config!");
|
||||||
@@ -259,6 +267,12 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): inotify socket %d invalid.", __func__, w->fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
err(1, "invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
@@ -289,7 +303,7 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
#ifdef AUTO_RELOAD
|
#ifdef AUTO_RELOAD
|
||||||
if (conf_any_change())
|
if (conf_any_change())
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,10 +477,15 @@ 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.");
|
||||||
else if (errno == EPERM) /* Probably inside an unpriviliged container */
|
else if (errno == EPERM) /* Probably inside an unprivileged container */
|
||||||
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
|
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
|
||||||
else
|
else
|
||||||
err(1, "Failed mounting cgroup v2");
|
err(1, "Failed mounting cgroup v2");
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+64
-45
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -58,73 +58,90 @@ int cgroup_avail(void)
|
|||||||
return fismnt(FINIT_CGPATH);
|
return fismnt(FINIT_CGPATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pid_cmdline(int pid, char *buf, size_t len)
|
static size_t flen(FILE *fp)
|
||||||
{
|
{
|
||||||
size_t i, sz;
|
size_t total = 0, sz;
|
||||||
char *ptr;
|
char buf[512];
|
||||||
|
|
||||||
|
while ((sz = fread(buf, 1, sizeof(buf), fp)) > 0)
|
||||||
|
total += sz;
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pid_cmdline(int pid)
|
||||||
|
{
|
||||||
|
size_t i, len;
|
||||||
|
char *buf;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/cmdline", pid);
|
fp = fopenf("r", "/proc/%d/cmdline", pid);
|
||||||
if (!fp) {
|
if (!fp)
|
||||||
buf[0] = 0;
|
return strdup(""); /* regular process */
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
sz = fread(buf, sizeof(buf[0]), len - 1, fp);
|
len = flen(fp);
|
||||||
|
if (len == 0) {
|
||||||
|
fail:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (!sz)
|
|
||||||
return NULL; /* kernel thread */
|
return NULL; /* kernel thread */
|
||||||
|
|
||||||
buf[sz] = 0;
|
|
||||||
|
|
||||||
ptr = strchr(buf, 0);
|
|
||||||
if (ptr && ptr != buf) {
|
|
||||||
ptr++;
|
|
||||||
sz -= ptr - buf;
|
|
||||||
memmove(buf, ptr, sz + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sz; i++) {
|
buf = calloc(len + 1, 1);
|
||||||
if (buf[i] == 0)
|
if (!buf)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (fread(buf, 1, len, fp) < len) {
|
||||||
|
free(buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replace all NUL chars with space */
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (buf[i] == '\0')
|
||||||
buf[i] = ' ';
|
buf[i] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pid_comm(int pid, char *buf, size_t len)
|
char *pid_cgroup(int pid)
|
||||||
{
|
{
|
||||||
char *ptr = NULL;
|
char *buf, *ptr = NULL;
|
||||||
FILE *fp;
|
size_t len;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/comm", pid);
|
|
||||||
if (!fp)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (fgets(buf, len, fp))
|
|
||||||
ptr = chomp(buf);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *pid_cgroup(int pid, char *buf, size_t len)
|
|
||||||
{
|
|
||||||
char *ptr = NULL;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/cgroup", pid);
|
fp = fopenf("r", "/proc/%d/cgroup", pid);
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
len = flen(fp);
|
||||||
|
if (len == 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
|
||||||
|
buf = calloc(1, len);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (fgets(buf, len, fp))
|
if (fgets(buf, len, fp))
|
||||||
ptr = chomp(buf);
|
ptr = chomp(buf);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr) {
|
||||||
ptr = strchr(buf, '/');
|
ptr = strchr(ptr, '/');
|
||||||
|
if (ptr) {
|
||||||
|
memmove(buf, ptr, strlen(ptr) + 1);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ptr;
|
free(buf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *cgroup_val(char *path, char *file, char *buf, size_t len)
|
static char *cgroup_val(char *path, char *file, char *buf, size_t len)
|
||||||
@@ -423,7 +440,7 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
char comm[80] = { 0 };
|
char *cmdline;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = atoi(chomp(buf));
|
pid = atoi(chomp(buf));
|
||||||
@@ -431,8 +448,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip kernel threads for now (no cmdline) */
|
/* skip kernel threads for now (no cmdline) */
|
||||||
pid_comm(pid, comm, sizeof(comm));
|
cmdline = pid_cmdline(pid);
|
||||||
if (pid_cmdline(pid, buf, sizeof(buf))) {
|
if (cmdline) {
|
||||||
char proc[ttcols];
|
char proc[ttcols];
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@@ -450,7 +467,7 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
strlcat(row, pfx, rplen);
|
strlcat(row, pfx, rplen);
|
||||||
strlcat(row, ++i == num ? END : FORK, rlen);
|
strlcat(row, ++i == num ? END : FORK, rlen);
|
||||||
|
|
||||||
snprintf(proc, sizeof(proc), " %d %s %s", pid, comm, buf);
|
snprintf(proc, sizeof(proc), " %d %s", pid, cmdline);
|
||||||
|
|
||||||
if (plain) {
|
if (plain) {
|
||||||
strlcat(row, proc, rplen);
|
strlcat(row, proc, rplen);
|
||||||
@@ -468,6 +485,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
puts(row);
|
puts(row);
|
||||||
|
|
||||||
|
free(cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
|
|||||||
+3
-4
@@ -1,6 +1,6 @@
|
|||||||
/* Cgroup utility functions for initctl
|
/* Cgroup utility functions for initctl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -54,9 +54,8 @@ struct cg {
|
|||||||
|
|
||||||
int cgroup_avail(void);
|
int cgroup_avail(void);
|
||||||
|
|
||||||
char *pid_cmdline (int pid, char *buf, size_t len);
|
char *pid_cmdline (int pid);
|
||||||
char *pid_comm (int pid, char *buf, size_t len);
|
char *pid_cgroup (int pid);
|
||||||
char *pid_cgroup (int pid, char *buf, size_t len);
|
|
||||||
|
|
||||||
uint64_t cgroup_memory(char *group);
|
uint64_t cgroup_memory(char *group);
|
||||||
|
|
||||||
|
|||||||
+5
-13
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -95,19 +97,9 @@ int client_request(struct init_request *rq, ssize_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Exception, only command that don't need to wait for a
|
|
||||||
* response from Finit. Registers the client socket as a
|
|
||||||
* readiness notification socket with Finit
|
|
||||||
*/
|
|
||||||
if (rq->cmd == INIT_CMD_NOTIFY_SOCKET) {
|
|
||||||
rq->cmd = INIT_CMD_ACK;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+13
-4
@@ -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;
|
||||||
@@ -112,7 +113,7 @@ static void cond_boot_strap(void)
|
|||||||
*
|
*
|
||||||
* => 'pid/' + 'teamd' + '' = condition <pid/teamd>
|
* => 'pid/' + 'teamd' + '' = condition <pid/teamd>
|
||||||
*
|
*
|
||||||
* When you add a second aggrate you need to tell Finit it's a different
|
* When you add a second aggregate you need to tell Finit it's a different
|
||||||
* instance usugin the :ID syntax:
|
* instance usugin the :ID syntax:
|
||||||
*
|
*
|
||||||
* service :lag2 teamd -f /etc/teamd/lag2.conf -- Aggregate lag2
|
* service :lag2 teamd -f /etc/teamd/lag2.conf -- Aggregate lag2
|
||||||
@@ -201,6 +202,9 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
|
|||||||
{
|
{
|
||||||
const char *cond, *ptr;
|
const char *cond, *ptr;
|
||||||
|
|
||||||
|
(void)sb;
|
||||||
|
(void)tflag;
|
||||||
|
|
||||||
if (ftw->level == 0)
|
if (ftw->level == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -214,6 +218,9 @@ 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;
|
||||||
|
if (sm_in_reload())
|
||||||
|
cond_clear_noupdate(cond);
|
||||||
|
else
|
||||||
cond_update(cond);
|
cond_update(cond);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -284,7 +291,7 @@ int cond_update(const char *name)
|
|||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
int affects = 0;
|
int affects = 0;
|
||||||
|
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
||||||
continue;
|
continue;
|
||||||
@@ -317,7 +324,7 @@ int cond_set_noupdate(const char *name)
|
|||||||
|
|
||||||
void cond_set(const char *name)
|
void cond_set(const char *name)
|
||||||
{
|
{
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
if (cond_set_noupdate(name))
|
if (cond_set_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -368,7 +375,7 @@ int cond_clear_noupdate(const char *name)
|
|||||||
|
|
||||||
void cond_clear(const char *name)
|
void cond_clear(const char *name)
|
||||||
{
|
{
|
||||||
dbg("%s", name);
|
// dbg("%s", name);
|
||||||
if (cond_clear_noupdate(name))
|
if (cond_clear_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -386,6 +393,8 @@ static int do_assert(const char *fpath, const struct stat *sb, int tflg, struct
|
|||||||
{
|
{
|
||||||
char *nm;
|
char *nm;
|
||||||
|
|
||||||
|
(void)sb;
|
||||||
|
|
||||||
if (ftw->level == 0)
|
if (ftw->level == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -96,16 +96,16 @@ enum cond_state cond_get(const char *name)
|
|||||||
|
|
||||||
enum cond_state cond_get_agg(const char *names)
|
enum cond_state cond_get_agg(const char *names)
|
||||||
{
|
{
|
||||||
static char conds[MAX_COND_LEN];
|
|
||||||
enum cond_state s = COND_ON;
|
enum cond_state s = COND_ON;
|
||||||
char *cond;
|
|
||||||
|
|
||||||
if (!names)
|
if (names) {
|
||||||
return COND_ON;
|
char conds[strlen(names) + 1];
|
||||||
|
const char *cond;
|
||||||
|
|
||||||
strlcpy(conds, names, sizeof(conds));
|
strlcpy(conds, names, sizeof(conds));
|
||||||
for (cond = strtok(conds, ","); s && cond; cond = strtok(NULL, ","))
|
for (cond = strtok(conds, ","); s && cond; cond = strtok(NULL, ","))
|
||||||
s = min(s, cond_get(cond));
|
s = min(s, cond_get(cond));
|
||||||
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
+90
-30
@@ -1,6 +1,6 @@
|
|||||||
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -50,6 +50,25 @@
|
|||||||
|
|
||||||
#define BOOTSTRAP (runlevel == INIT_LEVEL)
|
#define BOOTSTRAP (runlevel == INIT_LEVEL)
|
||||||
|
|
||||||
|
int runlevel = INIT_LEVEL; /* Bootstrap 'S' */
|
||||||
|
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
|
||||||
|
int cmdlevel = 0; /* runlevel override from cmdline */
|
||||||
|
int prevlevel = -1;
|
||||||
|
int debug = 0; /* debug mode from kernel cmdline */
|
||||||
|
int rescue = 0; /* rescue mode from kernel cmdline */
|
||||||
|
int single = 0; /* single user mode from kernel cmdline */
|
||||||
|
int bootstrap = 1; /* set while bootstrapping (for TTYs) */
|
||||||
|
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
|
||||||
|
int syncsec = 0; /* reboot delay */
|
||||||
|
int readiness = SVC_NOTIFY_PID;
|
||||||
|
char *finit_conf= NULL;
|
||||||
|
char *finit_rcsd= NULL;
|
||||||
|
char *fstab = NULL;
|
||||||
|
char *sdown = NULL;
|
||||||
|
char *network = NULL;
|
||||||
|
char *hostname = NULL;
|
||||||
|
char *osheading = NULL;
|
||||||
|
|
||||||
int logfile_size_max = 200000; /* 200 kB */
|
int logfile_size_max = 200000; /* 200 kB */
|
||||||
int logfile_count_max = 5;
|
int logfile_count_max = 5;
|
||||||
|
|
||||||
@@ -348,8 +367,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");
|
||||||
@@ -487,14 +509,16 @@ void conf_save_service(int type, char *cfg, char *file)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Sets, and makes a note of, all KEY=VALUE lines in a given .conf line
|
* conf_parse_env - Parse a key=value line
|
||||||
* from finit.conf, or other .conf file. Note, PATH is always reset in
|
* @line: Line buffer without newline
|
||||||
* the conf_reset_env() function.
|
* @value: Whitespace trimmed value
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* %NULL on error, otherwise a whitespace trimmed key.
|
||||||
*/
|
*/
|
||||||
static void parse_env(char *line)
|
char *conf_parse_env(char *line, char **value)
|
||||||
{
|
{
|
||||||
struct env_entry *node;
|
|
||||||
char *key, *val, *end;
|
char *key, *val, *end;
|
||||||
|
|
||||||
/* skip any leading whitespace */
|
/* skip any leading whitespace */
|
||||||
@@ -516,7 +540,7 @@ static void parse_env(char *line)
|
|||||||
|
|
||||||
val = strchr(key, '=');
|
val = strchr(key, '=');
|
||||||
if (!val)
|
if (!val)
|
||||||
return;
|
return NULL;
|
||||||
*val++ = 0;
|
*val++ = 0;
|
||||||
|
|
||||||
/* strip leading whitespace from value */
|
/* strip leading whitespace from value */
|
||||||
@@ -524,14 +548,8 @@ static void parse_env(char *line)
|
|||||||
val++;
|
val++;
|
||||||
|
|
||||||
/* unquote value, if quoted */
|
/* unquote value, if quoted */
|
||||||
if (val[0] == '"' || val[0] == '\'') {
|
unquote(&val, end);
|
||||||
char q = val[0];
|
*value = val;
|
||||||
|
|
||||||
if (*end == q) {
|
|
||||||
val = &val[1];
|
|
||||||
*end = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find end of key */
|
/* find end of key */
|
||||||
end = key;
|
end = key;
|
||||||
@@ -558,18 +576,42 @@ static void parse_env(char *line)
|
|||||||
end++;
|
end++;
|
||||||
if (*end != 0) {
|
if (*end != 0) {
|
||||||
warnx("'%s=%s': not a valid identifier", key, val);
|
warnx("'%s=%s': not a valid identifier", key, val);
|
||||||
return; /* invalid key */
|
return NULL; /* invalid key */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets, and makes a note of, all KEY=VALUE lines in a given .conf line
|
||||||
|
* from finit.conf, or other .conf file. Note, PATH is always reset in
|
||||||
|
* the conf_reset_env() function.
|
||||||
|
*/
|
||||||
|
static void parse_env(char *line)
|
||||||
|
{
|
||||||
|
struct env_entry *node;
|
||||||
|
char *key, *val;
|
||||||
|
|
||||||
|
key = conf_parse_env(line, &val);
|
||||||
|
if (!key)
|
||||||
|
return;
|
||||||
|
|
||||||
dbg("Global env '%s'='%s'", key, val);
|
dbg("Global env '%s'='%s'", key, val);
|
||||||
setenv(key, val, 1);
|
setenv(key, val, 1);
|
||||||
|
|
||||||
node = malloc(sizeof(*node));
|
node = malloc(sizeof(*node));
|
||||||
if (!node) {
|
if (!node) {
|
||||||
|
nomem:
|
||||||
err(1, "Out of memory cannot track env vars");
|
err(1, "Out of memory cannot track env vars");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->name = strdup(key);
|
node->name = strdup(key);
|
||||||
|
if (!node->name) {
|
||||||
|
free(node);
|
||||||
|
goto nomem;
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_INSERT_HEAD(&env_list, node, link);
|
TAILQ_INSERT_HEAD(&env_list, node, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1311,7 +1353,7 @@ int conf_reload(void)
|
|||||||
if (strncmp(path, FINIT_SYSPATH_, strlen(FINIT_SYSPATH_)) &&
|
if (strncmp(path, FINIT_SYSPATH_, strlen(FINIT_SYSPATH_)) &&
|
||||||
strncmp(path, FINIT_RUNPATH_, strlen(FINIT_RUNPATH_)))
|
strncmp(path, FINIT_RUNPATH_, strlen(FINIT_RUNPATH_)))
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(basename(path), basename(gl.gl_pathv[j])))
|
if (strcmp(basenm(path), basenm(gl.gl_pathv[j])))
|
||||||
continue;
|
continue;
|
||||||
path = NULL; /* replacement later in list, skip this */
|
path = NULL; /* replacement later in list, skip this */
|
||||||
break;
|
break;
|
||||||
@@ -1429,15 +1471,21 @@ static int conf_change_act(char *dir, char *name, uint32_t mask)
|
|||||||
strlcpy(fn, dir, sizeof(fn));
|
strlcpy(fn, dir, sizeof(fn));
|
||||||
dbg("path: %s mask: %08x", fn, mask);
|
dbg("path: %s mask: %08x", fn, mask);
|
||||||
|
|
||||||
|
if (strchr(name, '@')) {
|
||||||
|
/* Skip realpath for templates */
|
||||||
|
rp = strdup(fn);
|
||||||
|
} else {
|
||||||
/* Handle disabling/removal of service */
|
/* Handle disabling/removal of service */
|
||||||
rp = realpath(fn, NULL);
|
rp = realpath(fn, NULL);
|
||||||
if (!rp) {
|
if (!rp) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
goto fail;
|
goto fail;
|
||||||
rp = strdup(fn);
|
rp = strdup(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!rp)
|
if (!rp)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
node = conf_find(rp);
|
node = conf_find(rp);
|
||||||
if (node) {
|
if (node) {
|
||||||
@@ -1477,7 +1525,11 @@ int conf_changed(char *file)
|
|||||||
if (!file)
|
if (!file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (strchr(file, '@'))
|
||||||
|
rp = strdup(file);
|
||||||
|
else
|
||||||
rp = realpath(file, NULL);
|
rp = realpath(file, NULL);
|
||||||
|
|
||||||
if (!rp)
|
if (!rp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1529,6 +1581,13 @@ static int conf_iwatch_read(int fd)
|
|||||||
|
|
||||||
static void conf_cb(uev_t *w, void *arg, int events)
|
static void conf_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): iwatch socket %d invalid.", __func__, w->fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (conf_iwatch_read(w->fd)) {
|
if (conf_iwatch_read(w->fd)) {
|
||||||
err(1, "invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
@@ -1537,7 +1596,7 @@ static void conf_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
#ifdef AUTO_RELOAD
|
#ifdef AUTO_RELOAD
|
||||||
if (conf_any_change())
|
if (conf_any_change())
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1561,25 +1620,26 @@ int conf_monitor(void)
|
|||||||
* have or not have symlinks in place. We need to monitor for
|
* have or not have symlinks in place. We need to monitor for
|
||||||
* changes to either symlink or target.
|
* changes to either symlink or target.
|
||||||
*/
|
*/
|
||||||
rc += iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
|
||||||
snprintf(path, sizeof(path), "%s/available/", finit_rcsd);
|
snprintf(path, sizeof(path), "%s/available/", finit_rcsd);
|
||||||
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
||||||
snprintf(path, sizeof(path), "%s/enabled/", finit_rcsd);
|
snprintf(path, sizeof(path), "%s/enabled/", finit_rcsd);
|
||||||
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
||||||
rc += iwatch_add(&iw_conf, finit_conf, 0);
|
rc |= iwatch_add(&iw_conf, finit_conf, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Systems with /etc/default, /etc/conf.d, or similar, can also
|
* Systems with /etc/default, /etc/conf.d, or similar, can also
|
||||||
* monitor changes in env files sourced by .conf files (above)
|
* monitor changes in env files sourced by .conf files (above)
|
||||||
* define your own with --with-sysconfig=/path/to/envfiles
|
* define your own with --with-sysconfig=/path/to/envfiles
|
||||||
*/
|
*/
|
||||||
rc += iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
|
||||||
rc += iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
|
||||||
#ifdef FINIT_SYSCONFIG
|
#ifdef FINIT_SYSCONFIG
|
||||||
rc += iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
|
||||||
#endif
|
#endif
|
||||||
|
rc |= conf_reload();
|
||||||
|
|
||||||
return rc + conf_reload();
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1617,7 +1677,7 @@ int conf_init(uev_ctx_t *ctx)
|
|||||||
* Start kernel event daemon as soon as possible, if enabled
|
* Start kernel event daemon as soon as possible, if enabled
|
||||||
*/
|
*/
|
||||||
if (whichp(FINIT_EXECPATH_ "/keventd"))
|
if (whichp(FINIT_EXECPATH_ "/keventd"))
|
||||||
conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init notify:none "
|
conf_save_service(SVC_TYPE_SERVICE, "[S12345789] cgroup.init notify:none "
|
||||||
FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf");
|
FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf");
|
||||||
|
|
||||||
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
|
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
|
||||||
|
|||||||
+20
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,6 +27,24 @@
|
|||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
|
extern int runlevel;
|
||||||
|
extern int cfglevel;
|
||||||
|
extern int cmdlevel;
|
||||||
|
extern int prevlevel;
|
||||||
|
extern int debug;
|
||||||
|
extern int rescue;
|
||||||
|
extern int single;
|
||||||
|
extern int bootstrap;
|
||||||
|
extern int kerndebug;
|
||||||
|
extern int syncsec;
|
||||||
|
extern int readiness;
|
||||||
|
extern char *fstab;
|
||||||
|
extern char *sdown;
|
||||||
|
extern char *network;
|
||||||
|
extern char *hostname;
|
||||||
|
extern char *runparts;
|
||||||
|
extern char *osheading;
|
||||||
|
|
||||||
extern int logfile_size_max;
|
extern int logfile_size_max;
|
||||||
extern int logfile_count_max;
|
extern int logfile_count_max;
|
||||||
|
|
||||||
@@ -47,6 +65,7 @@ void conf_saverc (void);
|
|||||||
void conf_save_exec_order (svc_t *svc, char *cmdline, int result);
|
void conf_save_exec_order (svc_t *svc, char *cmdline, int result);
|
||||||
void conf_save_service (int type, char *cfg, char *file);
|
void conf_save_service (int type, char *cfg, char *file);
|
||||||
void conf_parse_cmdline (int argc, char *argv[]);
|
void conf_parse_cmdline (int argc, char *argv[]);
|
||||||
|
char *conf_parse_env (char *line, char **val);
|
||||||
int conf_parse_runlevels (char *runlevels);
|
int conf_parse_runlevels (char *runlevels);
|
||||||
void conf_parse_cond (svc_t *svc, char *cond);
|
void conf_parse_cond (svc_t *svc, char *cond);
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -1,6 +1,6 @@
|
|||||||
/* Device node monitor for the Finit condition engine
|
/* Device node monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -77,7 +77,7 @@ void devmon_add_cond(const char *cond)
|
|||||||
struct dev_node *node;
|
struct dev_node *node;
|
||||||
|
|
||||||
if (!cond || strncmp(cond, "dev/", 4)) {
|
if (!cond || strncmp(cond, "dev/", 4)) {
|
||||||
dbg("no match");
|
// dbg("no match %s", cond ?: "<NIL>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +164,8 @@ static void devmon_scandir(struct iwatch *iw, char *dir, int len)
|
|||||||
size_t i;
|
size_t i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
(void)iw;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/*", dir);
|
snprintf(path, sizeof(path), "%s/*", dir);
|
||||||
rc = glob(path, GLOB_NOSORT, NULL, &gl);
|
rc = glob(path, GLOB_NOSORT, NULL, &gl);
|
||||||
if (rc && rc != GLOB_NOMATCH)
|
if (rc && rc != GLOB_NOMATCH)
|
||||||
@@ -207,6 +209,13 @@ static void devmon_cb(uev_t *w, void *arg, int events)
|
|||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
errx(1, "Unrecoverable error in devmon watcher");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
err(1, "invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Device node monitor for the Finit condition engine
|
/* Device node monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+15
-14
@@ -1,7 +1,7 @@
|
|||||||
/* Functions for exec'ing processes
|
/* Functions for exec'ing processes
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -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");
|
pp = popen(cmd, "r");
|
||||||
if (pp) {
|
if (!pp)
|
||||||
char buf[256];
|
_exit(EX_OSERR);
|
||||||
|
|
||||||
|
pfx = *log ? ": " : "";
|
||||||
while (fgets(buf, sizeof(buf), pp)) {
|
while (fgets(buf, sizeof(buf), pp)) {
|
||||||
chomp(buf);
|
chomp(buf);
|
||||||
logit(LOG_NOTICE, "%s%s%s", log, pfx, buf);
|
logit(LOG_NOTICE, "%s%s%s", log, pfx, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = pclose(pp);
|
rc = pclose(pp);
|
||||||
}
|
if (rc == -1)
|
||||||
}
|
_exit(EX_OSERR);
|
||||||
|
_exit(WEXITSTATUS(rc));
|
||||||
_exit(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)
|
||||||
@@ -198,7 +199,6 @@ int run(char *cmd, char *log)
|
|||||||
int run_interactive(char *cmd, char *fmt, ...)
|
int run_interactive(char *cmd, char *fmt, ...)
|
||||||
{
|
{
|
||||||
int status, oldout = 1, olderr = 2;
|
int status, oldout = 1, olderr = 2;
|
||||||
char line[LINE_SIZE];
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
@@ -243,6 +243,7 @@ int run_interactive(char *cmd, char *fmt, ...)
|
|||||||
|
|
||||||
/* Dump any results of cmd on stderr after we've printed [ OK ] or [FAIL] */
|
/* Dump any results of cmd on stderr after we've printed [ OK ] or [FAIL] */
|
||||||
if (fp && !debug) {
|
if (fp && !debug) {
|
||||||
|
char line[LINE_SIZE];
|
||||||
size_t len, written;
|
size_t len, written;
|
||||||
|
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
@@ -280,7 +281,7 @@ int exec_runtask(char *cmd, char *args[])
|
|||||||
return execvp(_PATH_BSHELL, argv);
|
return execvp(_PATH_BSHELL, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit rlimit[])
|
static void prepare_tty(char *tty, speed_t speed, const char *procname, struct rlimit rlimit[])
|
||||||
{
|
{
|
||||||
char name[80];
|
char name[80];
|
||||||
int fd, dummy;
|
int fd, dummy;
|
||||||
@@ -350,7 +351,7 @@ static int activate_console(int noclear, int nowait)
|
|||||||
dprint(STDERR_FILENO, clr, strlen(clr));
|
dprint(STDERR_FILENO, clr, strlen(clr));
|
||||||
dprint(STDERR_FILENO, msg, strlen(msg));
|
dprint(STDERR_FILENO, msg, strlen(msg));
|
||||||
while ((rc = read(STDIN_FILENO, &ch, 1)) > 0 && ch != '\r' && ch != '\n')
|
while ((rc = read(STDIN_FILENO, &ch, 1)) > 0 && ch != '\r' && ch != '\n')
|
||||||
continue;
|
;
|
||||||
|
|
||||||
/* On any error (likely EINTR), we avoid starting getty */
|
/* On any error (likely EINTR), we avoid starting getty */
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
|
|||||||
+33
-31
@@ -1,7 +1,7 @@
|
|||||||
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -59,25 +59,6 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
|
||||||
int runlevel = INIT_LEVEL; /* Bootstrap 'S' */
|
|
||||||
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
|
|
||||||
int cmdlevel = 0; /* runlevel override from cmdline */
|
|
||||||
int prevlevel = -1;
|
|
||||||
int debug = 0; /* debug mode from kernel cmdline */
|
|
||||||
int rescue = 0; /* rescue mode from kernel cmdline */
|
|
||||||
int single = 0; /* single user mode from kernel cmdline */
|
|
||||||
int bootstrap = 1; /* set while bootrapping (for TTYs) */
|
|
||||||
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
|
|
||||||
int syncsec = 0; /* reboot delay */
|
|
||||||
int readiness = SVC_NOTIFY_PID;
|
|
||||||
char *finit_conf= NULL;
|
|
||||||
char *finit_rcsd= NULL;
|
|
||||||
char *fstab = NULL;
|
|
||||||
char *sdown = NULL;
|
|
||||||
char *network = NULL;
|
|
||||||
char *hostname = NULL;
|
|
||||||
char *osheading = NULL;
|
|
||||||
|
|
||||||
uev_ctx_t *ctx = NULL; /* Main loop context */
|
uev_ctx_t *ctx = NULL; /* Main loop context */
|
||||||
svc_t *wdog = NULL; /* No watchdog by default */
|
svc_t *wdog = NULL; /* No watchdog by default */
|
||||||
|
|
||||||
@@ -87,14 +68,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 ...
|
||||||
@@ -264,10 +253,15 @@ static int fsck(int pass)
|
|||||||
* errors were corrected but that the boot may proceed.
|
* errors were corrected but that the boot may proceed.
|
||||||
*/
|
*/
|
||||||
if (fsck_rc > 1) {
|
if (fsck_rc > 1) {
|
||||||
|
if (hasmntopt(mnt,"nofail")) {
|
||||||
|
logit(LOG_CONSOLE | LOG_WARNING, "Ignoring failed fsck %s because of nofail option", dev);
|
||||||
|
fsck_rc = 0;
|
||||||
|
} else {
|
||||||
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
|
logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck %s, attempting sulogin ...", dev);
|
||||||
sulogin(1);
|
sulogin(1);
|
||||||
}
|
}
|
||||||
rc += fsck_rc;
|
}
|
||||||
|
rc |= fsck_rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
endmntent(fp);
|
endmntent(fp);
|
||||||
@@ -355,6 +349,8 @@ static void fs_remount_root(int fsckerr)
|
|||||||
*/
|
*/
|
||||||
static void fs_finalize(void)
|
static void fs_finalize(void)
|
||||||
{
|
{
|
||||||
|
int flags = MS_NOEXEC | MS_NOSUID;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some systems rely on us to both create /dev/shm and, to mount
|
* Some systems rely on us to both create /dev/shm and, to mount
|
||||||
* a tmpfs there. Any system with dbus needs shared memory, so
|
* a tmpfs there. Any system with dbus needs shared memory, so
|
||||||
@@ -362,8 +358,8 @@ static void fs_finalize(void)
|
|||||||
* the /etc/fstab file already.
|
* the /etc/fstab file already.
|
||||||
*/
|
*/
|
||||||
if (!fismnt("/dev/shm")) {
|
if (!fismnt("/dev/shm")) {
|
||||||
makedir("/dev/shm", 0777);
|
makedir("/dev/shm", 1777);
|
||||||
fs_mount("shm", "/dev/shm", "tmpfs", 0, "mode=0777");
|
fs_mount("shm", "/dev/shm", "tmpfs", flags | MS_NODEV, "mode=1777");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modern systems use /dev/pts */
|
/* Modern systems use /dev/pts */
|
||||||
@@ -381,7 +377,13 @@ static void fs_finalize(void)
|
|||||||
snprintf(opts, sizeof(opts), "gid=%d,mode=%d,ptmxmode=0666", gid, mode);
|
snprintf(opts, sizeof(opts), "gid=%d,mode=%d,ptmxmode=0666", gid, mode);
|
||||||
|
|
||||||
makedir("/dev/pts", 0755);
|
makedir("/dev/pts", 0755);
|
||||||
fs_mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC, opts);
|
fs_mount("devpts", "/dev/pts", "devpts", flags, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Needed on systems like Alpine Linux */
|
||||||
|
if (!fismnt("/dev/mqueue")) {
|
||||||
|
makedir("/dev/mqueue", 1777);
|
||||||
|
fs_mount("mqueue", "/dev/mqueue", "tmpfs", flags | MS_NODEV, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -393,7 +395,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 */
|
||||||
@@ -402,7 +404,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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,8 +726,8 @@ int main(int argc, char *argv[])
|
|||||||
* Initialize state machine and start all bootstrap tasks
|
* Initialize state machine and start all bootstrap tasks
|
||||||
* NOTE: no network available!
|
* NOTE: no network available!
|
||||||
*/
|
*/
|
||||||
sm_init(&sm);
|
sm_init();
|
||||||
sm_step(&sm);
|
sm_step();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enter main loop to monitor /dev/initctl and services
|
* Enter main loop to monitor /dev/initctl and services
|
||||||
|
|||||||
+7
-21
@@ -1,7 +1,7 @@
|
|||||||
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -54,11 +54,17 @@
|
|||||||
#define FINIT_CGPATH "/sys/fs/cgroup"
|
#define FINIT_CGPATH "/sys/fs/cgroup"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Prevent users from logging in at critical stages */
|
||||||
|
#ifndef FINIT_NOLOGIN_PATH
|
||||||
|
#define FINIT_NOLOGIN_PATH _PATH_NOLOGIN
|
||||||
|
#endif
|
||||||
|
|
||||||
/* To use these, include config.h, or define FINIT_EXECPATH_ */
|
/* To use these, include config.h, or define FINIT_EXECPATH_ */
|
||||||
#define _PATH_LOGIT FINIT_EXECPATH_ "/logit"
|
#define _PATH_LOGIT FINIT_EXECPATH_ "/logit"
|
||||||
#define _PATH_RUNPARTS FINIT_EXECPATH_ "/runparts"
|
#define _PATH_RUNPARTS FINIT_EXECPATH_ "/runparts"
|
||||||
#define _PATH_SULOGIN FINIT_EXECPATH_ "/sulogin"
|
#define _PATH_SULOGIN FINIT_EXECPATH_ "/sulogin"
|
||||||
#define _PATH_GETTY FINIT_EXECPATH_ "/getty"
|
#define _PATH_GETTY FINIT_EXECPATH_ "/getty"
|
||||||
|
#define _PATH_TMPFILES FINIT_EXECPATH_ "/tmpfiles"
|
||||||
|
|
||||||
#define CMD_SIZE 1024
|
#define CMD_SIZE 1024
|
||||||
#define LINE_SIZE 1024
|
#define LINE_SIZE 1024
|
||||||
@@ -98,7 +104,6 @@
|
|||||||
#define INIT_CMD_SVC_FIND 131
|
#define INIT_CMD_SVC_FIND 131
|
||||||
#define INIT_CMD_SVC_FIND_BYC 132
|
#define INIT_CMD_SVC_FIND_BYC 132
|
||||||
#define INIT_CMD_SIGNAL 133
|
#define INIT_CMD_SIGNAL 133
|
||||||
#define INIT_CMD_NOTIFY_SOCKET 200 /* For readiness notification socket */
|
|
||||||
#define INIT_CMD_NACK 254
|
#define INIT_CMD_NACK 254
|
||||||
#define INIT_CMD_ACK 255
|
#define INIT_CMD_ACK 255
|
||||||
|
|
||||||
@@ -111,25 +116,6 @@ struct init_request {
|
|||||||
char data[368];
|
char data[368];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int runlevel;
|
|
||||||
extern int cfglevel;
|
|
||||||
extern int cmdlevel;
|
|
||||||
extern int prevlevel;
|
|
||||||
extern int debug;
|
|
||||||
extern int rescue;
|
|
||||||
extern int single;
|
|
||||||
extern int bootstrap;
|
|
||||||
extern int kerndebug;
|
|
||||||
extern int syncsec;
|
|
||||||
extern int readiness;
|
|
||||||
extern char *fstab;
|
|
||||||
extern char *sdown;
|
|
||||||
extern char *network;
|
|
||||||
extern char *hostname;
|
|
||||||
extern char *runparts;
|
|
||||||
extern char *osheading;
|
|
||||||
extern uev_ctx_t *ctx;
|
|
||||||
|
|
||||||
#endif /* FINIT_H_ */
|
#endif /* FINIT_H_ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+6
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Initialize and serve a login terminal
|
/* Initialize and serve a login terminal
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -121,6 +121,9 @@ static int osrel(struct osrel *rel)
|
|||||||
snprintf(rel->version, sizeof(rel->version), "(%s)", codename);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,9 +312,9 @@ static int exec_login(char *name)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (passenv)
|
if (passenv)
|
||||||
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", name, NULL);
|
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", "--", name, NULL);
|
||||||
else
|
else
|
||||||
execl(_PATH_LOGIN, _PATH_LOGIN, name, NULL);
|
execl(_PATH_LOGIN, _PATH_LOGIN, "--", name, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Failed to exec login, should not happen on normal systems.
|
* Failed to exec login, should not happen on normal systems.
|
||||||
|
|||||||
+16
-102
@@ -1,7 +1,7 @@
|
|||||||
/* Misc. utility functions for finit and its plugins
|
/* Misc. utility functions for finit and its plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
|
|
||||||
#include <ctype.h> /* isblank() */
|
#include <ctype.h> /* isblank() */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <grp.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -42,6 +40,7 @@
|
|||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "conf.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
@@ -87,6 +86,9 @@ void console_init(void)
|
|||||||
/* Enable line wrap, if disabled previously, e.g., qemu */
|
/* Enable line wrap, if disabled previously, e.g., qemu */
|
||||||
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
||||||
|
|
||||||
|
/* Reset attributes, background and foreground color */
|
||||||
|
dprint(STDOUT_FILENO, "\033[49m\033[39m\e[2J", 14);
|
||||||
|
|
||||||
log_init();
|
log_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,6 +292,8 @@ static size_t print_timestamp(char *buf, size_t len)
|
|||||||
sscanf(buf, "%f %f", &stamp, &dummy);
|
sscanf(buf, "%f %f", &stamp, &dummy);
|
||||||
return snprintf(buf, len, "[ %.6f ]", stamp);
|
return snprintf(buf, len, "[ %.6f ]", stamp);
|
||||||
#else
|
#else
|
||||||
|
(void)buf;
|
||||||
|
(void)len;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -367,98 +371,6 @@ int print_result(int fail)
|
|||||||
return fail;
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getuser(char *username, char **home)
|
|
||||||
{
|
|
||||||
#ifdef ENABLE_STATIC
|
|
||||||
if (home)
|
|
||||||
*home = "/"; /* XXX: Fixme */
|
|
||||||
return fgetint("/etc/passwd", "x:\n", username);
|
|
||||||
#else
|
|
||||||
struct passwd *usr;
|
|
||||||
|
|
||||||
if (!username || (usr = getpwnam(username)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (home)
|
|
||||||
*home = usr->pw_dir;
|
|
||||||
return usr->pw_uid;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int getgroup(char *group)
|
|
||||||
{
|
|
||||||
#ifdef ENABLE_STATIC
|
|
||||||
return fgetint("/etc/group", "x:\n", group);
|
|
||||||
#else
|
|
||||||
struct group *grp;
|
|
||||||
|
|
||||||
if ((grp = getgrnam(group)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return grp->gr_gid;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get current user */
|
|
||||||
int getcuser(char *buf, size_t len)
|
|
||||||
{
|
|
||||||
char *ptr = "root";
|
|
||||||
|
|
||||||
#ifndef ENABLE_STATIC
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
|
||||||
|
|
||||||
if (pw)
|
|
||||||
ptr = pw->pw_name;
|
|
||||||
#endif
|
|
||||||
if (strlcpy(buf, ptr, len) > len)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get current group */
|
|
||||||
int getcgroup(char *buf, size_t len)
|
|
||||||
{
|
|
||||||
char *ptr = "root";
|
|
||||||
|
|
||||||
#ifndef ENABLE_STATIC
|
|
||||||
struct group *gr = getgrgid(getgid());
|
|
||||||
|
|
||||||
if (gr)
|
|
||||||
ptr = gr->gr_name;
|
|
||||||
#endif
|
|
||||||
if (strlcpy(buf, ptr, len) > len)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mksubsys(const char *dir, mode_t mode, char *user, char *group)
|
|
||||||
{
|
|
||||||
mode_t omask;
|
|
||||||
int uid, gid;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
omask = umask(0);
|
|
||||||
|
|
||||||
uid = getuser(user, NULL);
|
|
||||||
if (uid >= 0) {
|
|
||||||
gid = getgroup(group);
|
|
||||||
if (gid < 0)
|
|
||||||
gid = 0;
|
|
||||||
|
|
||||||
rc = makedir(dir, mode);
|
|
||||||
if (rc && errno == EEXIST)
|
|
||||||
rc = chmod(dir, mode);
|
|
||||||
if (chown(dir, uid, gid))
|
|
||||||
err(1, "Failed chown(%s, %d, %d)", dir, uid, gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
umask(omask);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_hostname(char **hostname)
|
void set_hostname(char **hostname)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@@ -522,9 +434,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 +452,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 ...",
|
||||||
@@ -581,7 +494,8 @@ int in_container(void)
|
|||||||
"lxc",
|
"lxc",
|
||||||
"docker",
|
"docker",
|
||||||
"kubepod",
|
"kubepod",
|
||||||
"unshare"
|
"unshare",
|
||||||
|
"systemd-nspawn"
|
||||||
};
|
};
|
||||||
const char *files[] = {
|
const char *files[] = {
|
||||||
"/run/.containerenv",
|
"/run/.containerenv",
|
||||||
|
|||||||
+3
-62
@@ -1,7 +1,7 @@
|
|||||||
/* Misc. utility functions and C-library extensions for finit and its plugins
|
/* Misc. utility functions and C-library extensions for finit and its plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -39,7 +39,6 @@
|
|||||||
#else
|
#else
|
||||||
# include <lite/lite.h>
|
# include <lite/lite.h>
|
||||||
#endif
|
#endif
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#define PROGRESS_DEFAULT PROGRESS_MODERN
|
#define PROGRESS_DEFAULT PROGRESS_MODERN
|
||||||
|
|
||||||
@@ -70,14 +69,6 @@ void print (int action, const char *fmt, ...) __attribute__ ((forma
|
|||||||
void print_desc (char *action, char *desc);
|
void print_desc (char *action, char *desc);
|
||||||
int print_result (int fail);
|
int print_result (int fail);
|
||||||
|
|
||||||
int getuser (char *username, char **home);
|
|
||||||
int getgroup (char *group);
|
|
||||||
|
|
||||||
int getcuser (char *buf, size_t len);
|
|
||||||
int getcgroup (char *buf, size_t len);
|
|
||||||
|
|
||||||
int mksubsys (const char *dir, mode_t mode, char *user, char *group);
|
|
||||||
|
|
||||||
void set_hostname (char **hostname);
|
void set_hostname (char **hostname);
|
||||||
void networking (int updown);
|
void networking (int updown);
|
||||||
int in_container (void);
|
int in_container (void);
|
||||||
@@ -91,56 +82,6 @@ pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimi
|
|||||||
pid_t run_bg (char *cmd, char *args[]);
|
pid_t run_bg (char *cmd, char *args[]);
|
||||||
int run_parts (char *dir, char *cmd, const char *env[], int progress, int sysv);
|
int run_parts (char *dir, char *cmd, const char *env[], int progress, int sysv);
|
||||||
|
|
||||||
/*
|
|
||||||
* Defaults to user "root" and group "wheel" (root) if:
|
|
||||||
* 1) the user is missing
|
|
||||||
* 2) the group or the file /etc/group is missing
|
|
||||||
*/
|
|
||||||
static inline int create(char *path, mode_t mode, char *user, char *group)
|
|
||||||
{
|
|
||||||
int fd, uid, gid;
|
|
||||||
|
|
||||||
if (!path) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uid = getuser(user, NULL);
|
|
||||||
if (uid < 0)
|
|
||||||
uid = 0;
|
|
||||||
gid = getgroup(group);
|
|
||||||
if (gid < 0)
|
|
||||||
gid = 0;
|
|
||||||
|
|
||||||
fd = creat(path, mode);
|
|
||||||
if (fd == -1) {
|
|
||||||
warn("Failed creating %s properly", path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
if (chown(path, uid, gid)) {
|
|
||||||
warn("Failed chowning %s properly", path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ln(const char *target, const char *linkpath)
|
|
||||||
{
|
|
||||||
if (!target || !linkpath) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symlink(target, linkpath)) {
|
|
||||||
if (errno != EEXIST)
|
|
||||||
warn("Failed creating %s -> %s symlink", target, linkpath);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline int dprint(int fd, const char *s, size_t len)
|
static inline int dprint(int fd, const char *s, size_t len)
|
||||||
{
|
{
|
||||||
size_t loop = 3;
|
size_t loop = 3;
|
||||||
@@ -159,7 +100,7 @@ static inline int dprint(int fd, const char *s, size_t len)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *fgetval(char *line, const char *key, char *sep)
|
static inline char *fgetval(const char *line, const char *key, char *sep)
|
||||||
{
|
{
|
||||||
char *ptr, *str, *copy;
|
char *ptr, *str, *copy;
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -179,7 +120,7 @@ static inline char *fgetval(char *line, const char *key, char *sep)
|
|||||||
* Check if we should strip optional separator, e.g.,
|
* Check if we should strip optional separator, e.g.,
|
||||||
* 'foo = bar' => '= bar' should be stripped to 'bar'
|
* 'foo = bar' => '= bar' should be stripped to 'bar'
|
||||||
*/
|
*/
|
||||||
while (str && strchr(sep, str[0])) {
|
while (strchr(sep, str[0])) {
|
||||||
ptr = strsep(&str, sep);
|
ptr = strsep(&str, sep);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
+19
-20
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -767,27 +767,25 @@ static int plugins_list(char *arg)
|
|||||||
*/
|
*/
|
||||||
char *runlevel_string(int currlevel, int levels)
|
char *runlevel_string(int currlevel, int levels)
|
||||||
{
|
{
|
||||||
static char lvl[21];
|
static char lvl[32];
|
||||||
int i = INIT_LEVEL;
|
int i = INIT_LEVEL;
|
||||||
int pos = 1;
|
|
||||||
|
|
||||||
memset(lvl, 0, sizeof(lvl));
|
strlcpy(lvl, "[", sizeof(lvl));
|
||||||
lvl[0] = '[';
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (ISSET(levels, i)) {
|
if (ISSET(levels, i)) {
|
||||||
if (!plain && currlevel == i)
|
char l[2] = { '0' + i, 0 };
|
||||||
pos = strlcat(lvl, "\e[1m", sizeof(lvl));
|
|
||||||
|
|
||||||
if (i == INIT_LEVEL)
|
|
||||||
lvl[pos++] = 'S';
|
|
||||||
else
|
|
||||||
lvl[pos++] = '0' + i;
|
|
||||||
|
|
||||||
if (!plain && currlevel == i)
|
if (!plain && currlevel == i)
|
||||||
pos = strlcat(lvl, "\e[0m", sizeof(lvl));
|
strlcat(lvl, "\e[1m", sizeof(lvl));
|
||||||
|
|
||||||
|
strlcat(lvl, i == INIT_LEVEL ? "S" : l, sizeof(lvl));
|
||||||
|
|
||||||
|
|
||||||
|
if (!plain && currlevel == i)
|
||||||
|
strlcat(lvl, "\e[0m", sizeof(lvl));
|
||||||
} else {
|
} else {
|
||||||
lvl[pos++] = '-';
|
strlcat(lvl, "-", sizeof(lvl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: ugly hack to get order right: S0123456789 */
|
/* XXX: ugly hack to get order right: S0123456789 */
|
||||||
@@ -798,8 +796,7 @@ char *runlevel_string(int currlevel, int levels)
|
|||||||
} while (i < INIT_LEVEL);
|
} while (i < INIT_LEVEL);
|
||||||
|
|
||||||
|
|
||||||
lvl[pos++] = ']';
|
strlcat(lvl, "]", sizeof(lvl));
|
||||||
lvl[pos] = 0;
|
|
||||||
|
|
||||||
return lvl;
|
return lvl;
|
||||||
}
|
}
|
||||||
@@ -872,7 +869,7 @@ static char *svc_environ(svc_t *svc, char *buf, size_t len, int ansi)
|
|||||||
{
|
{
|
||||||
int bold = missing(svc);
|
int bold = missing(svc);
|
||||||
|
|
||||||
if (!ansi || svc_checkenv(svc) || svc->env[0] == '-')
|
if (!ansi || svc_checkenv(svc))
|
||||||
bold = 0;
|
bold = 0;
|
||||||
|
|
||||||
strlcpy(buf, bold ? "\e[1m" : "", len);
|
strlcpy(buf, bold ? "\e[1m" : "", len);
|
||||||
@@ -1138,14 +1135,14 @@ static int show_status(char *arg)
|
|||||||
printf(" Restarts : %d (%d/%d)\n", svc->restart_tot, svc->restart_cnt, svc->restart_max);
|
printf(" Restarts : %d (%d/%d)\n", svc->restart_tot, svc->restart_cnt, svc->restart_max);
|
||||||
printf(" Runlevels : %s\n", runlevel_string(runlevel, svc->runlevels));
|
printf(" Runlevels : %s\n", runlevel_string(runlevel, svc->runlevels));
|
||||||
if (cgrp && svc->pid > 1) {
|
if (cgrp && svc->pid > 1) {
|
||||||
char grbuf[128];
|
const struct cg *cg;
|
||||||
char path[256];
|
char path[256];
|
||||||
struct cg *cg;
|
|
||||||
char *group;
|
char *group;
|
||||||
|
|
||||||
group = pid_cgroup(svc->pid, grbuf, sizeof(grbuf));
|
group = pid_cgroup(svc->pid);
|
||||||
if (!group)
|
if (!group)
|
||||||
goto no_cgroup; /* ... or PID doesn't exist (anymore) */
|
goto no_cgroup; /* ... or PID doesn't exist (anymore) */
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", FINIT_CGPATH, group);
|
snprintf(path, sizeof(path), "%s/%s", FINIT_CGPATH, group);
|
||||||
cg = cg_conf(path);
|
cg = cg_conf(path);
|
||||||
|
|
||||||
@@ -1154,6 +1151,8 @@ static int show_status(char *arg)
|
|||||||
group, cg->cg_cpu.set, cg->cg_cpu.weight, cg->cg_cpu.max,
|
group, cg->cg_cpu.set, cg->cg_cpu.weight, cg->cg_cpu.max,
|
||||||
cg->cg_mem.min, cg->cg_mem.max);
|
cg->cg_mem.min, cg->cg_mem.max);
|
||||||
show_cgroup_tree(group, " ");
|
show_cgroup_tree(group, " ");
|
||||||
|
|
||||||
|
free(group);
|
||||||
}
|
}
|
||||||
no_cgroup:
|
no_cgroup:
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+7
-1
@@ -1,7 +1,7 @@
|
|||||||
/* inotify watcher for files or directories
|
/* inotify watcher for files or directories
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -96,6 +96,12 @@ int iwatch_add1(struct iwatch *iw, char *file, uint32_t mask)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
iwp = iwatch_find_by_path(iw, file);
|
||||||
|
if (iwp) {
|
||||||
|
dbg("skipping, %s already registered", file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fexist(file)) {
|
if (!fexist(file)) {
|
||||||
dbg("skipping %s: no such file or directory", file);
|
dbg("skipping %s: no such file or directory", file);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/* inotify watcher for files or directories
|
/* inotify watcher for files or directories
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Listens to kernel events like AC power status and manages sys/ conditions
|
/* Listens to kernel events like AC power status and manages sys/ conditions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Finit daemon log functions
|
/* Finit daemon log functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -32,6 +32,9 @@
|
|||||||
# include <lite/lite.h>
|
# include <lite/lite.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SYSLOG_NAMES
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@@ -42,8 +45,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 +54,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +109,73 @@ static const char *l2s(int prio)
|
|||||||
return "UNK";
|
return "UNK";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s2f(const char *str)
|
||||||
|
{
|
||||||
|
for (int i = 0; facilitynames[i].c_name; i++) {
|
||||||
|
if (string_match(facilitynames[i].c_name, str))
|
||||||
|
return facilitynames[i].c_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s2l(const char *str)
|
||||||
|
{
|
||||||
|
for (int i = 0; prioritynames[i].c_name; i++) {
|
||||||
|
if (string_match(prioritynames[i].c_name, str))
|
||||||
|
return prioritynames[i].c_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse syslog facility.priority strings into their numerical values
|
||||||
|
* using arrays defined in <syslog.h>. Note, the 'prio' argument may
|
||||||
|
* be one of:
|
||||||
|
*
|
||||||
|
* - facility.level
|
||||||
|
* - facility
|
||||||
|
* - level
|
||||||
|
*
|
||||||
|
* It is up to the callee to assign defaults to 'facility' and 'level'
|
||||||
|
* before calling this function. If There is any match the respective
|
||||||
|
* facility or level will be assigned and this function returns OK.
|
||||||
|
*/
|
||||||
|
int log_parse(char *prio, int *facility, int *level)
|
||||||
|
{
|
||||||
|
char *fac = prio, *lvl;
|
||||||
|
int f = -1;
|
||||||
|
int l = -1;
|
||||||
|
|
||||||
|
if (!prio || !facility || !level)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
lvl = strchr(prio, '.');
|
||||||
|
if (lvl) {
|
||||||
|
*lvl = 0;
|
||||||
|
lvl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lvl && *lvl)
|
||||||
|
l = s2l(lvl);
|
||||||
|
|
||||||
|
f = s2f(fac);
|
||||||
|
if (l < 0)
|
||||||
|
l = s2l(fac);
|
||||||
|
|
||||||
|
if (l < 0 && f <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (l <= LOG_DEBUG)
|
||||||
|
*level = l;
|
||||||
|
|
||||||
|
if (f <= LOG_LOCAL7)
|
||||||
|
*facility = f;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log to /dev/kmsg until syslogd has started, then openlog()
|
* Log to /dev/kmsg until syslogd has started, then openlog()
|
||||||
* and continue logging as a regular daemon.
|
* and continue logging as a regular daemon.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Finit daemon log functions
|
/* Finit daemon log functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -78,6 +78,7 @@ void log_init (void);
|
|||||||
void log_exit (void);
|
void log_exit (void);
|
||||||
|
|
||||||
void log_debug(void);
|
void log_debug(void);
|
||||||
|
int log_parse(char *prio, int *facility, int *level);
|
||||||
|
|
||||||
void logit (int prio, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
void logit (int prio, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
void flog (char *file, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
void flog (char *file, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
|||||||
+67
-14
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -36,6 +36,9 @@
|
|||||||
# include <lite/lite.h>
|
# include <lite/lite.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LOG_MAX (200 * 1024)
|
||||||
|
#define LOG_NUM 5
|
||||||
|
|
||||||
static const char version_info[] = PACKAGE_NAME " v" PACKAGE_VERSION;
|
static const char version_info[] = PACKAGE_NAME " v" PACKAGE_VERSION;
|
||||||
extern int logrotate(char *file, int num, off_t sz);
|
extern int logrotate(char *file, int num, off_t sz);
|
||||||
|
|
||||||
@@ -87,23 +90,61 @@ reopen:
|
|||||||
return fclose(fp);
|
return fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse possible systemd style log <level> prefix from message
|
||||||
|
* For details, see libsystemd/sd-daemon.h
|
||||||
|
*
|
||||||
|
* Returns the level, and updates buf to point past the prefix
|
||||||
|
*/
|
||||||
|
static int parse_level(char **buf, int default_level)
|
||||||
|
{
|
||||||
|
char *msg = *buf;
|
||||||
|
|
||||||
|
if (msg[0] == '<' && msg[2] == '>' && msg[1] >= '0' && msg[1] <= '7') {
|
||||||
|
int level;
|
||||||
|
|
||||||
|
switch (msg[1]) {
|
||||||
|
case '0': level = LOG_EMERG; break;
|
||||||
|
case '1': level = LOG_ALERT; break;
|
||||||
|
case '2': level = LOG_CRIT; break;
|
||||||
|
case '3': level = LOG_ERR; break;
|
||||||
|
case '4': level = LOG_WARNING; break;
|
||||||
|
case '5': level = LOG_NOTICE; break;
|
||||||
|
case '6': level = LOG_INFO; break;
|
||||||
|
case '7': level = LOG_DEBUG; break;
|
||||||
|
default: level = default_level; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf = msg + 3;
|
||||||
|
return (default_level & ~LOG_PRIMASK) | level;
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_log(int level, char *msg)
|
||||||
|
{
|
||||||
|
syslog(parse_level(&msg, level), "%s", msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int logit(int level, char *buf, size_t len)
|
static int logit(int level, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
if (buf[0]) {
|
if (buf[0])
|
||||||
syslog(level, "%s", buf);
|
return do_log(level, buf);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((fgets(buf, len, stdin)))
|
while ((fgets(buf, len, stdin)))
|
||||||
syslog(level, "%s", buf);
|
do_log(level, buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_prio(char *arg, int *f, int *l)
|
static int parse_prio(char *arg, int *fac, int *lvl)
|
||||||
{
|
{
|
||||||
char *duparg = strdup(arg);
|
char *duparg = strdup(arg);
|
||||||
char *ptr, *prio;
|
const char *prio;
|
||||||
|
char *ptr;
|
||||||
|
int found;
|
||||||
|
|
||||||
if (!duparg)
|
if (!duparg)
|
||||||
prio = arg;
|
prio = arg;
|
||||||
@@ -114,23 +155,34 @@ static int parse_prio(char *arg, int *f, int *l)
|
|||||||
if (ptr) {
|
if (ptr) {
|
||||||
*ptr++ = 0;
|
*ptr++ = 0;
|
||||||
|
|
||||||
|
found = -1;
|
||||||
for (int i = 0; facilitynames[i].c_name; i++) {
|
for (int i = 0; facilitynames[i].c_name; i++) {
|
||||||
if (!strcmp(facilitynames[i].c_name, prio)) {
|
if (!strcmp(facilitynames[i].c_name, prio)) {
|
||||||
*f = facilitynames[i].c_val;
|
found = facilitynames[i].c_val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*fac = found;
|
||||||
prio = ptr;
|
prio = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found = -1;
|
||||||
for (int i = 0; prioritynames[i].c_name; i++) {
|
for (int i = 0; prioritynames[i].c_name; i++) {
|
||||||
|
|
||||||
if (!strcmp(prioritynames[i].c_name, prio)) {
|
if (!strcmp(prioritynames[i].c_name, prio)) {
|
||||||
*l = prioritynames[i].c_val;
|
found = prioritynames[i].c_val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found == -1)
|
||||||
|
return 1;
|
||||||
|
*lvl = found;
|
||||||
|
|
||||||
if (duparg != arg)
|
if (duparg != arg)
|
||||||
free(duparg);
|
free(duparg);
|
||||||
|
|
||||||
@@ -161,13 +213,14 @@ static int usage(int code)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c, rc, num = 5;
|
char *ident = NULL, *logfile = NULL;
|
||||||
|
int log_opts = LOG_NOWAIT;
|
||||||
int facility = LOG_USER;
|
int facility = LOG_USER;
|
||||||
int level = LOG_INFO;
|
int level = LOG_INFO;
|
||||||
int log_opts = LOG_NOWAIT;
|
off_t size = LOG_MAX;
|
||||||
off_t size = 200 * 1024;
|
|
||||||
char *ident = NULL, *logfile = NULL;
|
|
||||||
char buf[512] = "";
|
char buf[512] = "";
|
||||||
|
int num = LOG_NUM;
|
||||||
|
int c, rc;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "f:hn:p:r:st:v")) != EOF) {
|
while ((c = getopt(argc, argv, "f:hn:p:r:st:v")) != EOF) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+8
-6
@@ -1,6 +1,6 @@
|
|||||||
/* Handle MD arrays
|
/* Handle MD arrays
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
static glob_t *get_arrays(void)
|
static glob_t *get_arrays(void)
|
||||||
@@ -48,17 +49,18 @@ static glob_t *get_arrays(void)
|
|||||||
*/
|
*/
|
||||||
void mdadm_wait(void)
|
void mdadm_wait(void)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
glob_t *gl;
|
glob_t *gl;
|
||||||
char cmd[160];
|
|
||||||
|
|
||||||
/* Setup kernel specific settings, e.g. allow broadcast ping, etc. */
|
/* Setup kernel specific settings, e.g. allow broadcast ping, etc. */
|
||||||
gl = get_arrays();
|
gl = get_arrays();
|
||||||
if (gl) {
|
if (gl) {
|
||||||
for (i = 0; i < gl->gl_pathc; i++) {
|
size_t i;
|
||||||
char *array;
|
|
||||||
|
|
||||||
array = basename(gl->gl_pathv[i]);
|
for (i = 0; i < gl->gl_pathc; i++) {
|
||||||
|
const char *array;
|
||||||
|
char cmd[160];
|
||||||
|
|
||||||
|
array = basenm(gl->gl_pathv[i]);
|
||||||
snprintf(cmd, sizeof(cmd), "mdadm --wait-clean /dev/%s >/dev/null", array);
|
snprintf(cmd, sizeof(cmd), "mdadm --wait-clean /dev/%s >/dev/null", array);
|
||||||
run_interactive(cmd, "Marking MD array %s as clean", array);
|
run_interactive(cmd, "Marking MD array %s as clean", array);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,6 +1,6 @@
|
|||||||
/* Mount and unmount helpers
|
/* Mount and unmount helpers
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SysV init on Debian/Ubuntu skips these protected mount points
|
* SysV init on Debian/Ubuntu skips these protected mount points
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
* and regular filesystems that can be safely unmounted before we do
|
* and regular filesystems that can be safely unmounted before we do
|
||||||
* swapoff, and remount / as read-only, respectively.
|
* swapoff, and remount / as read-only, respectively.
|
||||||
*/
|
*/
|
||||||
static int is_protected(char *dir)
|
static int is_protected(const char *dir)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
char *protected_mnts[] = {
|
char *protected_mnts[] = {
|
||||||
@@ -111,7 +112,7 @@ static int unmount(const char *target)
|
|||||||
|
|
||||||
void unmount_tmpfs(void)
|
void unmount_tmpfs(void)
|
||||||
{
|
{
|
||||||
struct mntent *mnt;
|
const struct mntent *mnt;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
|
||||||
while ((mnt = iterator("/proc/mounts", &fp))) {
|
while ((mnt = iterator("/proc/mounts", &fp))) {
|
||||||
@@ -122,7 +123,7 @@ void unmount_tmpfs(void)
|
|||||||
|
|
||||||
void unmount_regular(void)
|
void unmount_regular(void)
|
||||||
{
|
{
|
||||||
struct mntent *mnt;
|
const struct mntent *mnt;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
|
||||||
while ((mnt = iterator("/proc/mounts", &fp))) {
|
while ((mnt = iterator("/proc/mounts", &fp))) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* PID and PID file helpers
|
/* PID and PID file helpers
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -192,7 +192,7 @@ int pid_file_set(svc_t *svc, char *file, int not)
|
|||||||
* pid:foo.tla --> /run/foo.tla.pid
|
* pid:foo.tla --> /run/foo.tla.pid
|
||||||
* pid:/tmp/foo --> /tmp/foo.pid (Not handled by pidfile plugin!)
|
* pid:/tmp/foo --> /tmp/foo.pid (Not handled by pidfile plugin!)
|
||||||
*
|
*
|
||||||
* An exclamation mark, or logial NOT, in the first character position
|
* An exclamation mark, or logical NOT, in the first character position
|
||||||
* indicates that Finit should *not* manage the PID file, and that the
|
* indicates that Finit should *not* manage the PID file, and that the
|
||||||
* process uses a "non-standard" location. Eg. if service is 'bar'
|
* process uses a "non-standard" location. Eg. if service is 'bar'
|
||||||
* Finit would assume the PID file is /run/bar.pid and the below simply
|
* Finit would assume the PID file is /run/bar.pid and the below simply
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* PID and PID file helpers
|
/* PID and PID file helpers
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+15
-9
@@ -1,6 +1,6 @@
|
|||||||
/* Plugin based services architecture for finit
|
/* Plugin based services architecture for finit
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0)
|
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd > 0)
|
||||||
#define SEARCH_PLUGIN(str) \
|
#define SEARCH_PLUGIN(str) \
|
||||||
@@ -77,23 +78,26 @@ static char *trim_ext(char *name)
|
|||||||
|
|
||||||
int plugin_register(plugin_t *plugin)
|
int plugin_register(plugin_t *plugin)
|
||||||
{
|
{
|
||||||
|
const char *nm;
|
||||||
|
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup default name if none is provided */
|
/* Setup default name if none is provided */
|
||||||
if (!plugin->name) {
|
nm = plugin->name;
|
||||||
|
if (!nm) {
|
||||||
#ifndef ENABLE_STATIC
|
#ifndef ENABLE_STATIC
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
|
|
||||||
if (dladdr(plugin, &info) && info.dli_fname)
|
if (dladdr(plugin, &info) && info.dli_fname)
|
||||||
plugin->name = basename(info.dli_fname);
|
nm = basenm(info.dli_fname);
|
||||||
#endif
|
#endif
|
||||||
if (!plugin->name)
|
if (!nm)
|
||||||
plugin->name = "unknown";
|
nm = "unknown";
|
||||||
}
|
}
|
||||||
plugin->name = trim_ext(strdup(plugin->name));
|
plugin->name = trim_ext(strdup(nm));
|
||||||
|
|
||||||
/* Already registered? */
|
/* Already registered? */
|
||||||
if (plugin_find(plugin->name)) {
|
if (plugin_find(plugin->name)) {
|
||||||
@@ -253,7 +257,7 @@ void plugin_run_hook(hook_point_t no, void *arg)
|
|||||||
|
|
||||||
PLUGIN_ITERATOR(p, tmp) {
|
PLUGIN_ITERATOR(p, tmp) {
|
||||||
if (p->hook[no].cb) {
|
if (p->hook[no].cb) {
|
||||||
dbg("Calling %s hook n:o %d (arg: %p) ...", basename(p->name), no, arg ?: "NIL");
|
dbg("Calling %s hook n:o %d (arg: %p) ...", basenm(p->name), no, arg ?: "NIL");
|
||||||
p->hook[no].cb(arg ? arg : p->hook[no].arg);
|
p->hook[no].cb(arg ? arg : p->hook[no].arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,9 +305,9 @@ int plugin_io_init(plugin_t *p)
|
|||||||
if (!is_io_plugin(p))
|
if (!is_io_plugin(p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dbg("Initializing plugin %s for I/O", basename(p->name));
|
dbg("Initializing plugin %s for I/O", basenm(p->name));
|
||||||
if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags)) {
|
if (uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags)) {
|
||||||
warn("Failed setting up I/O plugin %s", basename(p->name));
|
warn("Failed setting up I/O plugin %s", basenm(p->name));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +320,8 @@ static int init_plugins(uev_ctx_t *ctx)
|
|||||||
plugin_t *p, *tmp;
|
plugin_t *p, *tmp;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
|
||||||
|
(void)ctx;
|
||||||
|
|
||||||
PLUGIN_ITERATOR(p, tmp) {
|
PLUGIN_ITERATOR(p, tmp) {
|
||||||
if (plugin_io_init(p))
|
if (plugin_io_init(p))
|
||||||
fail++;
|
fail++;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Plugin based services architecture for finit
|
/* Plugin based services architecture for finit
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+3
-2
@@ -1,7 +1,7 @@
|
|||||||
/* Private header file for main finit daemon, not for plugins
|
/* Private header file for main finit daemon, not for plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -41,12 +41,13 @@ extern int service_interval;
|
|||||||
extern char *fsck_mode;
|
extern char *fsck_mode;
|
||||||
extern char *fsck_repair;
|
extern char *fsck_repair;
|
||||||
|
|
||||||
|
extern uev_ctx_t *ctx;
|
||||||
|
|
||||||
int api_init (uev_ctx_t *ctx);
|
int api_init (uev_ctx_t *ctx);
|
||||||
int api_exit (void);
|
int api_exit (void);
|
||||||
void conf_flush_events(void);
|
void conf_flush_events(void);
|
||||||
|
|
||||||
void service_monitor (pid_t lost, int status);
|
void service_monitor (pid_t lost, int status);
|
||||||
void service_notify_cb(uev_t *w, void *arg, int events);
|
|
||||||
|
|
||||||
const char *plugin_hook_str (hook_point_t no);
|
const char *plugin_hook_str (hook_point_t no);
|
||||||
int plugin_exists (hook_point_t no);
|
int plugin_exists (hook_point_t no);
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* reboot, halt, poweroff, shutdown, suspend for finit
|
/* reboot, halt, poweroff, shutdown, suspend for finit
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+14
-2
@@ -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)
|
||||||
{
|
{
|
||||||
|
if (interactive)
|
||||||
fprintf(stderr, "\e[1m[\e[0m\e[1;33m ⋯ \e[0m\e[1m]\e[0m %s %s", prefix, msg);
|
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 (interactive) {
|
||||||
if (rc)
|
if (rc)
|
||||||
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;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
|
||||||
else
|
else
|
||||||
fputs("\r\e[1m[\e[0m\e[1;32m OK \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
|
||||||
|
fprintf(stderr, "[%s] %s\n", rc ? "FAIL" : " OK ", active_msg ?: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sig_unblock(void)
|
void sig_unblock(void)
|
||||||
@@ -184,7 +193,7 @@ int run_parts(char *dir, char *cmd, const char *env[], int progress, int sysv)
|
|||||||
#ifndef __FINIT__
|
#ifndef __FINIT__
|
||||||
static int usage(int rc)
|
static int usage(int rc)
|
||||||
{
|
{
|
||||||
warnx("usage: runparts [-dhps?] DIRECTORY");
|
warnx("usage: runparts [-bdhps?] DIRECTORY");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|||||||
+4
-2
@@ -1,6 +1,6 @@
|
|||||||
/* Work queue helper functions
|
/* Work queue helper functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -22,7 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "private.h"
|
||||||
|
#include "log.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
|
|
||||||
#define SC_INIT 0x494E4954 /* "INIT", see ascii(7) */
|
#define SC_INIT 0x494E4954 /* "INIT", see ascii(7) */
|
||||||
@@ -35,6 +36,7 @@ static void cb(uev_t *w, void *arg, int events)
|
|||||||
struct wq *work = (struct wq *)arg;
|
struct wq *work = (struct wq *)arg;
|
||||||
|
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): spurious problem with schedule work timer, restarting.", __func__);
|
||||||
uev_timer_start(w);
|
uev_timer_start(w);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Work queue helper functions
|
/* Work queue helper functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2018-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+43
-24
@@ -1,6 +1,6 @@
|
|||||||
/* List and enable/disable service configurations
|
/* List and enable/disable service configurations
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2017-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -222,20 +222,13 @@ int serv_list(char *arg)
|
|||||||
* If the resulting file doesn't exist, and creat is not set, *or*
|
* 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,15 +236,26 @@ 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)) {
|
||||||
|
char *at = strchr(path, '@');
|
||||||
|
|
||||||
|
if (template && at)
|
||||||
|
*++at = 0;
|
||||||
|
else
|
||||||
paste(path, len, finit_rcsd, name);
|
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,15 +411,20 @@ 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);
|
||||||
|
|
||||||
|
fn = conf(path, sizeof(path), arg, 0, 1);
|
||||||
|
if (!fn || !fexist(fn)) {
|
||||||
WARNX("Cannot find %s", arg);
|
WARNX("Cannot find %s", arg);
|
||||||
return 1;
|
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);
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* List and enable/disable service configurations
|
/* List and enable/disable service configurations
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2017-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+565
-267
File diff suppressed because it is too large
Load Diff
+2
-4
@@ -1,7 +1,7 @@
|
|||||||
/* Finit service monitor, task starter and generic API for managing svc_t
|
/* Finit service monitor, task starter and generic API for managing svc_t
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,12 +27,10 @@
|
|||||||
|
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
void service_runlevel (int newlevel);
|
|
||||||
int service_register (int type, char *line, struct rlimit rlimit[], char *file);
|
int service_register (int type, char *line, struct rlimit rlimit[], char *file);
|
||||||
void service_unregister (svc_t *svc);
|
void service_unregister (svc_t *svc);
|
||||||
|
|
||||||
void service_runtask_clean (void);
|
void service_runtask_clean (void);
|
||||||
void service_reload_dynamic (void);
|
|
||||||
void service_update_rdeps (void);
|
void service_update_rdeps (void);
|
||||||
void service_mark_unavail (void);
|
void service_mark_unavail (void);
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ int service_timeout_after (svc_t *svc, int timeout, void (*cb)(svc_t *svc
|
|||||||
int service_timeout_cancel (svc_t *svc);
|
int service_timeout_cancel (svc_t *svc);
|
||||||
|
|
||||||
void service_forked (svc_t *svc);
|
void service_forked (svc_t *svc);
|
||||||
void service_ready (svc_t *svc);
|
void service_ready (svc_t *svc, int ready);
|
||||||
|
|
||||||
int service_stop (svc_t *svc);
|
int service_stop (svc_t *svc);
|
||||||
int service_step (svc_t *svc);
|
int service_step (svc_t *svc);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Signal management - Be conservative with what finit responds to!
|
/* Signal management - Be conservative with what finit responds to!
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "sm.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
|
||||||
@@ -232,6 +233,8 @@ void do_iterate_proc(int (*cb)(int, void *), void *data)
|
|||||||
dbg("Skipping %s ...", file);
|
dbg("Skipping %s ...", file);
|
||||||
else if (file[0] == '@')
|
else if (file[0] == '@')
|
||||||
dbg("Skipping %s ...", &file[1]);
|
dbg("Skipping %s ...", &file[1]);
|
||||||
|
else if (strstr(file, "initctl"))
|
||||||
|
dbg("Skipping %s ...", file);
|
||||||
else
|
else
|
||||||
if (cb(pid, data)) {
|
if (cb(pid, data)) {
|
||||||
dbg("PID %d is still alive (%s)", pid, file);
|
dbg("PID %d is still alive (%s)", pid, file);
|
||||||
@@ -258,6 +261,7 @@ static int status_cb(int pid, void *data)
|
|||||||
{
|
{
|
||||||
int *has_proc = (int *)data;
|
int *has_proc = (int *)data;
|
||||||
|
|
||||||
|
(void)pid;
|
||||||
*has_proc = 1;
|
*has_proc = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -423,6 +427,8 @@ void do_shutdown(shutop_t op)
|
|||||||
*/
|
*/
|
||||||
static void sighup_cb(uev_t *w, void *arg, int events)
|
static void sighup_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -439,7 +445,7 @@ static void sighup_cb(uev_t *w, void *arg, int events)
|
|||||||
api_init(w->ctx);
|
api_init(w->ctx);
|
||||||
|
|
||||||
/* INIT_CMD_RELOAD: 'init q', 'initctl reload', and SIGHUP */
|
/* INIT_CMD_RELOAD: 'init q', 'initctl reload', and SIGHUP */
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -449,6 +455,9 @@ static void sighup_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
static void sigint_cb(uev_t *w, void *arg, int events)
|
static void sigint_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)w;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -465,6 +474,9 @@ static void sigint_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
static void sigpwr_cb(uev_t *w, void *arg, int events)
|
static void sigpwr_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)w;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -479,6 +491,8 @@ static void sigpwr_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
static void sigusr1_cb(uev_t *w, void *arg, int events)
|
static void sigusr1_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -500,6 +514,9 @@ static void sigusr1_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
static void sigusr2_cb(uev_t *w, void *arg, int events)
|
static void sigusr2_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)w;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -512,7 +529,7 @@ static void sigusr2_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
halt = SHUT_OFF;
|
halt = SHUT_OFF;
|
||||||
service_runlevel(0);
|
sm_runlevel(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -520,6 +537,9 @@ static void sigusr2_cb(uev_t *w, void *arg, int events)
|
|||||||
*/
|
*/
|
||||||
static void sigterm_cb(uev_t *w, void *arg, int events)
|
static void sigterm_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
(void)w;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
dbg("...");
|
dbg("...");
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
@@ -532,7 +552,7 @@ static void sigterm_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
halt = SHUT_REBOOT;
|
halt = SHUT_REBOOT;
|
||||||
service_runlevel(6);
|
sm_runlevel(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -543,6 +563,9 @@ static void sigchld_cb(uev_t *w, void *arg, int events)
|
|||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
(void)w;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
errx(1, "Unrecoverable error in signal watcher");
|
errx(1, "Unrecoverable error in signal watcher");
|
||||||
return;
|
return;
|
||||||
@@ -599,6 +622,9 @@ const char *sig_name(int signo)
|
|||||||
*/
|
*/
|
||||||
static void chld_handler(int sig, siginfo_t *info, void *ctx)
|
static void chld_handler(int sig, siginfo_t *info, void *ctx)
|
||||||
{
|
{
|
||||||
|
(void)sig;
|
||||||
|
(void)info;
|
||||||
|
(void)ctx;
|
||||||
/* NOP */
|
/* NOP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Signal management - Be conservative with what finit responds to!
|
/* Signal management - Be conservative with what finit responds to!
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2023 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
@@ -38,11 +39,25 @@
|
|||||||
#include "sm.h"
|
#include "sm.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
|
||||||
sm_t sm;
|
typedef enum {
|
||||||
|
SM_BOOTSTRAP_STATE = 0, /* Init state, bootstrap services */
|
||||||
|
SM_BOOTSTRAP_WAIT_STATE, /* Waiting for bootstrap to complete */
|
||||||
|
SM_RUNNING_STATE, /* Normal state, services running */
|
||||||
|
SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occurred */
|
||||||
|
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped processes to halt */
|
||||||
|
SM_RUNLEVEL_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
|
||||||
|
SM_RELOAD_CHANGE_STATE, /* A reload event has occurred */
|
||||||
|
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped processes to halt */
|
||||||
|
SM_RELOAD_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
|
||||||
|
} sm_state_t;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
sm_state_t state; /* Running, Changed, Waiting, ... */
|
||||||
|
int newlevel; /* Set to new runlevel on change, -1 otherwise */
|
||||||
|
int reload; /* Set on reload event, else 0 */
|
||||||
|
int in_reload; /* Set when waiting for all processes to be halted */
|
||||||
|
} sm;
|
||||||
|
|
||||||
#ifndef FINIT_NOLOGIN_PATH
|
|
||||||
#define FINIT_NOLOGIN_PATH _PATH_NOLOGIN /* Stop user logging in. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for system bootstrap to complete, all SVC_TYPE_RUNTASK must be
|
* Wait for system bootstrap to complete, all SVC_TYPE_RUNTASK must be
|
||||||
@@ -90,7 +105,7 @@ static void sm_check_bootstrap(void *work)
|
|||||||
} else
|
} else
|
||||||
dbg("Change to default runlevel(%d), starting all services ...", cfglevel);
|
dbg("Change to default runlevel(%d), starting all services ...", cfglevel);
|
||||||
|
|
||||||
service_runlevel(level);
|
sm_runlevel(level);
|
||||||
|
|
||||||
/* Clean up bootstrap-only tasks/services that never started */
|
/* Clean up bootstrap-only tasks/services that never started */
|
||||||
dbg("Clean up all bootstrap-only tasks/services ...");
|
dbg("Clean up all bootstrap-only tasks/services ...");
|
||||||
@@ -107,6 +122,9 @@ static char *sm_status(sm_state_t state)
|
|||||||
case SM_BOOTSTRAP_STATE:
|
case SM_BOOTSTRAP_STATE:
|
||||||
return "bootstrap";
|
return "bootstrap";
|
||||||
|
|
||||||
|
case SM_BOOTSTRAP_WAIT_STATE:
|
||||||
|
return "bootstrap/wait";
|
||||||
|
|
||||||
case SM_RUNNING_STATE:
|
case SM_RUNNING_STATE:
|
||||||
return "running";
|
return "running";
|
||||||
|
|
||||||
@@ -116,18 +134,23 @@ static char *sm_status(sm_state_t state)
|
|||||||
case SM_RUNLEVEL_WAIT_STATE:
|
case SM_RUNLEVEL_WAIT_STATE:
|
||||||
return "runlevel/wait";
|
return "runlevel/wait";
|
||||||
|
|
||||||
|
case SM_RUNLEVEL_CLEAN_STATE:
|
||||||
|
return "runlevel/clean";
|
||||||
|
|
||||||
case SM_RELOAD_CHANGE_STATE:
|
case SM_RELOAD_CHANGE_STATE:
|
||||||
return "reload/change";
|
return "reload/change";
|
||||||
|
|
||||||
case SM_RELOAD_WAIT_STATE:
|
case SM_RELOAD_WAIT_STATE:
|
||||||
return "reload/wait";
|
return "reload/wait";
|
||||||
|
|
||||||
default:
|
case SM_RELOAD_CLEAN_STATE:
|
||||||
return "unknown";
|
return "reload/clean";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char sm_runlevel(int lvl)
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static char sm_rl2ch(int lvl)
|
||||||
{
|
{
|
||||||
if (lvl == INIT_LEVEL)
|
if (lvl == INIT_LEVEL)
|
||||||
return 'S';
|
return 'S';
|
||||||
@@ -150,54 +173,39 @@ static void nologin(void)
|
|||||||
erase(FINIT_NOLOGIN_PATH);
|
erase(FINIT_NOLOGIN_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm_init(sm_t *sm)
|
void sm_init(void)
|
||||||
{
|
{
|
||||||
static struct wq work = {
|
static struct wq work = {
|
||||||
.cb = sm_check_bootstrap,
|
.cb = sm_check_bootstrap,
|
||||||
.delay = 1000
|
.delay = 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
sm->state = SM_BOOTSTRAP_STATE;
|
sm.state = SM_BOOTSTRAP_STATE;
|
||||||
sm->newlevel = -1;
|
sm.newlevel = -1;
|
||||||
sm->reload = 0;
|
sm.reload = 0;
|
||||||
sm->in_teardown = 0;
|
sm.in_reload = 0;
|
||||||
|
|
||||||
dbg("Starting bootstrap finalize timer ...");
|
dbg("Starting bootstrap finalize timer ...");
|
||||||
schedule_work(&work);
|
schedule_work(&work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm_set_runlevel(sm_t *sm, int newlevel)
|
void sm_step(void)
|
||||||
{
|
|
||||||
sm->newlevel = newlevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sm_set_reload(sm_t *sm)
|
|
||||||
{
|
|
||||||
sm->reload = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sm_is_in_teardown(sm_t *sm)
|
|
||||||
{
|
|
||||||
return sm->in_teardown;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sm_step(sm_t *sm)
|
|
||||||
{
|
{
|
||||||
sm_state_t old_state;
|
sm_state_t old_state;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
old_state = sm->state;
|
old_state = sm.state;
|
||||||
|
|
||||||
dbg("state: %s, runlevel: %c, newlevel: %d, teardown: %d, reload: %d",
|
dbg("state: %s, runlevel: %c, newlevel: %d, teardown: %d, reload: %d",
|
||||||
sm_status(sm->state), sm_runlevel(runlevel), sm->newlevel, sm->in_teardown, sm->reload);
|
sm_status(sm.state), sm_rl2ch(runlevel), sm.newlevel, sm.in_reload, sm.reload);
|
||||||
|
|
||||||
switch (sm->state) {
|
switch (sm.state) {
|
||||||
case SM_BOOTSTRAP_STATE:
|
case SM_BOOTSTRAP_STATE:
|
||||||
dbg("Bootstrapping all services in runlevel S from %s", finit_conf);
|
dbg("Bootstrapping all services in runlevel S from %s", finit_conf);
|
||||||
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE);
|
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE | SVC_TYPE_SYSV);
|
||||||
|
|
||||||
sm->state = SM_BOOTSTRAP_WAIT_STATE;
|
sm.state = SM_BOOTSTRAP_WAIT_STATE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -218,7 +226,7 @@ restart:
|
|||||||
/* Allow runparts to start */
|
/* Allow runparts to start */
|
||||||
cond_set_oneshot("int/bootstrap");
|
cond_set_oneshot("int/bootstrap");
|
||||||
|
|
||||||
if (sm->newlevel == -1)
|
if (sm.newlevel == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Hooks that should run at the very end */
|
/* Hooks that should run at the very end */
|
||||||
@@ -229,10 +237,10 @@ restart:
|
|||||||
/* Disable progress output at normal runtime */
|
/* Disable progress output at normal runtime */
|
||||||
enable_progress(0);
|
enable_progress(0);
|
||||||
|
|
||||||
/* System bootrapped, launch TTYs et al */
|
/* System bootstrapped, launch TTYs et al */
|
||||||
bootstrap = 0;
|
bootstrap = 0;
|
||||||
service_step_all(SVC_TYPE_RESPAWN);
|
service_step_all(SVC_TYPE_RESPAWN);
|
||||||
sm->state = SM_RUNNING_STATE;
|
sm.state = SM_RUNNING_STATE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_RUNNING_STATE:
|
case SM_RUNNING_STATE:
|
||||||
@@ -240,26 +248,26 @@ restart:
|
|||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
/* runlevel changed? */
|
/* runlevel changed? */
|
||||||
if (sm->newlevel >= 0 && sm->newlevel <= 9) {
|
if (sm.newlevel >= 0 && sm.newlevel <= 9) {
|
||||||
if (runlevel == sm->newlevel) {
|
if (runlevel == sm.newlevel) {
|
||||||
sm->newlevel = -1;
|
sm.newlevel = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sm->state = SM_RUNLEVEL_CHANGE_STATE;
|
sm.state = SM_RUNLEVEL_CHANGE_STATE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reload ? */
|
/* reload ? */
|
||||||
if (sm->reload) {
|
if (sm.reload) {
|
||||||
sm->reload = 0;
|
sm.reload = 0;
|
||||||
sm->state = SM_RELOAD_CHANGE_STATE;
|
sm.state = SM_RELOAD_CHANGE_STATE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_RUNLEVEL_CHANGE_STATE:
|
case SM_RUNLEVEL_CHANGE_STATE:
|
||||||
prevlevel = runlevel;
|
prevlevel = runlevel;
|
||||||
runlevel = sm->newlevel;
|
runlevel = sm.newlevel;
|
||||||
sm->newlevel = -1;
|
sm.newlevel = -1;
|
||||||
|
|
||||||
/* Restore terse mode and run hooks before shutdown */
|
/* Restore terse mode and run hooks before shutdown */
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (runlevel == 0 || runlevel == 6) {
|
||||||
@@ -268,11 +276,11 @@ restart:
|
|||||||
plugin_run_hooks(HOOK_SHUTDOWN);
|
plugin_run_hooks(HOOK_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("Setting new runlevel --> %c <-- previous %c", sm_runlevel(runlevel), sm_runlevel(prevlevel));
|
dbg("Setting new runlevel --> %c <-- previous %c", sm_rl2ch(runlevel), sm_rl2ch(prevlevel));
|
||||||
if (osheading)
|
if (osheading)
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "%s, entering runlevel %c", osheading, sm_runlevel(runlevel));
|
logit(LOG_CONSOLE | LOG_NOTICE, "%s, entering runlevel %c", osheading, sm_rl2ch(runlevel));
|
||||||
else
|
else
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Entering runlevel %c", sm_runlevel(runlevel));
|
logit(LOG_CONSOLE | LOG_NOTICE, "Entering runlevel %c", sm_rl2ch(runlevel));
|
||||||
runlevel_set(prevlevel, runlevel);
|
runlevel_set(prevlevel, runlevel);
|
||||||
|
|
||||||
/* Disable login in single-user mode as well as shutdown/reboot */
|
/* Disable login in single-user mode as well as shutdown/reboot */
|
||||||
@@ -288,10 +296,10 @@ restart:
|
|||||||
service_runtask_clean();
|
service_runtask_clean();
|
||||||
|
|
||||||
dbg("Stopping services not allowed in new runlevel ...");
|
dbg("Stopping services not allowed in new runlevel ...");
|
||||||
sm->in_teardown = 1;
|
sm.in_reload = 1;
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
sm->state = SM_RUNLEVEL_WAIT_STATE;
|
sm.state = SM_RUNLEVEL_WAIT_STATE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_RUNLEVEL_WAIT_STATE:
|
case SM_RUNLEVEL_WAIT_STATE:
|
||||||
@@ -310,15 +318,33 @@ restart:
|
|||||||
plugin_run_hooks(HOOK_RUNLEVEL_CHANGE); /* Reconfigure HW/VLANs/etc here */
|
plugin_run_hooks(HOOK_RUNLEVEL_CHANGE); /* Reconfigure HW/VLANs/etc here */
|
||||||
|
|
||||||
dbg("Starting services new to this runlevel ...");
|
dbg("Starting services new to this runlevel ...");
|
||||||
sm->in_teardown = 0;
|
sm.in_reload = 0;
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
|
sm.state = SM_RUNLEVEL_CLEAN_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_RUNLEVEL_CLEAN_STATE:
|
||||||
|
/*
|
||||||
|
* Wait for post:script or cleanup:script to be collected,
|
||||||
|
* which moves the svc to HALTED or DEAD state. We will
|
||||||
|
* be called by the service_monitor() on collect.
|
||||||
|
*/
|
||||||
|
svc = svc_clean_completed();
|
||||||
|
if (svc) {
|
||||||
|
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
|
||||||
|
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup stale services */
|
/* 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
|
||||||
@@ -329,7 +355,7 @@ restart:
|
|||||||
if (runlevel == 0 || runlevel == 6)
|
if (runlevel == 0 || runlevel == 6)
|
||||||
do_shutdown(halt);
|
do_shutdown(halt);
|
||||||
|
|
||||||
sm->state = SM_RUNNING_STATE;
|
sm.state = SM_RUNNING_STATE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_RELOAD_CHANGE_STATE:
|
case SM_RELOAD_CHANGE_STATE:
|
||||||
@@ -341,11 +367,11 @@ restart:
|
|||||||
* let all affected services move to WAITING/HALTED
|
* let all affected services move to WAITING/HALTED
|
||||||
*/
|
*/
|
||||||
dbg("Stopping services not allowed after reconf ...");
|
dbg("Stopping services not allowed after reconf ...");
|
||||||
sm->in_teardown = 1;
|
sm.in_reload = 1;
|
||||||
cond_reload();
|
cond_reload();
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
sm->state = SM_RELOAD_WAIT_STATE;
|
sm.state = SM_RELOAD_WAIT_STATE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_RELOAD_WAIT_STATE:
|
case SM_RELOAD_WAIT_STATE:
|
||||||
@@ -359,11 +385,27 @@ restart:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sm->in_teardown = 0;
|
sm.in_reload = 0;
|
||||||
|
|
||||||
dbg("Starting services after reconf ...");
|
dbg("Starting services after reconf ...");
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
|
sm.state = SM_RELOAD_CLEAN_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_RELOAD_CLEAN_STATE:
|
||||||
|
/*
|
||||||
|
* Wait for post:script or cleanup:script to be collected,
|
||||||
|
* which moves the svc to HALTED or DEAD state. We will
|
||||||
|
* be called by the service_monitor() on collect.
|
||||||
|
*/
|
||||||
|
svc = svc_clean_completed();
|
||||||
|
if (svc) {
|
||||||
|
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
|
||||||
|
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup stale services */
|
/* Cleanup stale services */
|
||||||
svc_clean_dynamic(service_unregister);
|
svc_clean_dynamic(service_unregister);
|
||||||
|
|
||||||
@@ -374,14 +416,66 @@ restart:
|
|||||||
service_notify_reconf();
|
service_notify_reconf();
|
||||||
|
|
||||||
dbg("Reconfiguration done");
|
dbg("Reconfiguration done");
|
||||||
sm->state = SM_RUNNING_STATE;
|
sm.state = SM_RUNNING_STATE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sm->state != old_state)
|
if (sm.state != old_state)
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm_in_reload - System currently in reload or runlevel change?
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* %TRUE(1) or %FALSE(0)
|
||||||
|
*/
|
||||||
|
int sm_in_reload(void)
|
||||||
|
{
|
||||||
|
return sm.in_reload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm_reload - Called on SIGHUP, 'init q' or 'initctl reload'
|
||||||
|
*
|
||||||
|
* This function is called when Finit has received SIGHUP to reload
|
||||||
|
* .conf files in /etc/finit.d. It is responsible for starting,
|
||||||
|
* stopping and reloading (forwarding SIGHUP) to processes affected.
|
||||||
|
*/
|
||||||
|
void sm_reload(void)
|
||||||
|
{
|
||||||
|
sm.reload = 1;
|
||||||
|
|
||||||
|
dbg("Flushing pending .conf file events ...");
|
||||||
|
conf_flush_events();
|
||||||
|
|
||||||
|
sm_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm_runlevel - Change to a new runlevel
|
||||||
|
* @newlevel: New runlevel to activate
|
||||||
|
*
|
||||||
|
* Stops all services not in @newlevel and starts, or lets continue to run,
|
||||||
|
* those in @newlevel. Also updates @prevlevel and active @runlevel.
|
||||||
|
*/
|
||||||
|
void sm_runlevel(int newlevel)
|
||||||
|
{
|
||||||
|
if (!rescue && (runlevel == 1 || runlevel == INIT_LEVEL) && !IS_RESERVED_RUNLEVEL(newlevel))
|
||||||
|
networking(1);
|
||||||
|
|
||||||
|
sm.newlevel = newlevel;
|
||||||
|
|
||||||
|
dbg("Flushing pending .conf file events ...");
|
||||||
|
conf_flush_events();
|
||||||
|
|
||||||
|
sm_step();
|
||||||
|
|
||||||
|
if (!rescue && IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
|
networking(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* indent-tabs-mode: t
|
* indent-tabs-mode: t
|
||||||
|
|||||||
@@ -24,30 +24,12 @@
|
|||||||
#ifndef FINIT_SM_H_
|
#ifndef FINIT_SM_H_
|
||||||
#define FINIT_SM_H_
|
#define FINIT_SM_H_
|
||||||
|
|
||||||
typedef enum {
|
void sm_init (void);
|
||||||
SM_BOOTSTRAP_STATE = 0, /* Init state, bootstrap services */
|
void sm_step (void);
|
||||||
SM_BOOTSTRAP_WAIT_STATE, /* Waiting for bootstrap to complete */
|
|
||||||
SM_RUNNING_STATE, /* Normal state, services running */
|
|
||||||
SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occurred */
|
|
||||||
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped runlevel processes to be halted */
|
|
||||||
SM_RELOAD_CHANGE_STATE, /* A reload event has occurred */
|
|
||||||
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped reload processes to be halted */
|
|
||||||
} sm_state_t;
|
|
||||||
|
|
||||||
typedef struct sm {
|
int sm_in_reload (void);
|
||||||
sm_state_t state; /* Running, Changed, Waiting, ... */
|
void sm_reload (void);
|
||||||
int newlevel; /* Set on runlevel change to new runlevel, -1 if not change */
|
void sm_runlevel (int newlevel);
|
||||||
int reload; /* Set on reload event, else 0 */
|
|
||||||
int in_teardown; /* Set when waiting for all processes to be halted */
|
|
||||||
} sm_t;
|
|
||||||
|
|
||||||
extern sm_t sm;
|
|
||||||
|
|
||||||
void sm_init(sm_t *sm);
|
|
||||||
void sm_step(sm_t *sm);
|
|
||||||
void sm_set_runlevel(sm_t *sm, int newlevel);
|
|
||||||
void sm_set_reload(sm_t *sm);
|
|
||||||
int sm_is_in_teardown(sm_t *sm);
|
|
||||||
|
|
||||||
#endif /* FINIT_SM_H_ */
|
#endif /* FINIT_SM_H_ */
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user