mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50c99762f1 | ||
|
|
067043b298 |
@@ -9,9 +9,9 @@ For email questions/requests/alerts there is always the risk of memory
|
|||||||
exhaustion on the part of the maintainer(s).
|
exhaustion on the part of the maintainer(s).
|
||||||
|
|
||||||
If you are unsure of what to do, or how to implement an idea or bugfix,
|
If you are unsure of what to do, or how to implement an idea or bugfix,
|
||||||
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or use the
|
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or similar,
|
||||||
GitHub discussions forum, so we can discuss it. Talking about the code
|
so we can discuss it. Talking about the code first is the best way to
|
||||||
first is the best way to get started before submitting a pull request.
|
get started before submitting a pull request.
|
||||||
|
|
||||||
Either way, when sending an email, patch, or pull request, start by
|
Either way, when sending an email, patch, or pull request, start by
|
||||||
stating the version the change is made against, what it does, and why.
|
stating the version the change is made against, what it does, and why.
|
||||||
@@ -24,8 +24,7 @@ the maintainer(s) and make it easier for them to include your code.
|
|||||||
Coding Style
|
Coding Style
|
||||||
------------
|
------------
|
||||||
|
|
||||||
> [!TIP]
|
> **Tip:** Always submit code that follows the style of surrounding code!
|
||||||
> 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
|
||||||
@@ -74,6 +73,7 @@ It is expected of everyone engaging in the project to, in the words of
|
|||||||
Bill & Ted; [be excellent to each other][conduct].
|
Bill & Ted; [be excellent to each other][conduct].
|
||||||
|
|
||||||
|
|
||||||
|
[github]: https://github.com/troglobit/finit/
|
||||||
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
||||||
[gitbook]: https://git-scm.com/book/ch5-2.html
|
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||||
[conduct]: CODE-OF-CONDUCT.md
|
[conduct]: CODE-OF-CONDUCT.md
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
name: Bob the Builder
|
|
||||||
|
|
||||||
# Run on all branches, including all pull requests, except the 'dev'
|
|
||||||
# branch since that's where we run Coverity Scan (limited tokens/day)
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
- '!dev'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
# Verify we can build on latest Ubuntu with both gcc and clang
|
|
||||||
name: ${{ matrix.compiler }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
compiler: [gcc, clang]
|
|
||||||
fail-fast: false
|
|
||||||
env:
|
|
||||||
CC: ${{ matrix.compiler }}
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Static Finit
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix= --enable-static
|
|
||||||
make -j3 V=1
|
|
||||||
- name: Regular Finit
|
|
||||||
run: |
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
|
||||||
--with-keventd \
|
|
||||||
CFLAGS="-fsanitize=address -ggdb"
|
|
||||||
make -j3 clean
|
|
||||||
make -j3 V=1
|
|
||||||
- name: Install to /tmp
|
|
||||||
run: |
|
|
||||||
DESTDIR=/tmp make install-strip
|
|
||||||
tree /tmp || true
|
|
||||||
- name: Check dependencies
|
|
||||||
run: |
|
|
||||||
ldd /tmp/sbin/finit
|
|
||||||
size /tmp/sbin/finit
|
|
||||||
ldd /tmp/sbin/initctl
|
|
||||||
size /tmp/sbin/initctl
|
|
||||||
ldd /tmp/sbin/reboot
|
|
||||||
size /tmp/sbin/reboot
|
|
||||||
- name: Verify starting and showing usage text
|
|
||||||
run: |
|
|
||||||
sudo /tmp/sbin/finit -h
|
|
||||||
sudo /tmp/sbin/initctl -h
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Run Unit Tests
|
|
||||||
run: |
|
|
||||||
make check || (cat test/test-suite.log; false)
|
|
||||||
- name: Upload Test Results
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: finit-test-${{ matrix.compiler }}
|
|
||||||
path: test/*.log
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
name: Coverity Scan
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'dev'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
PROJECT_NAME: finit
|
|
||||||
CONTACT_EMAIL: troglobit@gmail.com
|
|
||||||
COVERITY_NAME: troglobit-finit
|
|
||||||
COVERITY_PROJ: troglobit%2Ffinit
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
coverity:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Fetch latest Coverity Scan MD5
|
|
||||||
id: var
|
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
run: |
|
|
||||||
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
|
||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
|
||||||
-O coverity-latest.tar.gz.md5
|
|
||||||
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: coverity-latest.tar.gz
|
|
||||||
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
|
||||||
${{ runner.os }}-coverity-
|
|
||||||
${{ runner.os }}-coverity
|
|
||||||
- name: Download Coverity Scan
|
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
run: |
|
|
||||||
if [ ! -f coverity-latest.tar.gz ]; then
|
|
||||||
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
|
||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
|
||||||
-O coverity-latest.tar.gz
|
|
||||||
else
|
|
||||||
echo "Latest Coverity Scan available from cache :-)"
|
|
||||||
md5sum coverity-latest.tar.gz
|
|
||||||
fi
|
|
||||||
mkdir coverity
|
|
||||||
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config
|
|
||||||
wget https://github.com/troglobit/libuev/releases/download/v2.4.0/libuev-2.4.0.tar.xz
|
|
||||||
wget https://github.com/troglobit/libite/releases/download/v2.5.2/libite-2.5.2.tar.gz
|
|
||||||
tar xf libuev-2.4.0.tar.xz
|
|
||||||
tar xf libite-2.5.2.tar.gz
|
|
||||||
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
|
|
||||||
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
|
||||||
sudo ldconfig
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
export PATH=`pwd`/coverity/bin:$PATH
|
|
||||||
cov-build --dir cov-int make
|
|
||||||
- name: Submit results to Coverity Scan
|
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
run: |
|
|
||||||
tar czvf ${PROJECT_NAME}.tgz cov-int
|
|
||||||
curl \
|
|
||||||
--form project=${COVERITY_NAME} \
|
|
||||||
--form token=$TOKEN \
|
|
||||||
--form email=${CONTACT_EMAIL} \
|
|
||||||
--form file=@${PROJECT_NAME}.tgz \
|
|
||||||
--form version=trunk \
|
|
||||||
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
|
||||||
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
|
||||||
- name: Upload build.log
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: coverity-build.log
|
|
||||||
path: cov-int/build-log.txt
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
name: Release General
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '[0-9]+.[0-9]+*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Build and upload release tarball
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
MAKEFLAGS: -j3
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Installing dependencies ...
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
|
||||||
- name: Setting release variables ...
|
|
||||||
id: build
|
|
||||||
run: |
|
|
||||||
ver=${GITHUB_REF#refs/tags/}
|
|
||||||
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
|
||||||
if echo $ver | grep -qE '^[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
|
|
||||||
echo "pre=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "pre=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
|
|
||||||
echo "latest=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "latest=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Creating Makefiles ...
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
|
||||||
--with-keventd
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Build release ...
|
|
||||||
run: |
|
|
||||||
make release || (cat test/test-suite.log; false)
|
|
||||||
ls -lF ../
|
|
||||||
mkdir -p artifacts/
|
|
||||||
mv ../*.tar.* artifacts/
|
|
||||||
- name: Extract ChangeLog entry ...
|
|
||||||
run: |
|
|
||||||
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|
|
||||||
|head -n -1 > release.md
|
|
||||||
cat release.md
|
|
||||||
- uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
name: Finit v${{ github.ref_name }}
|
|
||||||
prerelease: ${{ steps.build.outputs.pre }}
|
|
||||||
makeLatest: ${{ steps.build.outputs.latest }}
|
|
||||||
bodyFile: "release.md"
|
|
||||||
artifacts: "artifacts/*"
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
name: Weekly Distcheck
|
|
||||||
|
|
||||||
# Verify that `make distcheck` works as intended: all tests pass, and
|
|
||||||
# any new files are distributed in the tarballs
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 0'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
schedule:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
run: ${{ steps.check.outputs.run }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Check for any commits since last week
|
|
||||||
id: schedule
|
|
||||||
run: |
|
|
||||||
commits="$(git log --format=%H --since='1 week ago')"
|
|
||||||
if [ -n "$commits" ]; then
|
|
||||||
echo "run=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "run=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
distcheck:
|
|
||||||
needs: schedule
|
|
||||||
if: ${{ needs.schedule.outputs.run == 'true' }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Base run
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var
|
|
||||||
make -j9 V=1
|
|
||||||
- name: Install to /tmp
|
|
||||||
run: |
|
|
||||||
DESTDIR=/tmp make install-strip
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Check dist tarball
|
|
||||||
run: |
|
|
||||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
|
||||||
dir=finit-$ver/_build/sub
|
|
||||||
make -j1 distcheck || (cat $dir/test/test-suite.log; false)
|
|
||||||
@@ -14,7 +14,6 @@ GTAGS
|
|||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/ar-lib
|
/ar-lib
|
||||||
/backup/
|
|
||||||
/compile
|
/compile
|
||||||
/config.cache
|
/config.cache
|
||||||
/config.h
|
/config.h
|
||||||
@@ -37,9 +36,6 @@ GTAGS
|
|||||||
/test-driver
|
/test-driver
|
||||||
/test-suite.log
|
/test-suite.log
|
||||||
|
|
||||||
# Misc
|
|
||||||
/.gdb_history
|
|
||||||
|
|
||||||
# TroglOS build system
|
# TroglOS build system
|
||||||
/.config
|
/.config
|
||||||
/.stamp
|
/.stamp
|
||||||
@@ -49,6 +45,3 @@ GTAGS
|
|||||||
/.autoconf
|
/.autoconf
|
||||||
/.automake
|
/.automake
|
||||||
/.built
|
/.built
|
||||||
|
|
||||||
# VS Code user settings
|
|
||||||
.vscode
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
|
||||||
default:\
|
|
||||||
:tc=default@/etc/gtags/gtags.conf:\
|
|
||||||
:tc=common:
|
|
||||||
|
|
||||||
common:\
|
|
||||||
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css,sysroot/:
|
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
# Travis CI integration -- https://travis-ci.org/troglobit/finit
|
||||||
|
# Defaults to GNU GCC and autotools: ./configure && make && make test
|
||||||
|
language: c
|
||||||
|
|
||||||
|
# Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
# Use non-docker builds atm. to install libuEv and libite from source
|
||||||
|
#sudo: true
|
||||||
|
|
||||||
|
# Test build with both GCC and Clang (LLVM)
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
- clang
|
||||||
|
|
||||||
|
# The secure: declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||||
|
# via the "travis encrypt" command using the project repo's public key
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- PKG_CONFIG_PATH=/tmp/lib/pkgconfig
|
||||||
|
- CFLAGS="-W -Wall -Wextra"
|
||||||
|
- secure: "eOiuHs02lG2Uv146K9dMqucGTWUJFEhpz1oAtwe+kPrRXsXWc20hYMO+DSpMgD05vSvNeQA6p7h7LdRFQ+/g/Obj27TsOE+RKkUvRAtdwzxnKVyii9C/nmML8cFw7rIA0VS8O9mAkVYeyDxNDupBp3e9DPCibhKPvqCvioTnyy4="
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- tree
|
||||||
|
coverity_scan:
|
||||||
|
project:
|
||||||
|
name: "troglobit/finit"
|
||||||
|
description: "finit | Fast & Extensible init for Linux"
|
||||||
|
notification_email: troglobit@gmail.com
|
||||||
|
build_command_prepend: "./autogen.sh && ./configure --prefix=/tmp"
|
||||||
|
build_command: "make"
|
||||||
|
branch_pattern: dev
|
||||||
|
|
||||||
|
install:
|
||||||
|
- wget https://github.com/troglobit/libuev/releases/download/v2.3.2/libuev-2.3.2.tar.xz
|
||||||
|
- wget https://github.com/troglobit/libite/releases/download/v2.3.1/libite-2.3.1.tar.gz
|
||||||
|
- tar xf libuev-2.3.2.tar.xz
|
||||||
|
- tar xf libite-2.3.1.tar.gz
|
||||||
|
- (cd libuev-2.3.2 && ./configure --prefix=/tmp && make && make install-strip)
|
||||||
|
- (cd libite-2.3.1 && ./configure --prefix=/tmp && make && make install-strip)
|
||||||
|
|
||||||
|
# Custom build script for the time being, no "make test" yet
|
||||||
|
script:
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure --prefix=/tmp --enable-static
|
||||||
|
- make clean
|
||||||
|
- make V=1 -j5
|
||||||
|
- ./configure --prefix=/tmp --enable-x11-common-plugin --enable-fallback-shell --enable-watchdog --enable-logit
|
||||||
|
- cat config.log
|
||||||
|
- make clean
|
||||||
|
- make V=1 -j5
|
||||||
|
- make install-strip
|
||||||
|
- tree /tmp
|
||||||
|
- ldd /tmp/sbin/finit
|
||||||
|
- size /tmp/sbin/finit
|
||||||
|
- size /tmp/sbin/initctl
|
||||||
|
- size /tmp/sbin/reboot
|
||||||
|
- LD_LIBRARY_PATH=/tmp/lib /tmp/sbin/initctl -h
|
||||||
|
- unshare -V
|
||||||
|
- nsenter -V
|
||||||
|
- chroot --version
|
||||||
|
- 'LD_LIBRARY_PATH=/tmp/lib make distcheck || (cat finit-4.0-beta1/_build/sub/test/test-suite.log; exit 1)'
|
||||||
+55
-1014
File diff suppressed because it is too large
Load Diff
@@ -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-2024 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2021 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
|
||||||
|
|||||||
+16
-20
@@ -1,5 +1,5 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = man plugins src system tmpfiles.d
|
SUBDIRS = plugins src test
|
||||||
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,22 +9,7 @@ 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
|
|
||||||
bashdir = $(BASH_DIR)
|
|
||||||
dist_bash_DATA = initctl
|
|
||||||
endif
|
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
@@ -45,7 +30,18 @@ release: distcheck
|
|||||||
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
||||||
done
|
done
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
run:
|
||||||
--enable-testserv-plugin --enable-x11-common-plugin \
|
srcdir=@srcdir@/test \
|
||||||
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
top_builddir=@top_builddir@ \
|
||||||
--with-bash-completion-dir=no
|
TENV_ROOT=$(tenv_root) \
|
||||||
|
@srcdir@/test/setup-root.sh
|
||||||
|
|
||||||
|
mkdir -p $(dir $(tenv_root)/@FINIT_CONF@)
|
||||||
|
echo 'tty [12345] @console linux noclear nologin' > $(tenv_root)/@FINIT_CONF@
|
||||||
|
|
||||||
|
-TENV_ROOT=$(tenv_root) \
|
||||||
|
TESTENV_PATH=@sbindir@:/bin \
|
||||||
|
FINIT_RCSD=@FINIT_RCSD@ \
|
||||||
|
test/tenv/start.sh finit
|
||||||
|
|
||||||
|
run : tenv_root ?= @abs_top_builddir@/run-rootfs
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
[![License Badge][]][License] [![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
|
||||||
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
|
* [Bootstrap](doc/bootstrap.md#bootstrap)
|
||||||
* [Runlevels](#runlevels)
|
* [Runlevels](#runlevels)
|
||||||
* [Syntax](doc/config.md#syntax)
|
* [Syntax](doc/config.md#syntax)
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
||||||
@@ -21,53 +22,20 @@
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Fast init for Linux systems. Reverse engineered from the [EeePC
|
Finit is a simple alternative to [SysV init][4] and [systemd][6]. It
|
||||||
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
was reverse engineered from the [EeePC fastinit][] over ten years ago
|
||||||
|
by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
||||||

|
|
||||||
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
|
|
||||||
|
|
||||||
Features include:
|
|
||||||
|
|
||||||
* Runlevels, defined per service
|
|
||||||
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
|
||||||
* Runparts and `/etc/rc.local` support
|
|
||||||
* Process supervision similar to [systemd][]
|
|
||||||
* Sourcing environment files
|
|
||||||
* Conditions for network/process/custom dependencies
|
|
||||||
* Readiness notification; PID files (native) for synchronizing system
|
|
||||||
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
|
||||||
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
|
||||||
* Pre/Post script actions
|
|
||||||
* Rudimentary [templating support](doc/config.md#templating)
|
|
||||||
* Tooling to enable/disable services
|
|
||||||
* Built-in getty
|
|
||||||
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
|
||||||
* Built-in support for Debian/BusyBox `/etc/network/interfaces`
|
|
||||||
* Cgroups v2, both configuration and monitoring in `initctl top`
|
|
||||||
* Plugin support for customization
|
|
||||||
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
|
||||||
* Integration with [watchdogd][] for full system supervision
|
|
||||||
* Logging to kernel ring buffer before `syslogd` has started, see the
|
|
||||||
recommended [sysklogd][] project for complete logging integration
|
|
||||||
and how to log to the kernel ring buffer from scripts using `logger`
|
|
||||||
|
|
||||||
Focus is on small and embedded systems, although Finit is fully usable
|
Focus is on small and embedded systems, although Finit is fully usable
|
||||||
on server and desktop systems as well. For working examples, see the
|
on server and desktop systems as well. For working examples, see the
|
||||||
[contrib/](contrib/) section with tutorials for the following Linux
|
[contrib/](contrib/) section with tutorials for:
|
||||||
distributions:
|
|
||||||
|
|
||||||
* [Void Linux](contrib/void/),
|
* [Void Linux](contrib/void/),
|
||||||
* [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/)
|
||||||
|
|
||||||
> [!NOTE]
|

|
||||||
> Support for various Linux distributions does not mean Finit installs
|
The screenshot shows [Alpine Linux](https://www.alpinelinux.org/).
|
||||||
> easily on all architectures. The bundled install scripts are examples
|
|
||||||
> for standard installations, tested on amd64 (x86_64) systems. Custom
|
|
||||||
> setups, e.g., for embedded systems, can be found in the following
|
|
||||||
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
|
||||||
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -76,36 +44,24 @@ Example
|
|||||||
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
||||||
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
||||||
be placed in `/etc/finit.d/available` and enabled by an operator using
|
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.
|
||||||
distributions, or [myLinux][].
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> As of Finit v4.4, `.conf` lines can be broken up using the standard
|
|
||||||
> UNIX continuation character (`\`), trailing comments are now also
|
|
||||||
> supported. The latter means you need to escape any hashes used in
|
|
||||||
> directives and descriptions (`\#`). For more on this and examples,
|
|
||||||
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
|
||||||
|
|
||||||
```ApacheConf
|
```ApacheConf
|
||||||
# Fallback if /etc/hostname is missing
|
# Fallback if /etc/hostname is missing
|
||||||
host default
|
host default
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, 'S', default: 2
|
# Runlevel to start after bootstrap, 'S', default: 2
|
||||||
#runlevel 2
|
runlevel 2
|
||||||
|
|
||||||
# Support for setting global environment variables, using foo=bar syntax
|
|
||||||
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
|
|
||||||
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
||||||
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
||||||
log size=100k count=4
|
log size=100k count=4
|
||||||
|
|
||||||
# Services to be monitored and respawned as needed
|
# Services to be monitored and respawned as needed
|
||||||
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon
|
service [S12345] watchdogd -L -f -- System watchdog daemon
|
||||||
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon
|
service [S12345] syslogd -n -b 3 -D -- System log daemon
|
||||||
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
service [S12345] <pid/syslogd> klogd -n -- Kernel log daemon
|
||||||
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab)
|
service [2345] lldpd -d -c -M1 -H0 -i -- LLDP daemon (IEEE 802.1ab)
|
||||||
|
|
||||||
# The BusyBox ntpd does not use syslog when running in the foreground
|
# The BusyBox ntpd does not use syslog when running in the foreground
|
||||||
# So we use this trick to redirect stdout/stderr to a log file. The
|
# So we use this trick to redirect stdout/stderr to a log file. The
|
||||||
@@ -120,29 +76,24 @@ service :80 [2345] merecat -n -p 80 /var/www -- Web server
|
|||||||
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
||||||
|
|
||||||
# Alternative method instead of below runparts, can also use /etc/rc.local
|
# Alternative method instead of below runparts, can also use /etc/rc.local
|
||||||
#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap
|
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
||||||
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
#task [S] /etc/init.d/kbd -- Preparing console
|
#task [S] /etc/init.d/kbd start -- Preparing console
|
||||||
|
|
||||||
# Hidden from boot progress, using empty `--` description
|
|
||||||
#sysv [S] /etc/init.d/keyboard-setup --
|
|
||||||
#sysv [S] /etc/init.d/acpid --
|
|
||||||
#task [S] /etc/init.d/kbd --
|
|
||||||
|
|
||||||
# Run start scripts from this directory
|
# Run start scripts from this directory
|
||||||
# runparts /etc/start.d
|
# runparts /etc/start.d
|
||||||
|
|
||||||
# Virtual consoles run BusyBox getty, keep kernel default speed
|
# Virtual consoles run BusyBox getty, keep kernel default speed
|
||||||
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear
|
tty [12345] /sbin/getty -L 0 /dev/tty1 linux
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear
|
tty [12345] /sbin/getty -L 0 /dev/tty2 linux
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear
|
tty [12345] /sbin/getty -L 0 /dev/tty3 linux
|
||||||
|
|
||||||
# Use built-in getty for serial port and USB serial
|
# Use built-in getty for serial port and USB serial
|
||||||
#tty [12345] /dev/ttyAMA0 noclear nowait
|
tty [12345] /dev/ttyAMA0 noclear nowait
|
||||||
#tty [12345] /dev/ttyUSB0 noclear
|
tty [12345] /dev/ttyUSB0 noclear
|
||||||
|
|
||||||
# Just give me a shell, I need to debug this embedded system!
|
# Just give me a shell, I need to debug this embedded system!
|
||||||
#tty [12345] console noclear nologin
|
tty [12345] @console noclear nologin
|
||||||
```
|
```
|
||||||
|
|
||||||
The `service` stanza, as well as `task`, `run` and others are described
|
The `service` stanza, as well as `task`, `run` and others are described
|
||||||
@@ -151,10 +102,10 @@ some of the most common components needed to start a UNIX daemon:
|
|||||||
|
|
||||||
```
|
```
|
||||||
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
||||||
^ ^ ^ ^ ^ ^ ^ ^
|
^ ^ ^ ^ ^ ^ ^ ^
|
||||||
| | | | | | | `---------- Optional description
|
| | | | | | | `-- Optional description
|
||||||
| | | | | | `------------------ Daemon arguments
|
| | | | | | `----------- Daemon arguments
|
||||||
| | | | | `------------------------- Path to daemon
|
| | | | | `-------------------------- Path to daemon
|
||||||
| | | | `---------------------------------------------------- Optional env. file
|
| | | | `---------------------------------------------------- Optional env. file
|
||||||
| | | `-------------------------------------------------------- Redirect output to log
|
| | | `-------------------------------------------------------- Redirect output to log
|
||||||
| | `--------------------------------------------------------------- Optional conditions
|
| | `--------------------------------------------------------------- Optional conditions
|
||||||
@@ -166,13 +117,13 @@ Some components are optional: runlevel(s), condition(s) and description,
|
|||||||
making it easy to create simple start scripts and still possible for more
|
making it easy to create simple start scripts and still possible for more
|
||||||
advanced uses as well:
|
advanced uses as well:
|
||||||
|
|
||||||
service /usr/sbin/sshd -D
|
service sshd -D
|
||||||
|
|
||||||
Dependencies are handled using [conditions](doc/conditions.md). One of
|
Dependencies are handled using [conditions](doc/conditions.md). One of
|
||||||
the most common conditions is to wait for basic networking to become
|
the most common conditions is to wait for basic networking to become
|
||||||
available:
|
available:
|
||||||
|
|
||||||
service <net/route/default> nginx -- High performance HTTP server
|
service <net/route/default> nginx -- High performace HTTP server
|
||||||
|
|
||||||
Here is another example where we instruct Finit to not start BusyBox
|
Here is another example where we instruct Finit to not start BusyBox
|
||||||
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
||||||
@@ -247,49 +198,11 @@ networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
|||||||
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
||||||
given on the kernel cmdline, in which case runlevel 1 is started.
|
given on the kernel cmdline, in which case runlevel 1 is started.
|
||||||
|
|
||||||
All services in runlevel S) are started first, followed by the desired
|
All services in runlevel S(0) 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
|
||||||
[`initctl`](#commands--status) tool.
|
`intictl` tool.
|
||||||
|
|
||||||
|
|
||||||
**Conditions**
|
|
||||||
|
|
||||||
As mentioned previously, Finit has an advanced dependency system to
|
|
||||||
handle synchronization, called [conditions](doc/conditions.md). It can
|
|
||||||
be used in many ways; depend on another service, network availability,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
One *really cool* example useful for embedded systems is to run certain
|
|
||||||
scripts if a board has a certain feature encoded in its device tree. At
|
|
||||||
bootstrap we run the following `ident` script:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
#!/bin/sh
|
|
||||||
conddir=/var/run/finit/cond/hw/model
|
|
||||||
dtmodel=/sys/firmware/devicetree/base/model
|
|
||||||
|
|
||||||
if ! test -e $dtmodel; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
model=$(cat $dtmodel | tr "[A-Z] " "[a-z]-")
|
|
||||||
mkdir -p $conddir && ln -s ../../reconf $conddir/$model
|
|
||||||
```
|
|
||||||
|
|
||||||
Provided the device tree node exists, and is a string, we can then use
|
|
||||||
the condition `<hw/model/foo>` when starting other scripts. Here is an
|
|
||||||
example:
|
|
||||||
|
|
||||||
```
|
|
||||||
run [S] /path/to/ident --
|
|
||||||
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
|
||||||
```
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> Notice the trick with an empty description to hide the call to `ident`
|
|
||||||
> in the Finit progress output.
|
|
||||||
|
|
||||||
|
|
||||||
**Plugins**
|
**Plugins**
|
||||||
@@ -319,11 +232,8 @@ For more information, see [doc/plugins.md](doc/plugins.md).
|
|||||||
By default, Finit monitors `/etc/finit.d/` and `/etc/finit.d/enabled/`
|
By default, Finit monitors `/etc/finit.d/` and `/etc/finit.d/enabled/`
|
||||||
registering any changes to `.conf` files. To activate a change the user
|
registering any changes to `.conf` files. To activate a change the user
|
||||||
must call `initctl reload`, which reloads all modified files, stops any
|
must call `initctl reload`, which reloads all modified files, stops any
|
||||||
removed services, starts new ones, and restarts any modified ones. If the
|
removed services, starts new ones, and restarts any modified ones, with
|
||||||
command line arguments of a service have changed, the process will be
|
SIGHUP if the process supports it.
|
||||||
terminated and then started again with the updated arguments. If the arguments
|
|
||||||
have not been modified and the process supports SIGHUP, the process will
|
|
||||||
receive a SIGHUP rather than being terminated and started.
|
|
||||||
|
|
||||||
For some use-cases the extra step of calling `initctl reload` creates an
|
For some use-cases the extra step of calling `initctl reload` creates an
|
||||||
unnecessary overhead, which can be removed at build-time using:
|
unnecessary overhead, which can be removed at build-time using:
|
||||||
@@ -331,51 +241,6 @@ unnecessary overhead, which can be removed at build-time using:
|
|||||||
configure --enable-auto-reload
|
configure --enable-auto-reload
|
||||||
|
|
||||||
|
|
||||||
**Cgroups**
|
|
||||||
|
|
||||||
Finit supports cgroups v2 and comes with the following default groups in
|
|
||||||
which services and user sessions are placed in:
|
|
||||||
|
|
||||||
/sys/fs/cgroup
|
|
||||||
|-- init/ # cpu.weight:100
|
|
||||||
|-- system/ # cpu.weight:9800
|
|
||||||
`-- user/ # cpu.weight:100
|
|
||||||
|
|
||||||
Finit itself and its helper scripts and services are placed in the
|
|
||||||
top-level leaf-node group `init/`, which also is _reserved_.
|
|
||||||
|
|
||||||
All run/task/service/sysv processes are placed in their own sub-group
|
|
||||||
in `system/`. The name of each sub-group is taken from the respective
|
|
||||||
`.conf` file from `/etc/finit.d`.
|
|
||||||
|
|
||||||
All getty/tty processes are placed in their own sub-group in `user/`.
|
|
||||||
The name of each sub-group is taken from the username.
|
|
||||||
|
|
||||||
A fourth group also exists, the `root` group. It is also _reserved_ and
|
|
||||||
primarily intended for RT tasks. If you have RT tasks they need to be
|
|
||||||
declared as such in their service stanza like this:
|
|
||||||
|
|
||||||
service [...] <...> cgroup.root /path/to/foo args -- description
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
cgroup.root
|
|
||||||
service [...] <...> /path/to/foo args -- description
|
|
||||||
service [...] <...> /path/to/bar args -- description
|
|
||||||
|
|
||||||
See [doc/config.md](doc/config.md#cgroups) for more information, e.g.,
|
|
||||||
how to configure per-group limits.
|
|
||||||
|
|
||||||
The `initctl` tool has three commands to help debug and optimize the
|
|
||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
|
||||||
commands for details.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Systems that do not support cgroups, specifically version 2, are
|
|
||||||
> automatically detected. On such systems the above functionality is
|
|
||||||
> disabled early at boot.
|
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
Runparts & /etc/rc.local
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -395,33 +260,8 @@ Right after the runlevel change when all services have started properly,
|
|||||||
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
If it exists and is an executable shell script Finit calls it at the very
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
||||||
in [doc/plugins.md](doc/plugins.md#hooks).
|
in [doc/plugins.md](doc/plugins.md#hooks), and about the system bootstrap
|
||||||
|
in [doc/bootstrap.md](doc/bootstrap.md).
|
||||||
|
|
||||||
### Limitations
|
|
||||||
|
|
||||||
It is not possible to call Finit via signals or use `initctl` in any
|
|
||||||
runparts or `/etc/rc.local` script. This because Finit is single
|
|
||||||
threaded and is calling these scripts in a blocking fashion at the end
|
|
||||||
of runlevel S, at which point the event loop has not yet been started.
|
|
||||||
|
|
||||||
The event loop is the whole thing which Finit is built around, except
|
|
||||||
for runlevel S, which remains a slow procession through a lot of set up,
|
|
||||||
with a few hooks and blocking call outs to external scripts.
|
|
||||||
|
|
||||||
However, not all `initctl` commands are prohibited. Supported commands:
|
|
||||||
|
|
||||||
- `inictl cond`: only operate of files in `/run/finit/cond`
|
|
||||||
- `initctl enable/disable`: enabled run/task/service is activated on
|
|
||||||
the runlevel change from S to 2
|
|
||||||
- `initctl touch/show/create/delete/list`: `create`, provided the
|
|
||||||
non-interactive mode is used, again changes take effect in the
|
|
||||||
runlevel change directly after bootstrap
|
|
||||||
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
|
||||||
force direct kernel commands
|
|
||||||
|
|
||||||
**Example:** you can set a `usr/` condition in `/etc/rc.local` and have
|
|
||||||
a service/task in runlevel 2 depend on it to execute.
|
|
||||||
|
|
||||||
|
|
||||||
Runlevels
|
Runlevels
|
||||||
@@ -508,67 +348,40 @@ Finit also implements a modern API to query status, and start/stop
|
|||||||
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
||||||
not return until the given command has fully completed.
|
not return until the given command has fully completed.
|
||||||
|
|
||||||
```
|
```shell
|
||||||
|
~ $ initctl -h
|
||||||
Usage: initctl [OPTIONS] [COMMAND]
|
Usage: initctl [OPTIONS] [COMMAND]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-b, --batch Batch mode, no screen size probing
|
|
||||||
-c, --create Create missing paths (and files) as needed
|
|
||||||
-f, --force Ignore missing files and arguments, never prompt
|
|
||||||
-h, --help This help text
|
|
||||||
-j, --json JSON output in 'status' and 'cond' commands
|
|
||||||
-1, --once Only one lap in commands like 'top'
|
|
||||||
-p, --plain Use plain table headings, no ctrl chars
|
|
||||||
-q, --quiet Silent, only return status of command
|
|
||||||
-t, --no-heading Skip table headings
|
|
||||||
-v, --verbose Verbose output
|
-v, --verbose Verbose output
|
||||||
-V, --version Show program version
|
-h, --help This help text
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
debug Toggle Finit (daemon) debug
|
debug Toggle Finit (daemon) debug
|
||||||
help This help text
|
help This help text
|
||||||
version Show program version
|
version Show Finit version
|
||||||
|
|
||||||
ls | list List all .conf in /etc/finit.d
|
list List all .conf in /etc/finit.d/
|
||||||
create <CONF> Create .conf in /etc/finit.d/available
|
enable <CONF> Enable .conf in /etc/finit.d/available/
|
||||||
delete <CONF> Delete .conf in /etc/finit.d/available
|
disable <CONF> Disable .conf in /etc/finit.d/[enabled/]
|
||||||
show <CONF> Show .conf in /etc/finit.d/available
|
touch <CONF> Mark .conf in /etc/finit.d/ for reload
|
||||||
edit <CONF> Edit .conf in /etc/finit.d/available
|
reload Reload *.conf in /etc/finit.d/ (activates changes)
|
||||||
touch <CONF> Change .conf in /etc/finit.d/available
|
|
||||||
enable <CONF> Enable .conf in /etc/finit.d/available
|
cond show Show condition status
|
||||||
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
cond dump Dump all conditions and their status
|
||||||
reload Reload *.conf in /etc/finit.d (activate changes)
|
|
||||||
|
|
||||||
cond set <COND> Set (assert) user-defined conditions +usr/COND
|
|
||||||
cond get <COND> Get status of user-defined condition, see $? and -v
|
|
||||||
cond clear <COND> Clear (deassert) user-defined conditions -usr/COND
|
|
||||||
cond status Show condition status, default cond command
|
|
||||||
cond dump [TYPE] Dump all, or a type of, conditions and their status
|
|
||||||
|
|
||||||
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
||||||
start <NAME>[:ID] Start service by name, with optional ID
|
start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
|
||||||
stop <NAME>[:ID] Stop/Pause a running service by name
|
stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
|
||||||
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
|
restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
|
||||||
This allows restart of run/tasks that have already run
|
status <JOB|NAME>[:ID] Show service status, by job# or name
|
||||||
Note: Finit .conf file(s) are *not* reloaded!
|
status | show Show status of services, default command
|
||||||
restart <NAME>[:ID] Restart (stop/start) service by name
|
|
||||||
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
|
|
||||||
ident [NAME] Show matching identities for NAME, or all
|
|
||||||
status <NAME>[:ID] Show service status, by name
|
|
||||||
status Show status of services, default command
|
|
||||||
|
|
||||||
cgroup List cgroup config overview
|
|
||||||
ps List processes based on cgroups
|
|
||||||
top Show top-like listing based on cgroups
|
|
||||||
|
|
||||||
plugins List installed plugins
|
|
||||||
|
|
||||||
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
||||||
reboot Reboot system
|
reboot Reboot system
|
||||||
halt Halt system
|
halt Halt system
|
||||||
poweroff Halt and power off system
|
poweroff Halt and power off system
|
||||||
suspend Suspend system
|
|
||||||
|
|
||||||
utmp show Raw dump of UTMP/WTMP db
|
utmp show Raw dump of UTMP/WTMP db
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -577,74 +390,22 @@ 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]
|
**Note:** even though it is possible to start services not belonging in
|
||||||
> Even though it is possible to start services not belonging in the
|
the current runlevel these services will not be respawned automatically
|
||||||
> current runlevel these services will not be respawned automatically by
|
by Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
||||||
> 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
|
```shell
|
||||||
monitored run/task/services. Here we call `initctl -p`, suitable for
|
~ $ initctl status -v
|
||||||
scripting and documentation:
|
1 running 476 [S12345] /sbin/watchdog -T 16 -t 2 -F /dev/watchdog
|
||||||
|
2 running 477 [S12345] /sbin/syslogd -n -b 3 -D
|
||||||
```
|
3 running 478 [S12345] /sbin/klogd -n
|
||||||
alpine:~# initctl -p
|
4:1 inetd 0 [2345] internal time allow *:37,!eth0
|
||||||
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
4:2 inetd 0 [2345] internal time allow eth0:3737
|
||||||
======================================================================
|
5:1 inetd 0 [2345] /sbin/telnetd allow *:23 deny eth0,eth1
|
||||||
1506 acpid running [---2345----] ACPI daemon
|
5:2 inetd 0 [2345] /sbin/telnetd allow eth0:2323,eth2:2323,eth1:2323
|
||||||
1509 crond running [---2345----] Cron daemon
|
6:1 inetd 0 [345] /sbin/dropbear allow eth0:222
|
||||||
1489 dropbear running [---2345----] Dropbear SSH daemon
|
6:2 inetd 0 [345] /sbin/dropbear allow *:22 deny eth0
|
||||||
1511 klogd running [S-12345----] Kernel log daemon
|
|
||||||
1512 ntpd running [---2345----] NTP daemon
|
|
||||||
1473 syslogd running [S-12345----] Syslog daemon
|
|
||||||
|
|
||||||
alpine:~# initctl -pv
|
|
||||||
PID IDENT STATUS RUNLEVELS COMMAND
|
|
||||||
======================================================================
|
|
||||||
1506 acpid running [---2345----] acpid -f
|
|
||||||
1509 crond running [---2345----] crond -f -S $CRON_OPTS
|
|
||||||
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
|
|
||||||
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
|
|
||||||
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
|
|
||||||
1473 syslogd running [S-12345----] syslogd -n
|
|
||||||
```
|
|
||||||
|
|
||||||
The environment variables to each of the services above are read from,
|
|
||||||
in the case of Alpine Linux, `/etc/conf.d/`. Other distributions may
|
|
||||||
have other directories, e.g., Debian use `/etc/default/`.
|
|
||||||
|
|
||||||
The `status` command takes an optional `NAME:ID` argument. Here we
|
|
||||||
check the status of `dropbear`, which only has one instance in this
|
|
||||||
system:
|
|
||||||
|
|
||||||
```
|
|
||||||
alpine:~# initctl -p status dropbear
|
|
||||||
Status : running
|
|
||||||
Identity : dropbear
|
|
||||||
Description : Dropbear SSH daemon
|
|
||||||
Origin : /etc/finit.d/enabled/dropbear.conf
|
|
||||||
Environment : -/etc/conf.d/dropbear
|
|
||||||
Condition(s):
|
|
||||||
Command : dropbear -R -F $DROPBEAR_OPTS
|
|
||||||
PID file : !/run/dropbear.pid
|
|
||||||
PID : 1485
|
|
||||||
User : root
|
|
||||||
Group : root
|
|
||||||
Uptime : 2 hour 46 min 56 sec
|
|
||||||
Runlevels : [---2345----]
|
|
||||||
Memory : 1.2M
|
|
||||||
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
|
||||||
|- 1485 dropbear -R -F
|
|
||||||
|- 2634 dropbear -R -F
|
|
||||||
|- 2635 ash
|
|
||||||
`- 2652 initctl -p status dropbear
|
|
||||||
|
|
||||||
Apr 8 12:19:49 alpine authpriv.info dropbear[1485]: Not backgrounding
|
|
||||||
Apr 8 12:37:45 alpine authpriv.info dropbear[2300]: Child connection from 192.168.121.1:47834
|
|
||||||
Apr 8 12:37:46 alpine authpriv.notice dropbear[2300]: Password auth succeeded for 'root' from 192.168.121.1:47834
|
|
||||||
Apr 8 12:37:46 alpine authpriv.info dropbear[2300]: Exit (root) from <192.168.121.1:47834>: Disconnect received
|
|
||||||
Apr 8 15:02:11 alpine authpriv.info dropbear[2634]: Child connection from 192.168.121.1:48576
|
|
||||||
Apr 8 15:02:12 alpine authpriv.notice dropbear[2634]: Password auth succeeded for 'root' from 192.168.121.1:48576
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -682,43 +443,36 @@ This project is based on the [original finit][] by [Claudio Matsuoka][]
|
|||||||
which was reverse engineered from syscalls of the [EeePC fastinit][] —
|
which was reverse engineered from syscalls of the [EeePC fastinit][] —
|
||||||
"gaps filled with frog DNA …"
|
"gaps filled with frog DNA …"
|
||||||
|
|
||||||
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][6].
|
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][].
|
||||||
Please file bug reports, clone it, or send pull requests for bug fixes
|
Please file bug reports, clone it, or send pull requests for bug fixes
|
||||||
and proposed extensions.
|
and proposed extensions.
|
||||||
|
|
||||||
|
|
||||||
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
||||||
[2]: https://cr.yp.to/daemontools.html
|
[2]: http://cr.yp.to/daemontools.html
|
||||||
[3]: https://smarden.org/runit/
|
[3]: http://smarden.org/runit/
|
||||||
[4]: https://en.wikipedia.org/wiki/Init
|
[4]: http://en.wikipedia.org/wiki/Init
|
||||||
[5]: https://en.wikipedia.org/wiki/Runlevel
|
[5]: http://en.wikipedia.org/wiki/Runlevel
|
||||||
[6]: https://github.com/troglobit/finit
|
[6]: https://www.freedesktop.org/wiki/Software/systemd/
|
||||||
|
[9]: https://github.com/troglobit/troglos
|
||||||
[RFC862]: https://tools.ietf.org/html/rfc862
|
[RFC862]: https://tools.ietf.org/html/rfc862
|
||||||
[RFC863]: https://tools.ietf.org/html/rfc863
|
[RFC863]: https://tools.ietf.org/html/rfc863
|
||||||
[RFC864]: https://tools.ietf.org/html/rfc864
|
[RFC864]: https://tools.ietf.org/html/rfc864
|
||||||
[RFC867]: https://tools.ietf.org/html/rfc867
|
[RFC867]: https://tools.ietf.org/html/rfc867
|
||||||
[RFC868]: https://tools.ietf.org/html/rfc868
|
[RFC868]: https://tools.ietf.org/html/rfc868
|
||||||
[init]: https://en.wikipedia.org/wiki/Init
|
[init]: http://en.wikipedia.org/wiki/Init
|
||||||
[upstart]: https://upstart.ubuntu.com/
|
[upstart]: http://upstart.ubuntu.com/
|
||||||
[systemd]: https://www.freedesktop.org/wiki/Software/systemd/
|
[systemd]: http://www.freedesktop.org/wiki/Software/systemd/
|
||||||
[openrc]: https://www.gentoo.org/proj/en/base/openrc/
|
[openrc]: http://www.gentoo.org/proj/en/base/openrc/
|
||||||
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
[s6 style]: https://skarnet.org/software/s6/notifywhenup.html
|
|
||||||
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
||||||
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
|
||||||
[original finit]: http://helllabs.org/finit/
|
[original finit]: http://helllabs.org/finit/
|
||||||
[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]: http://troglobit.com
|
||||||
[Buildroot]: https://buildroot.org
|
[GitHub]: https://github.com/troglobit/finit
|
||||||
[Infix]: https://kernelkit.github.io
|
|
||||||
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
|
||||||
[License]: https://en.wikipedia.org/wiki/MIT_License
|
[License]: 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
|
||||||
[myLinux]: https://github.com/troglobit/myLinux/
|
[Travis]: https://travis-ci.org/troglobit/finit
|
||||||
[watchdogd]: https://github.com/troglobit/watchdogd/
|
[Travis Status]: https://travis-ci.org/troglobit/finit.png?branch=master
|
||||||
[sysklogd]: https://github.com/troglobit/sysklogd/
|
|
||||||
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
|
||||||
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
|
||||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||||
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# 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
|
|
||||||
fi
|
|
||||||
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
|
||||||
--enable-x11-common-plugin --with-watchdog --with-keventd \
|
|
||||||
CFLAGS='-fsanitize=address -ggdb'
|
|
||||||
|
|
||||||
if [ "$run_make" -eq 1 ]; then
|
|
||||||
make -j"$jobs" clean check
|
|
||||||
fi
|
|
||||||
+67
-234
@@ -1,25 +1,20 @@
|
|||||||
AC_INIT([Finit], [4.13-pre], [https://github.com/troglobit/finit/issues],
|
AC_INIT(Finit, 4.0-rc1, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
||||||
[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])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/finit.c])
|
AC_CONFIG_SRCDIR([src/finit.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADER([config.h])
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
||||||
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile
|
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile contrib/debian/grub.d/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
|
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
system/Makefile system/10-hotplug.conf
|
test/test.env
|
||||||
test/test.env test/Makefile
|
test/Makefile])
|
||||||
test/lib/Makefile test/src/Makefile
|
|
||||||
tmpfiles.d/Makefile])
|
|
||||||
|
|
||||||
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
||||||
#m4_include([m4/plugin.m4])
|
#m4_include([m4/plugin.m4])
|
||||||
@@ -36,8 +31,9 @@ AC_PROG_INSTALL
|
|||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
|
|
||||||
# Configuration.
|
# Configuration.
|
||||||
AC_CHECK_HEADERS([termios.h sys/ioctl.h mntent.h sys/sysmacros.h])
|
AC_HEADER_STDC
|
||||||
AC_CHECK_FUNCS([strstr getopt getmntent getmntent_r])
|
AC_CHECK_HEADERS([fstaby.h termios.h])
|
||||||
|
AC_CHECK_FUNCS([strstr getopt getfsenty])
|
||||||
|
|
||||||
# Check for uint[8,16,32]_t
|
# Check for uint[8,16,32]_t
|
||||||
AC_TYPE_UINT8_T
|
AC_TYPE_UINT8_T
|
||||||
@@ -52,36 +48,33 @@ PKG_CHECK_MODULES([uev], [libuev >= 2.2.0])
|
|||||||
PKG_CHECK_MODULES([lite], [libite >= 2.2.0])
|
PKG_CHECK_MODULES([lite], [libite >= 2.2.0])
|
||||||
|
|
||||||
# Check for configured Finit features
|
# Check for configured Finit features
|
||||||
|
AC_ARG_ENABLE(emergency_shell,
|
||||||
|
AS_HELP_STRING([--enable-emergency-shell], [Experimental emergency fallback at boot.
|
||||||
|
Use only for debugging very early boot problems with Finit]),,[
|
||||||
|
enable_emergency_shell=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(fallback_shell,
|
||||||
|
AS_HELP_STRING([--enable-fallback-shell], [Start a shell if no TTYs can start]),,[
|
||||||
|
enable_fallback_shell=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(auto_reload,
|
AC_ARG_ENABLE(auto_reload,
|
||||||
AS_HELP_STRING([--enable-auto-reload], [Automatic reload on any .conf change]),,[
|
AS_HELP_STRING([--enable-auto-reload], [Automatic reload on any .conf change]),,[
|
||||||
enable_auto_reload=no])
|
enable_auto_reload=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(kernel_cmdline,
|
AC_ARG_ENABLE(watchdog,
|
||||||
AS_HELP_STRING([--enable-kernel-cmdline], [Parse init args from /proc/cmdline (don't use!)]),,[
|
AS_HELP_STRING([--enable-watchdog], [Enable built-in watchdog, uses /dev/watchdog]),,[
|
||||||
enable_kernel_cmdline=no])
|
enable_watchdog=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(fastboot,
|
|
||||||
AS_HELP_STRING([--enable-fastboot], [Skip fsck check on filesystems listed in /etc/fstab]),,[
|
|
||||||
enable_fastboot=no])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(fsckfix,
|
|
||||||
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
|
|
||||||
enable_fsckfix=no])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(cgroup,
|
|
||||||
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
|
|
||||||
enable_cgroup=yes])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(redirect,
|
AC_ARG_ENABLE(redirect,
|
||||||
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
AS_HELP_STRING([--enable-redirect], [Redirect service output to /dev/null, default: no]),,[
|
||||||
enable_redirect=yes])
|
enable_redirect_output=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(kernel_logging,
|
AC_ARG_ENABLE(logit,
|
||||||
AS_HELP_STRING([--disable-kernel-logging], [Disable kernel logging to console (use 'quiet' instead!]),,[
|
AS_HELP_STRING([--disable-logit], [Disable logit, used for log redirection, default: enable]),,[
|
||||||
enable_kernel_logging=yes])
|
enable_logit=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, default enabled]),,[
|
||||||
enable_logrotate=yes])
|
enable_logrotate=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(doc,
|
AC_ARG_ENABLE(doc,
|
||||||
@@ -92,39 +85,19 @@ AC_ARG_ENABLE(contrib,
|
|||||||
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
||||||
enable_contrib=yes])
|
enable_contrib=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE([rescue],
|
|
||||||
AS_HELP_STRING([--disable-rescue], [Disable potentially unsafe rescue mode]),,
|
|
||||||
[enable_rescue=yes])
|
|
||||||
|
|
||||||
# Check for extra plugins to enable
|
# Check for extra plugins to enable
|
||||||
AC_ARG_ENABLE(all_plugins,
|
enable_all_plugins=auto
|
||||||
AS_HELP_STRING([--enable-all-plugins], [Enable all plugins, default: auto]),
|
|
||||||
enable_all_plugins=$enableval, enable_all_plugins=auto)
|
|
||||||
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
||||||
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
||||||
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
||||||
AC_PLUGIN([modprobe], [no], [Coldplug modules using modalias magic])
|
|
||||||
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
||||||
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
||||||
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
||||||
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
|
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
||||||
AC_PLUGIN([hotplug], [yes], [Start udevd or mdev kernel event datamon])
|
|
||||||
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
|
||||||
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
|
||||||
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
|
||||||
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
AC_ARG_WITH([bash-completion-dir],
|
|
||||||
AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Directory to install Bash completion, default: auto]),
|
|
||||||
[bash_dir=$withval], [bash_dir=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(fstab,
|
|
||||||
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
|
|
||||||
[fstab=$withval], [fstab=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(heading,
|
AC_ARG_WITH(heading,
|
||||||
AS_HELP_STRING([--with-heading=GREET], [Heading for boot progress. Default: PRETTY_NAME from /etc/os-release, fallback to "Finit vX.YY"]),
|
AS_HELP_STRING([--with-heading=GREET], [Display GREET instead of Finit version at boot]),
|
||||||
[heading=$withval], [heading=yes])
|
[heading=$withval], [heading=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(config,
|
AC_ARG_WITH(config,
|
||||||
@@ -143,98 +116,44 @@ AC_ARG_WITH(sysconfig,
|
|||||||
AS_HELP_STRING([--with-sysconfig=DIR], [System environment directory, sourced by .conf files, default /etc/default & /etc/conf.d]),
|
AS_HELP_STRING([--with-sysconfig=DIR], [System environment directory, sourced by .conf files, default /etc/default & /etc/conf.d]),
|
||||||
[sysconfig=$withval], [sysconfig=default])
|
[sysconfig=$withval], [sysconfig=default])
|
||||||
|
|
||||||
AC_ARG_WITH(group,
|
|
||||||
AS_HELP_STRING([--with-group=NAME], [Group for /run/finit/socket (initctl), default: root]),
|
|
||||||
[group=$withval], [group=root])
|
|
||||||
|
|
||||||
AC_ARG_WITH(hostname,
|
AC_ARG_WITH(hostname,
|
||||||
AS_HELP_STRING([--with-hostname=NAME], [If /etc/hostname is missing, default: noname]),
|
AS_HELP_STRING([--with-hostname=NAME], [If /etc/hostname is missing, default: noname]),
|
||||||
[hostname=$withval], [hostname=yes])
|
[hostname=$withval], [hostname=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(runlevel,
|
AC_ARG_WITH(runlevel,
|
||||||
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap [1-9], default: 2]),
|
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap, default: 2]),
|
||||||
[runlevel=$withval], [runlevel=yes])
|
[runlevel=$withval], [runlevel=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(random-seed,
|
AC_ARG_WITH(random-seed,
|
||||||
AS_HELP_STRING([--with-random-seed=FILE], [Save a random seed for /dev/urandom across reboots, default /var/lib/misc/random-seed]),
|
AS_HELP_STRING([--with-random-seed=FILE], [Save a random seed for /dev/urandom across reboots, default /var/lib/misc/random-seed]),
|
||||||
[random_seed=$withval], [random_seed=yes])
|
[random_seed=$withval], [random_seed=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(keventd,
|
|
||||||
AS_HELP_STRING([--with-keventd], [Enable built-in keventd, default: no]),, [with_keventd=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH(sulogin,
|
|
||||||
AS_HELP_STRING([--with-sulogin@<:@=USER@:>@], [Enable built-in sulogin, optional USER to request password for (default root), default: no.]),[sulogin=$withval],[with_sulogin=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH(watchdog,
|
|
||||||
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Enable built-in watchdog, default: /dev/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,
|
|
||||||
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])
|
|
||||||
|
|
||||||
AC_ARG_WITH(plugin-path,
|
|
||||||
AS_HELP_STRING([--with-plugin-path=DIR], [Search path for external plugins, default /usr/lib/finit/plugins:/usr/local/lib/finit/plugins]),
|
|
||||||
[plugin_path=$withval], [plugin_path=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-date,
|
|
||||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
|
|
||||||
[rtc_date=$withval], [rtc_date=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-file,
|
|
||||||
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
|
|
||||||
[rtc_file=$withval], [rtc_file=no])
|
|
||||||
|
|
||||||
### Enable features ###########################################################################
|
### Enable features ###########################################################################
|
||||||
|
|
||||||
# Create config.h from selected features and fallback defaults
|
# Create config.h from selected features and fallback defautls
|
||||||
|
AS_IF([test "x$enable_emergency_shell" = "xyes"], [
|
||||||
|
AC_DEFINE(EMERGENCY_SHELL, 1, [Fork off init and let PID 1 wait and start /bin/sh if init crashes.])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_fallback_shell" = "xyes"], [
|
||||||
|
AC_DEFINE(FALLBACK_SHELL, 1, [Start /bin/sh on console if no TTYs.])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
||||||
AC_DEFINE(AUTO_RELOAD, 1, [Finit automatically does `initctl reload` on any .conf change])])
|
AC_DEFINE(AUTO_RELOAD, 1, [Finit automatically does `initctl reload` on any .conf change])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
AS_IF([test "x$enable_watchdog" = "xyes"], [
|
||||||
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
AC_DEFINE(BUILTIN_WATCHDOG, 1, [Enable built-in watchdog, kicks on /dev/watchdog])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_kernel_logging" = "xyes"], [
|
|
||||||
AC_DEFINE(KERNEL_LOGGING, 1, [Keep kernel warn/err logs to console])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_cgroup" = "xyes"], [
|
|
||||||
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
|
||||||
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_fsckfix" = "xyes"], [
|
|
||||||
AC_DEFINE(FSCK_FIX, 1, [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_redirect" = "xyes"], [
|
AS_IF([test "x$enable_redirect" = "xyes"], [
|
||||||
AC_DEFINE(REDIRECT_OUTPUT, 1, [Enable redirection of service output to /dev/null])])
|
AC_DEFINE(REDIRECT_OUTPUT, 1, [Enable redirection of service output to /dev/null])])
|
||||||
|
|
||||||
### Disable features ###########################################################################
|
### Disable features ###########################################################################
|
||||||
|
AS_IF([test "x$enable_logit" != "xno"], [
|
||||||
|
AC_DEFINE(LOGIT_ENABLED, 1, [Enable logit tool, used for log redirection by Finit])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_logrotate" != "xno"], [
|
AS_IF([test "x$enable_logrotate" != "xno"], [
|
||||||
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_rescue" != "xno"], [
|
|
||||||
AC_DEFINE([RESCUE_MODE], 1, [Define to enable support for rescue mode.])])
|
|
||||||
|
|
||||||
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
|
||||||
|
|
||||||
### With features ##############################################################################
|
### With features ##############################################################################
|
||||||
AS_IF([test "x$bash_dir" = "xyes"], [
|
|
||||||
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
|
|
||||||
[BASH_DIR="$(pkg-config --variable=completionsdir bash-completion)"],
|
|
||||||
[BASH_DIR="$datadir/bash-completion/completions"])], [
|
|
||||||
BASH_DIR="$bash_dir"])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_fstab" != "xno"], [
|
|
||||||
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
|
|
||||||
AC_EXPAND_DIR(fstab_path, "$fstab")
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_FSTAB, "$fstab_path", [Built-in default: /etc/fstab])],[
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_FSTAB, NULL, [No built-in default fstab])])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_config" != "xno"], [
|
AS_IF([test "x$with_config" != "xno"], [
|
||||||
AS_IF([test "x$conf" = "xyes"], [
|
AS_IF([test "x$conf" = "xyes"], [
|
||||||
conf=$sysconfdir/finit.conf])])
|
conf=$sysconfdir/finit.conf])])
|
||||||
@@ -250,9 +169,10 @@ 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"], [rclocal=$sysconfdir/rc.local])
|
AS_IF([test "x$rclocal" = "xyes"], [
|
||||||
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
rclocal=$sysconfdir/rc.local])])
|
||||||
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])])
|
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])
|
||||||
|
|
||||||
AS_IF([test "x$with_sysconfig" != "xno"], [
|
AS_IF([test "x$with_sysconfig" != "xno"], [
|
||||||
AS_IF([test "x$sysconfig" != "xdefault"], [
|
AS_IF([test "x$sysconfig" != "xdefault"], [
|
||||||
@@ -261,13 +181,9 @@ AS_IF([test "x$with_sysconfig" != "xno"], [
|
|||||||
[System environment, default /etc/default & /etc/conf.d])])])
|
[System environment, default /etc/default & /etc/conf.d])])])
|
||||||
|
|
||||||
AS_IF([test "x$with_heading" != "xno"], [
|
AS_IF([test "x$with_heading" != "xno"], [
|
||||||
AS_IF([test "x$heading" = "xyes"], [heading=""])
|
AS_IF([test "x$heading" = "xyes"], [
|
||||||
AC_DEFINE_UNQUOTED(INIT_OSHEADING, "$heading", [Displayed by Finit at boot, defaults to /etc/os-release PRETTY_NAME])])
|
heading="$PACKAGE_NAME v$PACKAGE_VERSION"])])
|
||||||
|
AC_DEFINE_UNQUOTED(INIT_HEADING, "$heading", [Displayed by Finit at boot])
|
||||||
AS_IF([test "x$with_group" != "xno"], [
|
|
||||||
AS_IF([test "x$group" = "xyes"], [
|
|
||||||
group=root])])
|
|
||||||
AC_DEFINE_UNQUOTED(DEFGROUP, "$group", [For /run/finit/socket])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_hostname" != "xno"], [
|
AS_IF([test "x$with_hostname" != "xno"], [
|
||||||
AS_IF([test "x$hostname" = "xyes"], [
|
AS_IF([test "x$hostname" = "xyes"], [
|
||||||
@@ -286,100 +202,30 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
|||||||
AC_EXPAND_DIR(random_path, "$random_seed")
|
AC_EXPAND_DIR(random_path, "$random_seed")
|
||||||
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"], [
|
|
||||||
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
|
||||||
rtc_date=""])
|
|
||||||
|
|
||||||
AS_IF([test "x$rtc_file" != "xno"], [
|
|
||||||
AS_IF([test "x$rtc_file" = "xyes"], [
|
|
||||||
rtc_file=/var/lib/misc/rtc])
|
|
||||||
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
|
|
||||||
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
|
|
||||||
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_sulogin" != "xno"], [
|
|
||||||
AS_IF([test "x$sulogin" = "xyes"], [
|
|
||||||
sulogin=root])
|
|
||||||
with_sulogin=yes
|
|
||||||
AC_DEFINE_UNQUOTED(SULOGIN_USER, "$sulogin", [Built-in sulogin user, default: root])], [
|
|
||||||
sulogin=])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_watchdog" != "xno"], [
|
|
||||||
AS_IF([test "x$watchdog" = "xyes"], [
|
|
||||||
watchdog=/dev/watchdog])
|
|
||||||
with_watchdog=yes
|
|
||||||
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
|
||||||
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$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
|
||||||
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
|
||||||
AC_DEFINE_UNQUOTED(PLUGIN_HOOK_SCRIPTS_PATH, "$hook_scripts_path", [Built-in default: $libexecdir/finit])])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_plugin_path" != "xno"], [
|
|
||||||
AS_IF([test "x$plugin_path" = "xyes"], [plugin_path=/usr/lib/finit/plugins:/usr/local/lib/finit/plugins])
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$plugin_path")
|
|
||||||
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
|
|
||||||
|
|
||||||
# Control build with automake flags
|
# Control build with automake flags
|
||||||
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
|
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
||||||
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
AM_CONDITIONAL(WATCHDOGD, [test "x$enable_watchdog" = "xyes"])
|
||||||
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
AM_CONDITIONAL(LOGIT, [test "x$enable_logit" = "xyes"])
|
||||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||||
AM_CONDITIONAL(LIBSYSTEMD, [test "x$with_libsystemd" != "xno"])
|
|
||||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
|
||||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
|
||||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
|
||||||
|
|
||||||
# Workaround for as-of-yet unreleased runstatedir support, planned for
|
|
||||||
# autoconf 2.70, which some major distros have backported.
|
|
||||||
AS_IF([test -z "$runstatedir"], runstatedir="$localstatedir/run")
|
|
||||||
AC_SUBST(runstatedir)
|
|
||||||
|
|
||||||
# Override default libdir, used for plugins and rescue.conf
|
# Override default libdir, used for plugins and rescue.conf
|
||||||
pkglibdir=$libdir/finit
|
pkglibdir=$libdir/finit
|
||||||
AC_SUBST(pkglibexecdir)
|
AC_SUBST(pkglibexecdir)
|
||||||
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
||||||
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
|
AC_DEFINE_UNQUOTED(FINIT_LIBPATH_, "$pkglibexecdir", [Finit libexec path])
|
||||||
AC_EXPAND_DIR(finit_runpath, "$runstatedir/finit/system")
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "$finit_runpath", [Finit runtime dynamic system services])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
|
AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins")
|
||||||
AC_SUBST(plugin_path)
|
AC_SUBST(plugin_path)
|
||||||
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
||||||
|
|
||||||
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
|
AC_EXPAND_DIR(rescue_conf, "$libdir/finit/rescue.conf")
|
||||||
AC_SUBST(tmpfiles_path)
|
|
||||||
AC_DEFINE_UNQUOTED(TMPFILES_PATH_, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
|
|
||||||
AC_SUBST(finit_tmpfiles)
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf path])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
|
|
||||||
AC_SUBST(system_path)
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_SYSPATH_, "$system_path", [Static services, previously generated at runtime by plugins])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
|
|
||||||
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
||||||
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
|
AC_EXPAND_DIR(sample_conf, "$libdir/finit/sample.conf")
|
||||||
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
||||||
|
|
||||||
AC_EXPAND_DIR(bash_completion_dir, "$BASH_DIR")
|
AC_EXPAND_DIR(path_stdpath, "$sbindir:$bindir:/usr/sbin:/usr/bin:/sbin:/bin")
|
||||||
AC_SUBST(BASH_DIR, "$bash_completion_dir")
|
AC_DEFINE_UNQUOTED(_PATH_STDPATH, "$path_stdpath", [Default PATH])
|
||||||
|
|
||||||
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
|
||||||
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
|
||||||
|
|
||||||
RTC_DATE=$rtc_date
|
|
||||||
AS_IF([test "$rtc_date" = ""], [RTC_DATE="<DEFAULT>"])
|
|
||||||
AS_IF([test "$rtc_date" = "no"], [RTC_DATE="<DEFAULT>"])
|
|
||||||
|
|
||||||
# Generate all files
|
# Generate all files
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
@@ -388,16 +234,14 @@ cat <<EOF
|
|||||||
|
|
||||||
------------------ Summary ------------------
|
------------------ Summary ------------------
|
||||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||||
Prefix................: $(eval echo $prefix)
|
Prefix................: $prefix
|
||||||
Exec prefix...........: $(eval echo $exec_prefix)
|
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`
|
|
||||||
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..: `eval echo $rclocal`
|
Compat rc.local path..: $rclocal_path
|
||||||
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
|
||||||
@@ -406,27 +250,16 @@ cat <<EOF
|
|||||||
Behavior:
|
Behavior:
|
||||||
Boot heading..........: $heading
|
Boot heading..........: $heading
|
||||||
Plugins...............: $plugins
|
Plugins...............: $plugins
|
||||||
RTC restore date......: $RTC_DATE
|
|
||||||
RTC fallback file.....: $rtc_file
|
|
||||||
|
|
||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
Install contrib/......: $enable_contrib
|
Install contrib/......: $enable_contrib
|
||||||
Bash completion.......: $bash_completion_dir
|
Built-in watchdogd....: $enable_watchdog
|
||||||
Built-in keventd......: $with_keventd
|
|
||||||
Built-in sulogin......: $with_sulogin $sulogin
|
|
||||||
Built-in watchdogd....: $with_watchdog $watchdog
|
|
||||||
Built-in logrotate....: $enable_logrotate
|
Built-in logrotate....: $enable_logrotate
|
||||||
Replacement libsystemd: $with_libsystemd
|
Scripting tool logit..: $enable_logit
|
||||||
Use cgroup v2.........: $enable_cgroup
|
Emergency shell.......: $enable_emergency_shell
|
||||||
Parse kernel cmdline..: $enable_kernel_cmdline
|
Fallback shell........: $enable_fallback_shell
|
||||||
Keep kernel logging...: $enable_kernel_logging
|
|
||||||
Skip fsck check.......: $enable_fastboot
|
|
||||||
Run fsck fix mode.....: $enable_fsckfix
|
|
||||||
Redirect output.......: $enable_redirect
|
|
||||||
Rescue mode...........: $enable_rescue
|
|
||||||
Default hostname......: $hostname
|
Default hostname......: $hostname
|
||||||
Default group.........: $group
|
|
||||||
Default runlevel......: $runlevel
|
Default runlevel......: $runlevel
|
||||||
|
|
||||||
------------- Compiler version --------------
|
------------- Compiler version --------------
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
SUBDIRS = finit.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/alpine
|
docsdir := @docdir@/contrib/alpine
|
||||||
docs_DATA = README.md finit.conf build.sh install.sh rc.local
|
docs_DATA = README.md finit.conf alpine-release build.sh install.sh rc.local
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4...3.19
|
HowTo: Finit on Alpine Linux 3.4-3.6
|
||||||
=======================================
|
====================================
|
||||||
|
|
||||||
> [!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,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.6.2
|
||||||
@@ -17,8 +17,8 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --without-watchdog \
|
--enable-alsa-utils-plugin --enable-watchdog \
|
||||||
--with-keventd --with-sulogin
|
--with-heading="Alpine Linux 3.13"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,3 +35,4 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -5,22 +5,6 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
|
||||||
# cgroup v2 controller default names.
|
|
||||||
#cgroup init cpu.weight:100
|
|
||||||
#cgroup user cpu.weight:100
|
|
||||||
#cgroup system cpu.weight:9700
|
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
|
||||||
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
|
||||||
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
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 syslogd.conf
|
keymap.conf modules.conf ntpd.conf \
|
||||||
|
klogd.conf syslogd.conf
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
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 syslogd.conf watchdog.conf
|
lxdm.conf modules.conf ntpd.conf klogd.conf syslog.conf \
|
||||||
|
watchdog.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty [12345] /dev/ttyS0 noclear
|
tty [12345] /dev/tty1 noclear nowait
|
||||||
tty [12345] /dev/tty1 noclear nowait
|
tty [2345] /dev/tty2 noclear nowait
|
||||||
tty [2345] /dev/tty2 noclear nowait
|
tty [2345] /dev/tty3 noclear nowait
|
||||||
tty [2345] /dev/tty3 noclear nowait
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Start klogd as soon as possible, after syslogd, should always run
|
||||||
|
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
||||||
@@ -4,4 +4,3 @@
|
|||||||
#module evdev
|
#module evdev
|
||||||
#module mousedev
|
#module mousedev
|
||||||
#module 8139cp
|
#module 8139cp
|
||||||
#module softdog
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Start syslogd as soon as possible, should always run
|
||||||
|
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- Syslog daemon
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Start syslogd as soon as possible, should always run
|
|
||||||
# Start klogd as soon as possible, but after syslogd
|
|
||||||
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- Syslog daemon
|
|
||||||
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
|
||||||
+28
-35
@@ -1,53 +1,44 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ "$(id -u)" != "0" ]; then
|
if [ "x`id -u`" != "x0" ]; then
|
||||||
printf "\n\e[1m*** This script must run as root\e[0m\n\n"
|
echo
|
||||||
|
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
|
||||||
if grep -q contrib/alpine Makefile 2>/dev/null; then
|
if [ -e alpine-release ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
fi
|
elif [ ! -e autogen.sh ]; then
|
||||||
|
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
|
||||||
|
|
||||||
printf "\n\e[1mInstall Finit on Alpine Linux\n"
|
echo
|
||||||
printf "========================================================================\e[0m\n"
|
echo "*** Install Finit on Alpine Linux"
|
||||||
printf "/sbin/finit - PID 1\n"
|
echo "========================================================================"
|
||||||
printf "/lib/finit/plugins/* - All enabled Finit plugins\n"
|
echo "/sbin/finit - PID 1"
|
||||||
printf "/etc/finit.conf - Finit configuration file\n"
|
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
||||||
printf "/etc/finit.d/ - Finit services\n"
|
echo "/etc/finit.conf - Finit configuration file"
|
||||||
|
echo "/etc/finit.d/ - Finit services"
|
||||||
|
echo
|
||||||
|
read -p "Do you want to continue (y/N)? " yorn
|
||||||
|
|
||||||
if yorn "Do you want to continue"; then
|
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
||||||
printf "\n\e[1m*** Installing Finit files ...\e[0m\n"
|
echo
|
||||||
|
echo "*** Installing Finit files ..."
|
||||||
make install
|
make install
|
||||||
cd /usr/share/doc/finit/contrib/alpine || exit 1
|
cd /usr/share/doc/finit/contrib/alpine
|
||||||
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/
|
||||||
|
|
||||||
if yorn "Install Finit as the system default Init"; then
|
read -p "*** Install Finit as the system default Init (y/N)? " yorn
|
||||||
printf "\e[1m*** Updating /sbin/init symlink --> finit ...\e[0m\n"
|
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
||||||
cd /sbin || exit 1
|
echo "*** Updating /sbin/init symlink --> finit ..."
|
||||||
|
cd /sbin
|
||||||
rm init
|
rm init
|
||||||
ln -s finit init
|
ln -s finit init
|
||||||
|
|
||||||
@@ -56,8 +47,10 @@ if yorn "Do you want to continue"; then
|
|||||||
ln -s reboot shutdown
|
ln -s reboot shutdown
|
||||||
ln -s reboot suspend
|
ln -s reboot suspend
|
||||||
fi
|
fi
|
||||||
printf "\n\e[1m*** Done\e[0m\n"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
else
|
else
|
||||||
printf "\n\e[1m*** Aborting install.\e[0m\n\n"
|
echo
|
||||||
|
echo "*** Aborting install."
|
||||||
|
echo
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
#
|
#
|
||||||
# Each line is run in sequence.
|
# Each line is run in sequence.
|
||||||
#
|
#
|
||||||
# NOTE: Remember to set the executable bit!
|
# NOTE: Remeber to set the executable bit!
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = finit.d
|
SUBDIRS = finit.d grub.d
|
||||||
docsdir := @docdir@/contrib/debian
|
docsdir := @docdir@/contrib/debian
|
||||||
docs_DATA = README.md finit.conf build.sh install.sh
|
docs_DATA = README.md finit.conf os-release build.sh install.sh
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -20,44 +20,29 @@ tools pre-systemd work as intended.
|
|||||||
|
|
||||||
root@debian:~# apt install initscripts console-setup
|
root@debian:~# apt install initscripts console-setup
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
|
||||||
> section of Debian. So just install the -dev packages :)
|
|
||||||
|
|
||||||
The following script can then be used to configure, build, install and
|
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:
|
||||||
|
|
||||||
user@debian:~/finit$ contrib/debian/build.sh
|
user@debian:~/finit$ contrib/debian/build.sh
|
||||||
|
|
||||||
However, since `/sbin/init` already exists on your system, the script
|
However, since `/sbin/init` already exists on your system, the script
|
||||||
creates another entry in your GRUB config by updating `$SUPPORTED_INITS`
|
creates another entry in your GRUB config, in `/etc/grub.d/40_custom`,
|
||||||
in `/etc/grub.d/10_inux` and run `update-grub`. On reboot you will find
|
where `init=/sbin/finit` is added to your kernel line. It is of course
|
||||||
a (finit) entry in the "Advanced options for Debian GNU/Linux" section.
|
also possible to change the default init to Finit, if you do you can
|
||||||
It is of course also possible to change the default init to Finit:
|
remove the custom Grub entry:
|
||||||
|
|
||||||
user@debian:~/finit# cd /sbin
|
user@debian:~/finit# cd /sbin
|
||||||
user@debian:/sbin# sudo mv init oldinit
|
user@debian:/sbin# sudo rm init
|
||||||
user@debian:/sbin# sudo ln -s finit init
|
user@debian:/sbin# sudo ln -s finit init
|
||||||
|
|
||||||
Before rebooting, check the default [/etc/finit.conf](finit.conf) and
|
Before rebooting, check the default [/etc/finit.conf](finit.conf) and
|
||||||
`/etc/finit.d/*.conf` files. The build + install script above provides
|
`/etc/finit.d/*.conf` files. The build + install script above provides
|
||||||
a few sample `.conf` files. See `initctl ls` after boot for a list of
|
a few sample `.conf` files. See `initctl list` after boot for a list of
|
||||||
enabled and available services, you can then use `enable` and `disable`
|
enabled and available services.
|
||||||
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]
|
|
||||||
> For the X Window system, you may need to `sudo apt install elogind`
|
|
||||||
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
|
||||||
> is enabled by default), and logout/login again. The elogind daemon
|
|
||||||
> ensures a regular non-root user can start and interact with an X
|
|
||||||
> session, otherwise keyboard and mouse won't work. When you're happy,
|
|
||||||
> you can enable the lightdm.conf, change the default runlevel to 3, and
|
|
||||||
> presto! you have a desktop again.
|
|
||||||
|
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
/Joachim ツ
|
/Joachim ツ
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ echo
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --with-keventd \
|
--enable-alsa-utils-plugin \
|
||||||
--with-random-seed=/var/lib/urandom/random-seed
|
--with-random-seed=/var/lib/urandom/random-seed \
|
||||||
|
--with-heading="Debian GNU/Linux"
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo
|
echo
|
||||||
@@ -59,3 +60,6 @@ else
|
|||||||
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,22 +5,6 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
|
||||||
# cgroup v2 controller default names.
|
|
||||||
#cgroup init cpu.weight:100
|
|
||||||
#cgroup user cpu.weight:100
|
|
||||||
#cgroup system cpu.weight:9700
|
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
|
||||||
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
|
||||||
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/debian/finit.d
|
docsdir := @docdir@/contrib/debian/finit.d
|
||||||
d_LINKS = acpid.conf apparmor.conf avahi-daemon.conf \
|
d_LINKS = console-setup.conf getty.conf keyboard-setup.conf \
|
||||||
bluetooth.conf console-setup.conf elogind.conf \
|
modules.conf rsyslogd.conf sshd.conf
|
||||||
getty.conf keyboard-setup.conf modules.conf \
|
|
||||||
plymouth-quit.conf rsyslogd.conf sshd.conf
|
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
docsdir := @docdir@/contrib/debian/finit.d/available
|
docsdir := @docdir@/contrib/debian/finit.d/available
|
||||||
docs_DATA = acpid.conf apparmor.conf avahi-daemon.conf bluetooth.conf \
|
docs_DATA = acpid.conf console-setup.conf getty.conf keyboard-setup.conf \
|
||||||
console-setup.conf elogind.conf getty.conf \
|
lightdm.conf modules.conf rsyslogd.conf sntpd.conf \
|
||||||
keyboard-setup.conf lightdm.conf modules.conf sntpd.conf \
|
sshd.conf syslogd.conf xdm.conf
|
||||||
plymouth-quit.conf rsyslogd.conf sshd.conf syslogd.conf \
|
|
||||||
xdm.conf
|
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
task [2345] <sys/pwr/ac,pid/syslogd> halt:usr1 env:-/etc/default/anacron anacron -d -q $ANACRON_ARGS -- Anacron jobs
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
sysv [S] /etc/init.d/apparmor -- AppArmor initialization
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
service [2345] env:-/etc/default/avahi-daemon avahi-daemon -s $AVAHI_DAEMON_OPTS -- Avahi mDNS/DNS-SD Stack
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# To ignore errors like "org.freedesktop.hostname1", update the env file with
|
|
||||||
# "--noplugin=hostname", i.e. append to BLUETOOTHD_OPTS
|
|
||||||
service [2345] log:null env:-/etc/default/bluetooth /usr/libexec/bluetooth/bluetoothd -n $BLUETOOTHD_OPTS -- Bluetooth service
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
service [2345] <sys/pwr/ac,pid/syslogd> env:-/etc/default/cron cron -f $EXTRA_OPTS -- Background job processing daemon
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# On some systems, bootstrap can be really quick and cause elogind
|
|
||||||
# to not start before a user has managed to log in. To prevent
|
|
||||||
# this, add <pid/elogind> as condition to your TTYs in getty.conf
|
|
||||||
service [2345] <pid/syslogd> /lib/elogind/elogind -- Login manager
|
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty [12345] /dev/tty1 linux noclear nowait
|
tty [12345] /dev/tty1 linux noclear nowait
|
||||||
tty [2345] /dev/tty2 linux nowait
|
tty [2345] /dev/tty2 linux noclear nowait
|
||||||
tty [2345] /dev/tty3 linux nowait
|
tty [2345] /dev/tty3 linux noclear nowait
|
||||||
tty [2345] /dev/tty4 linux nowait
|
|
||||||
tty [2345] /dev/tty5 linux nowait
|
|
||||||
tty [2345] /dev/tty6 linux nowait
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Need to stop plymouth, or it'll block stdin on tty1
|
|
||||||
task [S] /usr/bin/plymouth quit -- Stopping Plymouth Boot Screen
|
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
exec tail -n +3 $0
|
||||||
|
# This file provides an easy way to add custom menu entries. Simply type the
|
||||||
|
# menu entries you want to add after this comment. Be careful not to change
|
||||||
|
# the 'exec tail' line above.
|
||||||
|
|
||||||
|
menuentry '$MENU with Finit' --class $TYPE --class gnu-linux --class gnu --class os --user {
|
||||||
|
insmod gzio
|
||||||
|
insmod part_msdos
|
||||||
|
insmod ext2
|
||||||
|
search --no-floppy --fs-uuid --set=root $BOOT
|
||||||
|
linux /vmlinuz root=UUID=$ROOT ro quiet init=/sbin/finit
|
||||||
|
initrd /initrd.img
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
docsdir := @docdir@/contrib/debian/grub.d
|
||||||
|
docs_DATA = 40_custom
|
||||||
|
EXTRA_DIST = $(docs_DATA)
|
||||||
@@ -8,10 +8,10 @@ if [ "x`id -u`" != "x0" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
grep -q debian Makefile 2>/dev/null
|
grep -q Debian os-release 2>/dev/null
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e configure.ac ]; then
|
elif [ ! -e autogen.sh ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -23,7 +23,7 @@ echo "/sbin/finit - PID 1"
|
|||||||
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
||||||
echo "/etc/finit.conf - Finit configuration file"
|
echo "/etc/finit.conf - Finit configuration file"
|
||||||
echo "/etc/finit.d/ - Finit services"
|
echo "/etc/finit.d/ - Finit services"
|
||||||
echo "/etc/grub.d/10_linux - Add Finit to Grub's SUPPORTED_INITS"
|
echo "/etc/grub.d/40_custom - Add menu entry to the Grub boot loader"
|
||||||
echo
|
echo
|
||||||
read -p "Do you want to continue (y/N)? " yorn
|
read -p "Do you want to continue (y/N)? " yorn
|
||||||
echo
|
echo
|
||||||
@@ -38,18 +38,12 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
|||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
echo "*** Setting up a GRUB boot entry ..."
|
echo "*** Setting up a GRUB boot entry ..."
|
||||||
fn=/etc/grub.d/10_linux
|
MENU=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/menuentry '\([^']*\).*/\1/"`
|
||||||
if [ -e $fn ]; then
|
TYPE=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/.*' --class \([a-z]*\).*/\1/"`
|
||||||
if `grep SUPPORTED_INITS $fn |head -1 |grep -q finit`; then
|
BOOT=`grep set=root /boot/grub/grub.cfg |head -1 |sed 's/.* \([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
||||||
echo "Already installed, done."
|
ROOT=`grep root=UUID /boot/grub/grub.cfg |head -1 |sed 's/.*UUID=\([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
||||||
else
|
cat grub.d/40_custom | sed "s,\$BOOT,$BOOT,;s,\$ROOT,$ROOT,;s,\$TYPE,$TYPE,;s,\$MENU,$MENU," >/etc/grub.d/40_custom
|
||||||
echo "Adding Finit to list of SUPPORTED_INITS ..."
|
update-grub
|
||||||
sed -i 's/SUPPORTED_INITS="[^"]*/& finit:\/sbin\/finit/' $fn
|
|
||||||
update-grub
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Cannot find $fn, you'll have to set up your bootloader on your own."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
|
||||||
|
NAME="Debian GNU/Linux"
|
||||||
|
VERSION_ID="8"
|
||||||
|
VERSION="8 (jessie)"
|
||||||
|
ID=debian
|
||||||
|
HOME_URL="http://www.debian.org/"
|
||||||
|
SUPPORT_URL="http://www.debian.org/support"
|
||||||
|
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||||
+2
-37
@@ -8,18 +8,6 @@ module evdev
|
|||||||
module loop
|
module loop
|
||||||
module psmouse
|
module psmouse
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
|
||||||
# cgroup v2 controller default names.
|
|
||||||
cgroup init cpu.weight:100
|
|
||||||
cgroup user cpu.weight:100
|
|
||||||
cgroup system cpu.weight:9700 cpu.max:50000
|
|
||||||
|
|
||||||
# Example extra cgroup
|
|
||||||
cgroup maint cpu.weight:100
|
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, runlevel 'S'
|
# Runlevel to start after bootstrap, runlevel 'S'
|
||||||
runlevel 2
|
runlevel 2
|
||||||
|
|
||||||
@@ -28,21 +16,13 @@ network service networking start
|
|||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
||||||
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
||||||
log size:100k count:4
|
log size=100k count=4
|
||||||
|
|
||||||
# Virtual consoles to start getty on
|
# Virtual consoles to start getty on
|
||||||
tty /dev/tty1
|
tty /dev/tty1
|
||||||
tty /dev/tty2
|
tty /dev/tty2
|
||||||
tty /dev/tty3
|
tty /dev/tty3
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
|
||||||
task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
|
||||||
task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
|
||||||
|
|
||||||
# Alternative method instead of runparts
|
# Alternative method instead of runparts
|
||||||
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
||||||
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
@@ -50,24 +30,9 @@ task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
|||||||
#run [2] /etc/init.d/networking start -- Start networking
|
#run [2] /etc/init.d/networking start -- Start networking
|
||||||
|
|
||||||
# Services to be monitored and respawned as needed
|
# Services to be monitored and respawned as needed
|
||||||
|
|
||||||
# klgod and syslogd are placed in the maint cgroup
|
|
||||||
cgroup.maint
|
|
||||||
service [2345] <pid/syslogd> klogd -n -- Kernel logging server
|
service [2345] <pid/syslogd> klogd -n -- Kernel logging server
|
||||||
service [2345] syslogd -n -- Syslog server
|
service [2345] syslogd -n -- Syslog server
|
||||||
|
service [3] gdm -- GNOME Display Manager
|
||||||
# gdm in the system cgroup (default when read from it's own .conf file)
|
|
||||||
cgroup.system
|
|
||||||
service [3] cgroup:cpu.weight:250,mem.max:10M gdm -- GNOME Display Manager
|
|
||||||
|
|
||||||
# Start SSH daemon with opts from /etc/default/ssh (if available), move
|
|
||||||
# to user cgroup with cpu.weight:250. Default for services is system
|
|
||||||
# group. Default weight in user group is 100 (above). Max length of
|
|
||||||
# cgroup argument is (currently) 63 chars.
|
|
||||||
#
|
|
||||||
# Notice alternative syntax where current cgroup is only set for this
|
|
||||||
# particular service.
|
|
||||||
service [2345] cgroup.user:cpu.weight:250,mem.max:10M env:-/etc/default/ssh /usr/sbin/sshd -D $SSHD_OPTS -- OpenSSH daemon
|
|
||||||
|
|
||||||
# The BusyBox ntpd does not use syslog when running in the foreground
|
# The BusyBox ntpd does not use syslog when running in the foreground
|
||||||
# So we use this trick to redirect stdout/stderr to a log file. The
|
# So we use this trick to redirect stdout/stderr to a log file. The
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
In Finit issue #196 we were reminded [1] of a missing inotify flag in
|
|
||||||
Linux older kernels, IN_MASK_CREATE. Finit makes use of this internally
|
|
||||||
for monitoring PID conditions, and more. This is a central mechanism to
|
|
||||||
synchronize services at boot and reload at runtime.
|
|
||||||
|
|
||||||
The following patch for Linux 4.9.0, was provided by Andy Savage for
|
|
||||||
other people that may want to run Finit on slightly older kernels.
|
|
||||||
|
|
||||||
[1]: https://github.com/troglobit/finit/issues/196
|
|
||||||
|
|
||||||
Index: fs/notify/inotify/inotify_user.c
|
|
||||||
===================================================================
|
|
||||||
--- fs.orig/notify/inotify/inotify_user.c
|
|
||||||
+++ fs/notify/inotify/inotify_user.c
|
|
||||||
@@ -522,6 +522,7 @@ static int inotify_update_existing_watch
|
|
||||||
__u32 old_mask, new_mask;
|
|
||||||
__u32 mask;
|
|
||||||
int add = (arg & IN_MASK_ADD);
|
|
||||||
+ int create = (arg & IN_MASK_CREATE);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
mask = inotify_arg_to_mask(arg);
|
|
||||||
@@ -529,6 +530,8 @@ static int inotify_update_existing_watch
|
|
||||||
fsn_mark = fsnotify_find_inode_mark(group, inode);
|
|
||||||
if (!fsn_mark)
|
|
||||||
return -ENOENT;
|
|
||||||
+ else if (create)
|
|
||||||
+ return -EEXIST;
|
|
||||||
|
|
||||||
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
|
|
||||||
|
|
||||||
@@ -726,6 +729,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int,
|
|
||||||
if (unlikely(!f.file))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
+ /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
|
|
||||||
+ if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
/* verify that this is indeed an inotify instance */
|
|
||||||
if (unlikely(f.file->f_op != &inotify_fops)) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
@@ -814,7 +821,7 @@ static int __init inotify_user_setup(voi
|
|
||||||
BUILD_BUG_ON(IN_ISDIR != FS_ISDIR);
|
|
||||||
BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT);
|
|
||||||
|
|
||||||
- BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21);
|
|
||||||
+ BUG_ON(hweight32(ALL_INOTIFY_BITS) != 22);
|
|
||||||
|
|
||||||
inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark, SLAB_PANIC);
|
|
||||||
|
|
||||||
Index: include/linux/inotify.h
|
|
||||||
===================================================================
|
|
||||||
--- include.orig/linux/inotify.h
|
|
||||||
+++ include/linux/inotify.h
|
|
||||||
@@ -17,6 +17,6 @@ extern struct ctl_table inotify_table[];
|
|
||||||
IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | \
|
|
||||||
IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR | \
|
|
||||||
IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \
|
|
||||||
- IN_ISDIR | IN_ONESHOT)
|
|
||||||
+ IN_MASK_CREATE | IN_ISDIR | IN_ONESHOT)
|
|
||||||
|
|
||||||
#endif /* _LINUX_INOTIFY_H */
|
|
||||||
Index: include/uapi/linux/inotify.h
|
|
||||||
===================================================================
|
|
||||||
--- include.orig/uapi/linux/inotify.h
|
|
||||||
+++ include/uapi/linux/inotify.h
|
|
||||||
@@ -52,6 +52,7 @@ struct inotify_event {
|
|
||||||
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
|
|
||||||
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
|
|
||||||
#define IN_EXCL_UNLINK 0x04000000 /* exclude events on unlinked objects */
|
|
||||||
+#define IN_MASK_CREATE 0x10000000 /* only create watches */
|
|
||||||
#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
|
|
||||||
#define IN_ISDIR 0x40000000 /* event occurred against dir */
|
|
||||||
#define IN_ONESHOT 0x80000000 /* only send event once */
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = finit.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/void
|
docsdir := @docdir@/contrib/void
|
||||||
docs_DATA = README.md finit.conf build.sh install.sh rc.local
|
docs_DATA = README.md finit.conf build.sh install.sh rc.local xbps
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --with-watchdog \
|
--enable-alsa-utils-plugin --enable-watchdog \
|
||||||
--with-keventd --with-sulogin
|
--with-heading="Void Linux"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,3 +35,4 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -5,22 +5,5 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
|
||||||
# cgroup v2 controller default names.
|
|
||||||
#cgroup init cpu.weight:100
|
|
||||||
#cgroup user cpu.weight:100
|
|
||||||
#cgroup system cpu.weight:9700
|
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
|
||||||
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
|
||||||
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
docsdir := @docdir@/contrib/void/finit.d/available
|
docsdir := @docdir@/contrib/void/finit.d/available
|
||||||
docs_DATA = acpid.conf crond.conf dhcpcd.conf dmeventd.conf getty.conf \
|
docs_DATA = acpid.conf crond.conf dhcpcd.conf dmeventd.conf getty.conf \
|
||||||
keymap.conf lxdm.conf modules.conf ntpd.conf \
|
keymap.conf klogd.conf lxdm.conf modules.conf ntpd.conf \
|
||||||
sshd.conf syslog.conf uuidd.conf
|
sshd.conf syslogd.conf uuidd.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Start klogd as soon as possible, should always run
|
||||||
|
service [S12345] <pid/syslogd> klogd -n -- Kernel log daemon
|
||||||
@@ -4,4 +4,3 @@
|
|||||||
#module evdev
|
#module evdev
|
||||||
#module mousedev
|
#module mousedev
|
||||||
#module 8139cp
|
#module 8139cp
|
||||||
module softdog
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
# Start syslogd as soon as possible, should always run
|
|
||||||
# Start klogd as soon as possible, but after syslogd
|
|
||||||
service [S12345] syslogd -n -- Syslog daemon
|
|
||||||
service [S12345] <pid/syslogd> klogd -n -- Kernel log daemon
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Start syslogd as soon as possible, should always run
|
||||||
|
service [S12345] syslogd -n -- Syslog daemon
|
||||||
@@ -8,10 +8,9 @@ if [ "x`id -u`" != "x0" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
grep -q void Makefile 2>/dev/null
|
if [ -e xbps ]; then
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e configure.ac ]; then
|
elif [ ! -e autogen.sh ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
#
|
#
|
||||||
# Each line is run in sequence.
|
# Each line is run in sequence.
|
||||||
#
|
#
|
||||||
# NOTE: Remember to set the executable bit!
|
# NOTE: Remeber to set the executable bit!
|
||||||
|
|||||||
+6
-18
@@ -19,31 +19,19 @@ Some of these are also registered in the issue tracker on GitHub.
|
|||||||
* Add new (complimentary) .svc file format to slowly migrate away
|
* Add new (complimentary) .svc file format to slowly migrate away
|
||||||
from the very terse one-liner format currently used
|
from the very terse one-liner format currently used
|
||||||
* Allow running as non-pid1 => read .conf and RCSD form cmdline
|
* Allow running as non-pid1 => read .conf and RCSD form cmdline
|
||||||
|
* When a process dies, and Finit does not restart it, we should collect
|
||||||
|
a `siginfo_t` from the SIGCHLD signal and supply to the user in case
|
||||||
|
`initctl status <process>` is called to debug the issue.
|
||||||
* Add `finit.conf` support for UPS notification (SIGPWR) to start a task
|
* Add `finit.conf` support for UPS notification (SIGPWR) to start a task
|
||||||
using, e.g. <sys/power/{ok,fail,low}> conditions. More info in sig.c
|
using, e.g. <sys/power/{ok,fail,low}> conditions. More info in sig.c
|
||||||
|
|
||||||
As of Finit v4.1 SIGPWR generates <sys/power/fail> condition and it
|
|
||||||
is up to a task to check why and take appropriate action.
|
|
||||||
* Add `finit.conf` support for ctrl-alt-delete (SIGINT) and kbrequest,
|
* Add `finit.conf` support for ctrl-alt-delete (SIGINT) and kbrequest,
|
||||||
i.e. KeyboardSignal, (SIGWINCH) behavior. Using conditions to a task,
|
i.e. KeyboardSignal, (SIGWINCH) behavior. Using conditions to a task,
|
||||||
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
||||||
|
* Write man pages for finit and `finit.conf`, steal from the excellent
|
||||||
As of Finit v4.1 SIGINT generates <sys/key/ctrlaltdel>, but there is
|
`pimd` man pages ...
|
||||||
no check if the signal actually originates from the kernel. To get
|
* Add support for timed shutdown in Finit, including cancelled shutdown
|
||||||
this verification, a new libuEv release is needed. As of June 6 -21
|
|
||||||
that functionality is not yet released.
|
|
||||||
|
|
||||||
|
|
||||||
Initctl
|
|
||||||
-------
|
|
||||||
|
|
||||||
* Add support for timed shutdown in Finit, including cancelled shutdown:
|
|
||||||
|
|
||||||
shutdown -h 03:35 "foobar was here"
|
|
||||||
|
|
||||||
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
||||||
`initctl show --json`
|
`initctl show --json`
|
||||||
* Add support for `-s` to redirect all output to syslog, for scripting
|
|
||||||
|
|
||||||
|
|
||||||
Init
|
Init
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
Bootstrap
|
||||||
|
=========
|
||||||
|
|
||||||
|
1. Prepare emergency shell, if enabled
|
||||||
|
2. Set up initial signal handlers
|
||||||
|
3. Set up default $PATH early
|
||||||
|
4. Mount `/proc` and `/sys`
|
||||||
|
5. Check kernel command line for `debug` to figure out log level
|
||||||
|
6. Load all `.so` plugins
|
||||||
|
7. Call `fsck` on file systems listed in `/etc/fstab`
|
||||||
|
8. Populate `/dev` using either udev or mdev, depending on system type
|
||||||
|
9. Parse `/etc/finit.conf` and all `/etc/finit.d/*.conf` files
|
||||||
|
10. Start built-in watchdog, if enabled
|
||||||
|
11. Set hostname
|
||||||
|
12. Remount `/` read-write if `/` is listed in `/etc/fstab` without `ro`
|
||||||
|
13. Call 1st level hooks, `HOOK_ROOTFS_UP`
|
||||||
|
14. Mount all file systems listed in `/etc/fstab` and swap, if available
|
||||||
|
15. Enable SysV init signals
|
||||||
|
16. Call 2nd level hooks, `HOOK_BASEFS_UP`
|
||||||
|
17. Cleanup stale files from `/tmp/*` et al, handled by `bootmisc` plugin
|
||||||
|
18. Load kernel params from `/etc/sysctl.d/*.conf`, `/etc/sysctl.conf`
|
||||||
|
et al. (Supports all locations that SysV init does.), handled by
|
||||||
|
`procps` plugin
|
||||||
|
19. Start all 'S' runlevel tasks and services
|
||||||
|
20. Bring up loopback interface and all `/etc/network/interfaces`, if
|
||||||
|
the `.conf` setting `network <SCRIPT>` is set, it is called instead
|
||||||
|
21. Call 3rd level hooks, `HOOK_NETWORK_UP`
|
||||||
|
22. If `runparts <DIR>` is set, [run-parts(8)][] is called on `<DIR>`
|
||||||
|
23. Switch to the configured runlevel from `/etc/finit.conf`, default 2.
|
||||||
|
At every runlevel change all `*.conf` files in `/etc/finit.d/` are
|
||||||
|
(re)loaded and new services, tasks, and blocking run commands are
|
||||||
|
started. Provided they are allowed in the new runlevel and all of
|
||||||
|
their conditions, if any, are set.
|
||||||
|
24. Call 4th level hooks, `HOOK_SVC_UP`
|
||||||
|
25. Call `/etc/rc.local`, if it exists and is an executable shell script
|
||||||
|
26. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
|
||||||
|
27. Start all configured TTYs, or a fallback shell on `/dev/console`
|
||||||
|
|
||||||
|
In (19) and (22) tasks and services defined in `/etc/finit.conf` and
|
||||||
|
`/etc/sysctl.d/*.conf` are started. Remember, all `service` and `task`
|
||||||
|
stanzas are started in parallel and `run` in sequence, and in the order
|
||||||
|
listed. Hence, to emulate a SysV `/etc/init.d/rcS` one could write a
|
||||||
|
long `finit.conf` with only `run` statements.
|
||||||
|
|
||||||
|
Notice the five hook points that are called at various point in the
|
||||||
|
bootstrap process. This is where plugins can extend the boot in any way
|
||||||
|
they please. There are other hook points, e.g. `HOOK_MOUNT_ERROR`, for
|
||||||
|
more on this see [plugins.md](plugins.md).
|
||||||
|
|
||||||
|
For instance, at `HOOK_BASEFS_UP` a plugin could read an XML file from a
|
||||||
|
USB stick, convert/copy its contents to the system's `/etc/` directory,
|
||||||
|
well before all 'S' runlevel tasks are started. This could be used with
|
||||||
|
system images that are created read-only and all configuration is stored
|
||||||
|
on external media.
|
||||||
|
|
||||||
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
+34
-63
@@ -1,5 +1,5 @@
|
|||||||
Building Finit
|
Building
|
||||||
==============
|
========
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Configure](#configure)
|
* [Configure](#configure)
|
||||||
@@ -17,21 +17,20 @@ 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
|
||||||
|
|
||||||
> [!IMPORTANT]
|
**NOTE:** Most free/open source software that uses `configure` default
|
||||||
> Most free/open source software packages that use `configure` default
|
to install to `/usr/local`. However, some Linux distributions do no
|
||||||
> to install to `/usr/local`. However, some Linux distributions do no
|
longer search that path for installed software, e.g. Fedora and Alpine
|
||||||
> longer search that path for installed software, e.g. Fedora and Alpine
|
Linux. To get finit's configure script to find its dependencies you
|
||||||
> Linux. To get finit's configure script to find its dependencies you
|
have to help the `pkg-config` tool a bit if you do not change the
|
||||||
> have to help the `pkg-config` tool a bit if you do not change the
|
default prefix path:
|
||||||
> 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 requried versions:
|
||||||
|
|
||||||
- libite v2.2.0, or later
|
- libite v2.2.0
|
||||||
- libuEv v2.2.0, or later
|
- libuEv v2.2.0
|
||||||
|
|
||||||
|
|
||||||
Configure
|
Configure
|
||||||
@@ -54,10 +53,6 @@ Below are a few of the main switches to configure:
|
|||||||
built-ins (.o files) and all external libraries, except the C library
|
built-ins (.o files) and all external libraries, except the C library
|
||||||
will be linked statically.
|
will be linked statically.
|
||||||
|
|
||||||
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
|
||||||
`/proc/cmdline`, this is *not recommended* since Finit may be running as the
|
|
||||||
init for container apps that can see the host's `/proc` filesystem
|
|
||||||
|
|
||||||
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
||||||
|
|
||||||
* `--enable-dbus-plugin`: Enable the optional D-Bus `dbus.so` plugin.
|
* `--enable-dbus-plugin`: Enable the optional D-Bus `dbus.so` plugin.
|
||||||
@@ -66,20 +61,8 @@ Below are a few of the main switches to configure:
|
|||||||
|
|
||||||
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
||||||
|
|
||||||
* `--with-sulogin`: Enable bundled `sulogin` program. Default is to use the
|
|
||||||
system `sulogin(8)`. The sulogin shipped with Finit *allows password-less*
|
|
||||||
login if the `root` user is disabled or has no password at all.
|
|
||||||
|
|
||||||
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
|
|
||||||
> however included in (officially supported) released tarballs. The
|
|
||||||
> idea is that you should not need GNU autotools to build, only the
|
|
||||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
|
||||||
> Any contributing to Finit can generate it from `configure.ac` using
|
|
||||||
> the `autogen.sh` script.
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@@ -87,16 +70,16 @@ Example
|
|||||||
First, unpack the archive:
|
First, unpack the archive:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ tar xf finit-4.3.tar.gz
|
$ tar xf finit-3.0.tar.xz
|
||||||
$ cd finit-4.3/
|
$ cd finit-3.0/
|
||||||
```
|
```
|
||||||
|
|
||||||
Then configure, build and install:
|
Then configure, build and install:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ ./configure --prefix=/usr --exec-prefix= \
|
$ ./configure --prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--with-keventd --with-watchdog
|
--with-heading="Alpine Linux 3.13" --with-hostname=alpine
|
||||||
$ make
|
$ make
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -104,24 +87,23 @@ $ make
|
|||||||
$ DESTDIR=/tmp/finit make install
|
$ DESTDIR=/tmp/finit make install
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example the [finit-4.3.tar.gz][1] archive is unpacked to the
|
In this example the [finit-3.0.tar.xz][1] archive is unpacked to the
|
||||||
user's home directory, configured, built and installed to a temporary
|
user's home directory, configured, built and installed to a temporary
|
||||||
staging directory. The environment variable `DESTDIR` controls the
|
staging directory. The environment variable `DESTDIR` controls the
|
||||||
destination directory when installing, very useful for building binary
|
destination directory when installing, very useful for building binary
|
||||||
standalone packages.
|
standalone packages.
|
||||||
|
|
||||||
Finit 4.1 and later can detect if it runs on an embedded system, or a
|
Finit 3.0 and later can detect if it runs on an embedded system, or a
|
||||||
system that use BusyBox tools instead of udev & C:o. On such systems
|
system that use BusyBox tools instead of udev & C:o. On such systems
|
||||||
`mdev` instead of `udev` is used. However, remember to also change the
|
`mdev` instead of `udev` is used. However, remember to also change the
|
||||||
Linux config to:
|
Linux config to:
|
||||||
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||||
|
|
||||||
> [!TIP]
|
**Note:** If you run into problems starting Finit, take a look at
|
||||||
> If you run into problems starting Finit, take a look at `finit.c`.
|
`finit.c`. One of the most common problems is a custom Linux kernel
|
||||||
> One of the most common problems is a custom Linux kernel build that
|
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
||||||
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
system `/etc/fstab`.
|
||||||
> `/etc/fstab`.
|
|
||||||
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
@@ -160,43 +142,32 @@ 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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
|
||||||
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
|
||||||
> versions of these commands. Use the `-f` flag to force the action.
|
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Edit, or append to, the kernel command line: remove `quiet` to enable
|
Edit, or append to, the kernel command line: remove `quiet` to enable
|
||||||
kernel messages and add `finit.debug` to enable Finit debug messages.
|
kernel messages and add `debug` to enable Finit debug messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
append="init=/sbin/finit -- finit.debug"
|
append="init=/sbin/finit debug"
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice the `--` separator.
|
To debug startup issues, in particular issues with getty/login, try
|
||||||
|
`configure --enable-fallback-shell`. When no TTYs are detected, and
|
||||||
To debug startup issues, in particular issues with getty/login, add
|
Finit is configured with this option, Finit will try to start a bare
|
||||||
the following to your Finit .conf file:
|
`/bin/sh` on the boot console. Remember, this is only for debugging
|
||||||
|
and would leave your production system potentially wide open.
|
||||||
tty [12345789] notty noclear
|
|
||||||
|
|
||||||
The `notty` option ensures reusing the stdin/stdout set up by the
|
|
||||||
kernel. Remember, this is only for debugging and would leave your
|
|
||||||
production system potentially wide open.
|
|
||||||
|
|
||||||
There is also a rescue shell available, in case Finit crashes and the
|
There is also a rescue shell available, in case Finit crashes and the
|
||||||
kernel usually reboots: `configure --enable-emergency-shell`. However,
|
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.
|
||||||
|
|
||||||
> [!CAUTION]
|
**NOTE:** Neither of these two configure options should be enabled on
|
||||||
> None of these options should be enabled on production systems since
|
production systems since they can potentially give a user root access.
|
||||||
> they can potentially give a user root access.
|
|
||||||
|
|
||||||
|
|
||||||
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
[1]: ftp://troglobit.com/finit/finit-3.0.tar.xz
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[libite]: https://github.com/troglobit/libite
|
[libite]: https://github.com/troglobit/libite
|
||||||
|
|||||||
+15
-89
@@ -4,70 +4,17 @@ 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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> Remember to use `--` to separate kernel parameters from parameters to
|
|
||||||
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
|
||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
|
|
||||||
|
|
||||||
* `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.
|
||||||
|
|
||||||
* `fsck.mode=<auto,force,skip>`, default: `auto`, unless built with
|
|
||||||
`configure --enable-fastboot`, in which case the default is `skip`
|
|
||||||
|
|
||||||
* `fsck.repair=<preen,yes,no>`, default: `preen`, unless built with
|
|
||||||
`configure --enable-fsckfix`, in which case the default is `yes`.
|
|
||||||
This configure option also sets `fsck.mode=force`, unless fastboot
|
|
||||||
is selected at the same time. I.e., the `--enable-fastboot` build
|
|
||||||
option overrides the `fsck.mode` default value.
|
|
||||||
|
|
||||||
* `finit.cond=foo[,bar[,baz]]`: set `<boot/foo>` condition, optionally
|
|
||||||
multiple conditions can be set using the same option, separated with a
|
|
||||||
comma. Alternatively, multiple `foo.cond=arg` can be given. Each will
|
|
||||||
result in a `<boot/arg>` condition being set to control the rest of the
|
|
||||||
system bootstrap.
|
|
||||||
|
|
||||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
|
||||||
firmware upgrade, or rescue mode.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
|
||||||
|
|
||||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
|
||||||
compile-time bootstrap config file, default:
|
|
||||||
|
|
||||||
./configure --with-config=/etc/finit.conf
|
|
||||||
|
|
||||||
Useful when starting up in various rescue mode, factory, or
|
|
||||||
production test setups. Use the top-level configuration file
|
|
||||||
directive `rcsd /path/to/finit.d` to override the default
|
|
||||||
rcS.d directory.
|
|
||||||
|
|
||||||
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
||||||
independently of the kernel `debug` setting. New as of Finit v4.
|
independently of the kernel debug setting. New as of Finit v4.
|
||||||
|
|
||||||
* `finit.fstab=</path/to/etc/fstab.alternative>`: Tell Finit to use an
|
* `finit.show_status[=bool]`: Control finit boot progress, including
|
||||||
alternate `fstab` to mount the file system from. Remember, this file
|
banner.
|
||||||
must be on the `root=...` file system provided to Finit from the
|
|
||||||
kernel. By default the built-in fstab is used, which itself defaults
|
|
||||||
to `/etc/fstab`, but can be changed at build time with:
|
|
||||||
|
|
||||||
./configure --with-fstab=/path/to/fstab
|
|
||||||
|
|
||||||
It is even possible to disable a built-in default using:
|
|
||||||
|
|
||||||
./configure --without-fstab
|
|
||||||
|
|
||||||
Making `finit.fstab=/path/to/fstab` a *mandatory* command line option.
|
|
||||||
Note, if the command line fstab is missing, Finit falls back to the
|
|
||||||
built-in fstab, and if both are missing, the system treats this as a
|
|
||||||
bad `fsck` and thus calls `sulogin`. If, in turn, `sulogin` is not
|
|
||||||
available on the system, Finit calls reboot, which is also what will
|
|
||||||
happen when a user exits from `sulogin`.
|
|
||||||
|
|
||||||
* `finit.status[=bool]`: Control finit boot progress, including banner.
|
|
||||||
(Used to be `finit.show_status`, which works but is deprecated.)
|
|
||||||
|
|
||||||
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
||||||
when enabled.
|
when enabled.
|
||||||
@@ -77,44 +24,23 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
signals and has no job control. Recommend using, and modifying,
|
signals and has no job control. Recommend using, and modifying,
|
||||||
`rescue` mode instead.
|
`rescue` mode instead.
|
||||||
|
|
||||||
* `loglevel=<0-7>`, sets the kernel's log level, which is more granular
|
|
||||||
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
|
||||||
kernel logs to the console. This is very useful when debugging the
|
|
||||||
kernel at system bring-up. Since `loglevel=7` is the same as `debug`
|
|
||||||
this means you have to use `quiet` for a quiet boot, until sysklogd
|
|
||||||
takes over logging of kernel events.
|
|
||||||
|
|
||||||
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
||||||
panic. This setting will cause a kernel reboot after SEC seconds.
|
panic. This setting will cause a kernel reboot after SEC seconds.
|
||||||
|
|
||||||
* `quiet`: Suppress kernel logging to console, except for warnings and
|
* `quiet`: Suppress kernel logging to console, except for warnings and
|
||||||
errors. Also, see `loglevel` and `quiet` above.
|
errors.
|
||||||
|
|
||||||
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
* `rescue`: Start Finit rescue mode; no network, no `fsck` of file
|
||||||
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
systems in `/etc/fstab`, no `/etc/rc.local`, no `runparts`. The
|
||||||
you will be given a root login to a maintenance shell. However, if
|
configuration is read from `/lib/finit/rescue.conf`, and can be
|
||||||
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
modified by the operator.
|
||||||
the system booted in a limited fallback mode. See [config.md][]
|
|
||||||
for more information.
|
|
||||||
|
|
||||||
This option can be disabled with `configure --without-rescue`
|
* `single`, or `S`: Single user mode, runlevel 1, in Finit. Useful to
|
||||||
|
debug problems with the regular runlevel. All services and TTYs in
|
||||||
|
`[1]` will be started, so a `tty [1] @console nologin` configuration
|
||||||
|
presents you with a root console without login.
|
||||||
|
|
||||||
**Note:** in this mode `initctl` will not work. Correct the problem
|
For more on kernel boot paramaters, see the man page [bootparam(7)][].
|
||||||
and use `reboot -f` to force reboot.
|
|
||||||
|
|
||||||
* `single`, or `S`: Overrides the configured runlevel (default: 2) to go
|
|
||||||
to after bootstrap by forcing it to runlevel 1, this is also known
|
|
||||||
as single user mode. Useful to debug startup problems. All services
|
|
||||||
and TTYs in `[1]` will be started, so a `tty [1] @console nologin`
|
|
||||||
configuration presents you with a root console without login.
|
|
||||||
|
|
||||||
* `1-9`, except `6`: override the configured `runlevel`. Like the `S`
|
|
||||||
and `rescue`, giving a single number on the kernel command line tells
|
|
||||||
Finit to ignore any `runlevel` in `/etc/finit.conf` as well as the
|
|
||||||
configure fallback `--with-runlevel=N` setting. Remember, `6` is the
|
|
||||||
reboot runlevel and is not permitted. Any other values are ignored.
|
|
||||||
|
|
||||||
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
|
||||||
|
|
||||||
[config.md]: config.md#rescue-mode
|
|
||||||
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
||||||
|
|||||||
+23
-118
@@ -13,9 +13,9 @@ Finit Conditions
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Conditions are a relatively new addition to Finit, introduced in v3,
|
Conditions are a new addition to Finit, introduced in v3, with the
|
||||||
with the intention of providing a mechanism for common synchronization
|
intention of providing a mechanism for common synchronization problems.
|
||||||
problems. For example:
|
For example:
|
||||||
|
|
||||||
- *"wait for service A to start before starting service B"*, or
|
- *"wait for service A to start before starting service B"*, or
|
||||||
- *"wait for basic network access to be available"*
|
- *"wait for basic network access to be available"*
|
||||||
@@ -27,16 +27,6 @@ specified separated by comma. Multiple conditions are logically AND'ed
|
|||||||
during evaluation, i.e. all conditions must be satisfied in order for a
|
during evaluation, i.e. all conditions must be satisfied in order for a
|
||||||
service to run.
|
service to run.
|
||||||
|
|
||||||
A special syntax, using a leading `!` in run/task/service conditions,
|
|
||||||
denote if a:
|
|
||||||
|
|
||||||
- service does not support `SIGHUP`
|
|
||||||
- run/task should not block runlevel changes (i.e., bootstrap)
|
|
||||||
|
|
||||||
Finit guarantees by default that all run/tasks run (at least) once
|
|
||||||
per runlevel. For most tasks this is a good default, for example
|
|
||||||
checking SSH host keys or loading keymap. However, for conditions
|
|
||||||
that are unlikely to happen it is not. (See example below.)
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -45,60 +35,17 @@ that are unlikely to happen it is not. (See example below.)
|
|||||||
In this example the Network monitor daemon `netd` is not started until
|
In this example the Network monitor daemon `netd` is not started until
|
||||||
both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
**NOTE:** Conditions also stop services when a condition is no longer
|
||||||
> Conditions also stop services when a condition is no longer asserted.
|
asserted. I.e., if the Zebra process above stops or restarts, netd
|
||||||
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
will also stop or restart.
|
||||||
> stop or restart.
|
|
||||||
|
|
||||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
|
||||||
also see optional sourcing of arguments from an environment file:
|
|
||||||
|
|
||||||
service [2345789] <!> env:-/etc/default/dropbear dropbear -F -R $DROPBEAR_ARGS -- Dropbear SSH daemon
|
|
||||||
|
|
||||||
Finally, the weird "block runlevel changes" example. Here we see what
|
|
||||||
happens when Finit receives `SIGPWR`, sent from a power daemon like
|
|
||||||
[powstatd(8)][]. A condition is asserted and a user can set up their
|
|
||||||
own task to act on it. We do not want this task to block Finit from
|
|
||||||
moving to the next runlevel after bootstrap, so we set `<!>`:
|
|
||||||
|
|
||||||
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
|
||||||
|
|
||||||
|
|
||||||
Triggering
|
Triggering
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Conditions are mainly triggered (asserted) by built-in plugins, e.g.,
|
Conditions can only be triggered by built-in plugins.
|
||||||
|
|
||||||
- `netlink.so`: provides `<net/...>`
|
|
||||||
- `pidfile.so`: provides `<pid/...>`
|
|
||||||
- Cmdline `finit.cond=arg`: provides `<boot/arg>`
|
|
||||||
|
|
||||||
See below for built-in conditions. Finit also supports user-defined
|
|
||||||
conditions, sometimes referred to as static or one-shot conditions.
|
|
||||||
They live in the `<usr/...>` namespace and are constrained to a flat
|
|
||||||
hierarchy without any sub-directories, unlike the pidfile plugin, for
|
|
||||||
instance.
|
|
||||||
|
|
||||||
User-defined conditions are controlled using the `initctl cond set` and
|
|
||||||
`initctl cond clear` commands:
|
|
||||||
|
|
||||||
initctl cond set foo
|
|
||||||
initctl cond clear foo
|
|
||||||
|
|
||||||
The purpose of user-defined conditions is to be able to start or stop
|
|
||||||
services, or run/task jobs, on external site-dependent stimuli.
|
|
||||||
Example:
|
|
||||||
|
|
||||||
service [2345] <usr/foo> alarm --arg foo -- Foo alarm
|
|
||||||
|
|
||||||
For convenience, prefixing with `usr/` is allowed, but any other slashes
|
|
||||||
or period characters are disallowed. E.g., to trigger the `Foo alarm`,
|
|
||||||
the same as above, can also be achieved like this:
|
|
||||||
|
|
||||||
initctl cond set usr/foo
|
|
||||||
initctl cond clear usr/foo
|
|
||||||
|
|
||||||
Conditions retain their current state until the next reconfiguration or
|
Conditions retain their current state until the next reconfiguration or
|
||||||
runlevel change. At that point all set conditions transition into the
|
runlevel change. At that point all set conditions transition into the
|
||||||
@@ -107,49 +54,19 @@ 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.
|
||||||
|
|
||||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
> **Note:** For `pid/` conditions it is expected that services "touch"
|
||||||
|
> or recreate their PID file on `SIGHUP`.
|
||||||
> [!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
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Finit comes with a set of plugins for conditions:
|
Finit comes with a `pidfile` and `netlink` plugin. When enabled, the
|
||||||
|
`pidfile` plugin watches `/var/run/` (recursively) for PID files created
|
||||||
- `devmon` (built-in)
|
by the monitored services, and sets a corresponding condition in the
|
||||||
- `netlink`
|
`pid/` namespace. Similarily, the `netlink` plugin provides basic
|
||||||
- `pidfile`
|
conditions for when an interface is brought up/down and when a default
|
||||||
- `sys`
|
route (gateway) is set, in the `net/` namespace.
|
||||||
- `usr`
|
|
||||||
|
|
||||||
The `devmon` (built-in) plugin monitors `/dev` and `/dev/dir` for device
|
|
||||||
nodes being created and removed. It is active only when a run, task, or
|
|
||||||
service has declared a `<dev/foo>` or `<dev/dir/bar>` condition.
|
|
||||||
|
|
||||||
The `pidfile` plugin (recursively) watches `/run/` (recursively) for PID
|
|
||||||
files created by the monitored services, and sets a corresponding
|
|
||||||
condition in the `pid/` namespace.
|
|
||||||
|
|
||||||
Similarly, the `netlink` plugin provides basic conditions for when an
|
|
||||||
interface is brought up/down and when a default route (gateway) is set,
|
|
||||||
in the `net/` namespace.
|
|
||||||
|
|
||||||
The `sys` and `usr` plugins monitor are passive condition monitors where
|
|
||||||
the action is provided by `keventd`, signal handlers, and in the case of
|
|
||||||
`usr`, the end-user via the `initctl` tool.
|
|
||||||
|
|
||||||
Additionally, the various states of a run/task/sysv/service can also be
|
|
||||||
used as conditions, the image above shows the state names. The syntax
|
|
||||||
for a `service` type process: `<service/foo/STATE>`. The other types,
|
|
||||||
in particular run/task/sysv, there are the additional states `success`
|
|
||||||
and `failure`.
|
|
||||||
|
|
||||||
With the example listed above, finit does not start the `/sbin/netd`
|
With the example listed above, finit does not start the `/sbin/netd`
|
||||||
daemon until `setupd` and `zebra` has started *and* created their PID
|
daemon until `setupd` and `zebra` has started *and* created their PID
|
||||||
@@ -168,19 +85,10 @@ Built-in conditions:
|
|||||||
- `net/<IFNAME>/exist`
|
- `net/<IFNAME>/exist`
|
||||||
- `net/<IFNAME>/up`
|
- `net/<IFNAME>/up`
|
||||||
- `net/<IFNAME>/running`
|
- `net/<IFNAME>/running`
|
||||||
- `service/<NAME[:ID]>/<STATE>`
|
|
||||||
- `{run, task, sysv}/<NAME[:ID]>/{<STATE>, success, failure}`
|
|
||||||
- `sys/pwr/ac`
|
|
||||||
- `sys/pwr/fail`
|
|
||||||
- `sys/key/ctrlaltdel`
|
|
||||||
- `usr/foo`
|
|
||||||
- `boot/arg`
|
|
||||||
- `dev/node` and `dev/dir/node`
|
|
||||||
|
|
||||||
> [!NOTE]
|
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
difference is that `running` tells if the NIC has link.
|
||||||
> difference is that `running` tells if the NIC has link.
|
|
||||||
|
|
||||||
|
|
||||||
Composition
|
Composition
|
||||||
@@ -212,9 +120,8 @@ 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]
|
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
||||||
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
> called 'svc' conditions, and they were far more complex.
|
||||||
> conditions, and they were far more complex.
|
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -223,7 +130,7 @@ Debugging
|
|||||||
If a service is not being started as it should, the problem might be
|
If a service is not being started as it should, the problem might be
|
||||||
that one of its conditions is not in the expected state. Use the
|
that one of its conditions is not in the expected state. Use the
|
||||||
command `initctl status` to inspect service status. Services in the
|
command `initctl status` to inspect service status. Services in the
|
||||||
`waiting` state are pending a condition.
|
`ready` state are pending a condition.
|
||||||
|
|
||||||
In that situation, running `initctl cond show` reveals which of the
|
In that situation, running `initctl cond show` reveals which of the
|
||||||
conditions that are not satisfied. Listed as `off` below.
|
conditions that are not satisfied. Listed as `off` below.
|
||||||
@@ -240,7 +147,7 @@ PID IDENT STATUS CONDITION (+ ON, ~ FLUX, - OFF)
|
|||||||
|
|
||||||
Here we can see that `netd` is allowed to run since both its conditions
|
Here we can see that `netd` is allowed to run since both its conditions
|
||||||
are in the `on` state, as indicated by the `+`-prefix. `udhcpc` however
|
are in the `on` state, as indicated by the `+`-prefix. `udhcpc` however
|
||||||
is not allowed to run since `net/vlan1/exist` condition is not satisfied.
|
is not allowed to run since `net/vlan1/exist` condition is not satsifed.
|
||||||
As indicated by the `-`-prefix.
|
As indicated by the `-`-prefix.
|
||||||
|
|
||||||
To fake interface `vlan1` suddenly appearing, and test what happens to
|
To fake interface `vlan1` suddenly appearing, and test what happens to
|
||||||
@@ -291,5 +198,3 @@ Therefore, any plugin that supplies Finit with conditions must ensure
|
|||||||
that their state is updated after each reconfiguration. This can be
|
that their state is updated after each reconfiguration. This can be
|
||||||
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
||||||
to do this, see `plugins/pidfile.c`.
|
to do this, see `plugins/pidfile.c`.
|
||||||
|
|
||||||
[powstatd(8)]: https://manpages.ubuntu.com/manpages/trusty/en/man8/powstatd.8.html
|
|
||||||
|
|||||||
+100
-1060
File diff suppressed because it is too large
Load Diff
+2
-3
@@ -34,9 +34,8 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> **Note:** remember `--prefix` et al as well, the default is likely
|
||||||
> Remember `--prefix` et al as well, the default is likely *not* what
|
> *not* what you want. See the [build docs][1] for details.
|
||||||
> 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
|
||||||
|
|||||||
+29
-159
@@ -8,8 +8,7 @@ Hooks & Plugins
|
|||||||
* [Shutdown Hooks](#shutdown-hooks)
|
* [Shutdown Hooks](#shutdown-hooks)
|
||||||
|
|
||||||
Finit can be extended to add general functionality in the form of I/O
|
Finit can be extended to add general functionality in the form of I/O
|
||||||
monitors, or hook plugins. It is even possible to run scripts at these
|
monitors, or hook plugins.
|
||||||
hook points, see below.
|
|
||||||
|
|
||||||
The following sections detail existing plugins and hook points. For
|
The following sections detail existing plugins and hook points. For
|
||||||
more information, see the plugins listed below.
|
more information, see the plugins listed below.
|
||||||
@@ -28,95 +27,33 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
||||||
file systems must be writable for this plugin to work.
|
file systems must be writable for this plugin to work.
|
||||||
|
|
||||||
This plugin is a wrapper for the [tmpfiles.d(5)][] implementation that
|
Note: On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
||||||
Finit has. Capable but limited: no aging, attributes, or subvolumes.
|
disks and `/dev` is usually a `devtmpfs`. This must be defined in the
|
||||||
|
`/etc/fstab` file and in the Linux kernel config.
|
||||||
By default, `/lib/finit/tmpfiles.d` carries all the default .conf
|
|
||||||
files distributed with Finit. It is read first but can be overridden
|
|
||||||
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
|
||||||
> disks and `/dev` is usually a `devtmpfs`. This must be defined in
|
|
||||||
> the `/etc/fstab` file and in the Linux kernel config.
|
|
||||||
|
|
||||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
|
|
||||||
* *hook-scripts.so*: Trigger the execution of scripts from plugin hook
|
* *hotplug.so*: Setup and start either udev or mdev hotplug daemon, if
|
||||||
points (see [Hooks](#hooks)). _Optional plugin._
|
available.
|
||||||
|
|
||||||
This plugin is particularly useful for early boot debugging that needs
|
|
||||||
to take place before regular services are available.
|
|
||||||
|
|
||||||
For example, say that you want to enable some kernel tracing before
|
|
||||||
modules are loaded. With hook scripts, you can just drop in a shell
|
|
||||||
script in `/libexec/finit/hook/mount/all/` that will poke the right
|
|
||||||
control files in tracefs.
|
|
||||||
|
|
||||||
Scripts are located in `/libexec/finit/hook` by default, this can be
|
|
||||||
customized at build-time using the `--with-hook-scripts-path=PATH`
|
|
||||||
argument to `configure`.
|
|
||||||
|
|
||||||
* *hotplug.so*: Replaced with `/lib/finit/system/10-hotplug.conf`, which
|
|
||||||
checks for `udevd` and `mdev` at boot. This file can be overridden by a
|
|
||||||
file in `/etc/finit.d/10-hotplug.conf`.
|
|
||||||
|
|
||||||
Enabled by default.
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> See the [Services](config.md#services) section in the configuration
|
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
|
||||||
|
|
||||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||||
Enabled by default.
|
|
||||||
|
|
||||||
* *modules-load.so*: Scans `/etc/modules-load.d/*.conf` for modules to
|
* *modules-load.so*: Scans /etc/modules-load.d for modules to modprobe.
|
||||||
load using `modprobe`. Each file can contain multiple lines with the
|
|
||||||
name of the module to load. Any line starting with the standard UNIX
|
|
||||||
comment character, `#`, or `;`, is skipped.
|
|
||||||
|
|
||||||
Modules are by default loaded in runlevel `S` using the `task` stanza.
|
|
||||||
Each module gets a unique `name:modprobe.foo`, and optional`:ID`. The
|
|
||||||
runlevel can be changed per file using:
|
|
||||||
|
|
||||||
set runlevel 2345
|
|
||||||
|
|
||||||
The `:ID` is a globally incremented index, which can be disabled per
|
|
||||||
file (anywhere) using the following config line:
|
|
||||||
|
|
||||||
set noindex
|
|
||||||
|
|
||||||
To change the index used by the plugin:
|
|
||||||
|
|
||||||
set index 1234
|
|
||||||
|
|
||||||
Since these tasks run in the background, they return `[ OK ]` at boot,
|
|
||||||
unless the modprobe tool does not exist. Check syslog for warnings
|
|
||||||
and the actual status of the operation using `initctl`.
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> Unlike the traditional .conf `module` directive, which load any listed
|
|
||||||
> module immediately, this plugin creates a background `task` which load
|
|
||||||
> the module(s) in the background. The program is modprobe,
|
|
||||||
> `/sbin/modprobe`, which you can override per .conf file:
|
|
||||||
>
|
|
||||||
> set modprobe /path/to/maybe-a-modprobe-wrapper
|
|
||||||
|
|
||||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
* *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
|
||||||
for services that may want to be SIGHUP'ed on new default route or
|
for services that may want to be SIGHUP'ed on new default route or
|
||||||
interfaces going up/down. Enabled by default.
|
interfaces going up/down.
|
||||||
|
|
||||||
* *resolvconf.so*: Setup necessary files for `resolvconf` at startup.
|
* *resolvconf.so*: Setup necessary files for `resolvconf` at startup.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
|
|
||||||
* *tty.so*: Watches `/dev`, using inotify, for new device nodes (TTY's)
|
* *tty.so*: Watches `/dev`, using inotify, for new device nodes (TTY's)
|
||||||
to start/stop getty consoles on them on demand. Useful when plugging
|
to start/stop getty consoles on them on demand. Useful when plugging
|
||||||
in a usb2serial converter to login to your embedded device. Enabled
|
in a usb2serial converter to login to your embedded device.
|
||||||
by default.
|
|
||||||
|
|
||||||
* *urandom.so*: Setup random seed at startup. Enabled by default.
|
* *urandom.so*: Setup random seed at startup.
|
||||||
|
|
||||||
* *x11-common.so*: Setup necessary files for X-Window. _Optional plugin._
|
* *x11-common.so*: Setup necessary files for X-Window. _Optional plugin._
|
||||||
|
|
||||||
@@ -130,107 +67,40 @@ state, etc. Available hook points are:
|
|||||||
Hooks
|
Hooks
|
||||||
-----
|
-----
|
||||||
|
|
||||||
In the below listings, the first label is the hook point for a C plugin,
|
|
||||||
the second is the condition name and hook script path. A hook script is
|
|
||||||
a plain shell script, or program, that does a very small dedicated job
|
|
||||||
at the below hook points.
|
|
||||||
|
|
||||||
See [Run-parts Scripts](config.md#run-parts-scripts) for details on the
|
|
||||||
requirements, possibilities, and *limitations* of hook scripts.
|
|
||||||
|
|
||||||
All hook scripts are called with at least one environment variable set,
|
|
||||||
the hook name, useful when reusing the same hook script for multiple
|
|
||||||
hook points:
|
|
||||||
|
|
||||||
- `FINIT_HOOK_NAME`: set to the second label, e.g., `hook/net/up`
|
|
||||||
- `FINIT_SHUTDOWN`: set for `hook/sys/shutdown` and later to one
|
|
||||||
of `halt`, `poweroff`, or `reboot`.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
$ mkdir -p /libexec/finit/hook/sys/down
|
|
||||||
$ cat <<EOF >/libexec/finit/hook/sys/down/foo.sh
|
|
||||||
#!/bin/sh
|
|
||||||
echo 'I run just before the reboot() syscall at shutdown/reboot'
|
|
||||||
echo 'I have access to /dev since devtmpfs is exempt from umount'
|
|
||||||
echo "FINIT_HOOK_NAME: $FINIT_HOOK_NAME"
|
|
||||||
if [ -n "$FINIT_SHUTDOWN" ]; then
|
|
||||||
echo "FINIT_SHUTDOWN: $FINIT_SHUTDOWN"
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
EOF
|
|
||||||
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> 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
|
||||||
|
|
||||||
* `HOOK_BANNER`, `hook/sys/banner`: The very first point at which a
|
* `HOOK_ROOTFS_UP`: When `finit.conf` has been read and `/` has is
|
||||||
plugin can run. Intended to be used as a banner replacement.
|
mounted — very early
|
||||||
Essentially this runs just before entering runlevel S. Assume nothing
|
|
||||||
is available, so be prepared to use absolute paths, etc.
|
|
||||||
|
|
||||||
* `HOOK_ROOTFS_UP`, `hook/mount/root`: When `finit.conf` has been read
|
* `HOOK_BASEFS_UP`: All of `/etc/fstab` is mounted, swap is available
|
||||||
and `/` has is mounted — very early
|
and default init signals are setup
|
||||||
|
|
||||||
* `HOOK_MOUNT_ERROR`, `hook/mount/error`: executed if `mount -a` fails
|
* `HOOK_NETWORK_UP`: System bootstrap, runlevel S, has completed and
|
||||||
|
networking is up (`lo` is up and the `network` script has run)
|
||||||
|
|
||||||
* `HOOK_MOUNT_POST`, `hook/mount/post`: always executed after `mount -a`
|
* `HOOK_SVC_UP`: All services in the active runlevel has been launched
|
||||||
|
|
||||||
* `HOOK_BASEFS_UP`, `hook/mount/all`: All of `/etc/fstab` is mounted,
|
* `HOOK_SYSTEM_UP`: All services *and* everything in `/etc/finit.d`
|
||||||
swap is available and default init signals are setup
|
has been launched
|
||||||
|
|
||||||
* `HOOK_SVC_PLUGIN`, `hook/svc/plugin`: Called in `conf_init()` right
|
|
||||||
before loading `/etc/finit.conf`. For plugins to register any early
|
|
||||||
run/task/services, please do NOT use any earlier hook point. That
|
|
||||||
will cause uninitialized rlimits that lead to unpredictable results
|
|
||||||
when Finit later tries to start the run/task/service.
|
|
||||||
|
|
||||||
* `HOOK_NETWORK_UP`, `hook/net/up`: System bootstrap, runlevel S, has
|
|
||||||
completed and networking is up (`lo` is up and the `network` script
|
|
||||||
has run)
|
|
||||||
|
|
||||||
* `HOOK_SVC_UP`, `hook/svc/up`: All services in the active runlevel have
|
|
||||||
been launched
|
|
||||||
|
|
||||||
* `HOOK_SYSTEM_UP`, `hook/sys/up`: All services *and* everything in
|
|
||||||
`/etc/finit.d` has been launched
|
|
||||||
|
|
||||||
### Runtime Hooks
|
### Runtime Hooks
|
||||||
|
|
||||||
* `HOOK_SVC_RECONF`, N/A: Called when the user has changed something in
|
* `HOOK_SVC_RECONF`: Called when the user has changed something in the
|
||||||
the `/etc/finit.d` directory and issued `SIGHUP`. The hook is called
|
`/etc/finit.d` directory and issued `SIGHUP`. The hook is called when
|
||||||
when all modified/removed services have been stopped. When the hook
|
all modified/removed services have been stopped. When the hook has
|
||||||
has completed, Finit continues to start all modified and new services.
|
completed, Finit continues to start all modified and new services.
|
||||||
|
|
||||||
* `HOOK_RUNLEVEL_CHANGE`, N/A: Called when the user has issued a
|
* `HOOK_RUNLEVEL_CHANGE`: Called when the user has issued a runlevel
|
||||||
runlevel change. The hook is called when services not matching the
|
change. The hook is called when services not matching the new
|
||||||
new runlevel have been been stopped. When the hook has completed,
|
runlevel have been been stopped. When the hook has completed, Finit
|
||||||
Finit continues to start all services in the new runlevel.
|
continues to start all services in the new runlevel.
|
||||||
|
|
||||||
### Shutdown Hooks
|
### Shutdown Hooks
|
||||||
|
|
||||||
* `HOOK_NETWORK_DN`, `hook/net/down`: Called right after having changed
|
* `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all
|
||||||
to runlevel 6, or 0, when all services have received their 'stop' signal.
|
services are sent `SIGTERM`
|
||||||
|
|
||||||
* `HOOK_SHUTDOWN`, `hook/sys/shutdown`: Called at shutdown/reboot, right
|
|
||||||
before all services are sent `SIGTERM`
|
|
||||||
|
|
||||||
* `HOOK_SVC_DN`, `hook/svc/down`: In shutdown/reboot, all services and
|
|
||||||
non-reserved processes have been killed. **Note:** only hook scripts
|
|
||||||
can run here!
|
|
||||||
|
|
||||||
* `HOOK_SYSTEM_DN`, `hook/sys/down`: In shutdown/reboot, called after
|
|
||||||
all non-reserved file systems have been unmounted, just before Finit
|
|
||||||
tells the kernel to reboot or shut down. **Note:** only hook scripts
|
|
||||||
can run here!
|
|
||||||
|
|
||||||
Plugins like `tty.so` extend finit by acting on events, they are called
|
Plugins like `tty.so` extend finit by acting on events, they are called
|
||||||
I/O plugins and are called from the finit main loop when `poll()`
|
I/O plugins and are called from the finit main loop when `poll()`
|
||||||
detects an event. See the source code for `plugins/*.c` for more help
|
detects an event. See the source code for `plugins/*.c` for more help
|
||||||
and ideas.
|
and ideas.
|
||||||
|
|
||||||
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
|
||||||
|
|||||||
+2
-57
@@ -1,60 +1,7 @@
|
|||||||
Finit Services
|
Finit Services
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Starting & Monitoring
|

|
||||||
---------------------
|
|
||||||
|
|
||||||
Finit can start and monitor the following types of daemons:
|
|
||||||
|
|
||||||
* Forks to background, creates a PID file
|
|
||||||
* Runs in foreground:
|
|
||||||
- creates a PID file
|
|
||||||
- does not create a PID file -- Finit can create it for you (optional)
|
|
||||||
|
|
||||||
Finit can *not* start and monitor a daemon that:
|
|
||||||
|
|
||||||
* Forks to background and does *not* create a PID file
|
|
||||||
|
|
||||||
| | Forking | Creates PID File | Finit creates PID File |
|
|
||||||
|---|---------|------------------|------------------------|
|
|
||||||
| ✔ | Yes | Yes | No |
|
|
||||||
| ✔ | No | Yes | No |
|
|
||||||
| ✔ | No | No | Yes, optionally |
|
|
||||||
| ✘ | Yes | No | No |
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> PID files is one mechanism used to assert conditions to synchronize
|
|
||||||
> the start and stop of other, dependent, services.
|
|
||||||
|
|
||||||
### Forks to Background w/ PID File
|
|
||||||
|
|
||||||
There are two syntax variants, type 1 and type 2. The former is the
|
|
||||||
traditional one used also for `sysv` start/stop scripts, and the latter
|
|
||||||
is inspired by systemd, with a twist -- it lets Finit guess the pifdile
|
|
||||||
to look for based on the standard path and the basename of the command.
|
|
||||||
|
|
||||||
service pid:!/run/serv.pid serv -- Forking service, type 1
|
|
||||||
service type:forking serv -- Forking service, type 2
|
|
||||||
|
|
||||||
In this example the resulting files to watch for are `/run/serv.pid` and
|
|
||||||
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
|
||||||
the same directory (`/var/run` is a symlink to `../run`).
|
|
||||||
|
|
||||||
### Runs in Foreground w/ PID File
|
|
||||||
|
|
||||||
service serv -n -p -- Foreground service w/ PID file
|
|
||||||
|
|
||||||
### Runs in Foreground w/o PID File
|
|
||||||
|
|
||||||
Same as previous, but we tell Finit to create the PID file, because we
|
|
||||||
need it to synchronize start/stop of a dependent service.
|
|
||||||
|
|
||||||
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
|
||||||
|
|
||||||
### Runs in Foreground w/ Custom PID File
|
|
||||||
|
|
||||||
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
|
||||||
|
|
||||||
|
|
||||||
State Machine
|
State Machine
|
||||||
-------------
|
-------------
|
||||||
@@ -64,8 +11,6 @@ For `run`s and `task`s there is an additional end state called `DONE`,
|
|||||||
not shown in the diagram for brevity. Services start in the `HALTED`
|
not shown in the diagram for brevity. Services start in the `HALTED`
|
||||||
state.
|
state.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The current state depends on the two following conditions:
|
The current state depends on the two following conditions:
|
||||||
|
|
||||||
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
||||||
@@ -73,7 +18,7 @@ The current state depends on the two following conditions:
|
|||||||
|
|
||||||
A service may be stopped, or blocked, for several reasons:
|
A service may be stopped, or blocked, for several reasons:
|
||||||
|
|
||||||
- The user has manually stopped the service using `initctl stop NAME`
|
- The user has manually stopped the service using `initctl stop JOB`
|
||||||
- The program exits immediately. I.e. keeps crashing (make sure to use
|
- The program exits immediately. I.e. keeps crashing (make sure to use
|
||||||
the 'run this service in the foreground' command line option)
|
the 'run this service in the foreground' command line option)
|
||||||
- The binary is missing in the filesystem
|
- The binary is missing in the filesystem
|
||||||
|
|||||||
+9
-17
@@ -12,36 +12,28 @@ have been adopted:
|
|||||||
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
||||||
*.conf files in `/etc/finit.d/`
|
*.conf files in `/etc/finit.d/`
|
||||||
|
|
||||||
This also restarts the API (initctl) socket, like SysV init and systemd
|
|
||||||
does on USR1 with their FIFO/D-Bus.
|
|
||||||
|
|
||||||
|
|
||||||
`SIGUSR1`
|
`SIGUSR1`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Since Finit 4.1 this signal causes Finit to restart its API (initctl)
|
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
||||||
socket, like SysV init and systemd does on USR1 with their FIFO/D-Bus.
|
processes, and unmounts all file systems. Then tells kernel to halt.
|
||||||
|
Most people these days want `SIGUSR2` though.
|
||||||
Finit <= 4.0 performed a system halt (like USR2 without power-off), but
|
|
||||||
this caused compatibility problems with systemd and sysvinit on desktop
|
|
||||||
systems. Hence, since Finit 4.1 it is no longer possible to halt a
|
|
||||||
system with a signal.
|
|
||||||
|
|
||||||
|
SysV init and systemd use this to re-open their FIFO/D-Bus.
|
||||||
|
|
||||||
`SIGUSR2`
|
`SIGUSR2`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
Like SIGUSR1, but tell kernel to power-off the system, if ACPI or
|
||||||
processes, and unmounts all file systems. Then tells kernel to power
|
similar exists to actually do this. If the kernel fails power-off,
|
||||||
off the system, if ACPI or similar exists to actually do this. If the
|
Finit falls back to halt.
|
||||||
kernel fails power-off, Finit falls back to halt.
|
|
||||||
|
|
||||||
SysV init N/A, systemd dumps its internal state to log.
|
SysV init N/A, systemd dumps its internal state to log.
|
||||||
|
|
||||||
`SIGTERM`
|
`SIGTERM`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Like `SIGUSR2`, but tell kernel to reboot the system when done.
|
Like `SIGUSR1`, but tell kernel to reboot the system when done.
|
||||||
|
|
||||||
SysV init N/A, systemd rexecutes itself.
|
SysV init N/A, systemd rexecutes itself.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 16 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 814 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -1,141 +0,0 @@
|
|||||||
_cond()
|
|
||||||
{
|
|
||||||
initctl -pt cond dump | awk '{print $4}' | sed 's/<\(.*\)>/\1/'
|
|
||||||
}
|
|
||||||
|
|
||||||
_ident()
|
|
||||||
{
|
|
||||||
if [ -n "$1" ]; then
|
|
||||||
initctl ident | grep -q $1
|
|
||||||
else
|
|
||||||
initctl ident
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_svc()
|
|
||||||
{
|
|
||||||
initctl ls -pt | grep $1 | sed "s/.*\/\(.*\)/\1/g" | sort -u
|
|
||||||
}
|
|
||||||
|
|
||||||
_enabled()
|
|
||||||
{
|
|
||||||
echo "$(_svc enabled)"
|
|
||||||
}
|
|
||||||
|
|
||||||
_available()
|
|
||||||
{
|
|
||||||
all=$(mktemp)
|
|
||||||
ena=$(mktemp)
|
|
||||||
echo "$(_svc available)" >$all
|
|
||||||
echo "$(_svc enabled)" >$ena
|
|
||||||
grep -v -f $ena $all
|
|
||||||
rm $all $ena
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine first non-option word. Usually the command
|
|
||||||
_firstword() {
|
|
||||||
local firstword i
|
|
||||||
|
|
||||||
firstword=
|
|
||||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
|
||||||
if [[ ${COMP_WORDS[i]} != -* ]]; then
|
|
||||||
firstword=${COMP_WORDS[i]}
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo $firstword
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine last non-option word. Uusally a sub-command
|
|
||||||
_lastword() {
|
|
||||||
local lastword i
|
|
||||||
|
|
||||||
lastword=
|
|
||||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
|
||||||
if [[ ${COMP_WORDS[i]} != -* ]] && [[ -n ${COMP_WORDS[i]} ]] && [[ ${COMP_WORDS[i]} != $cur ]]; then
|
|
||||||
lastword=${COMP_WORDS[i]}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo $lastword
|
|
||||||
}
|
|
||||||
|
|
||||||
_initctl()
|
|
||||||
{
|
|
||||||
local cur command
|
|
||||||
|
|
||||||
cur=${COMP_WORDS[COMP_CWORD]}
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
firstword=$(_firstword)
|
|
||||||
lastword=$(_lastword)
|
|
||||||
|
|
||||||
commands="status cond debug help kill ls log version list enable \
|
|
||||||
disable touch show cat edit create delete reload start \
|
|
||||||
stop restart signal cgroup ps top plugins runlevel reboot \
|
|
||||||
halt poweroff suspend utmp"
|
|
||||||
cond_cmds="set get clear status dump"
|
|
||||||
cond_types="hook net pid service task usr"
|
|
||||||
signals="int term hup stop tstp cont usr1 usr2 pwr"
|
|
||||||
options="-b --batch \
|
|
||||||
-c --create \
|
|
||||||
-d --debug \
|
|
||||||
-f --force \
|
|
||||||
-h --help \
|
|
||||||
-j --json \
|
|
||||||
-n --noerr \
|
|
||||||
-1 --once \
|
|
||||||
-p --plain \
|
|
||||||
-q --quiet \
|
|
||||||
-t --no-heading \
|
|
||||||
-v --verbose \
|
|
||||||
-V --version"
|
|
||||||
|
|
||||||
case "${firstword}" in
|
|
||||||
enable)
|
|
||||||
COMPREPLY=($(compgen -W "$(_available)" -- $cur))
|
|
||||||
;;
|
|
||||||
disable|touch)
|
|
||||||
COMPREPLY=($(compgen -W "$(_enabled)" -- $cur))
|
|
||||||
;;
|
|
||||||
show|cat|edit|delete)
|
|
||||||
COMPREPLY=($(compgen -W "$(_svc .)" -- $cur))
|
|
||||||
;;
|
|
||||||
start|stop|restart|log|status)
|
|
||||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
|
||||||
;;
|
|
||||||
signal|kill)
|
|
||||||
if $(_ident "${prev}"); then
|
|
||||||
COMPREPLY=($(compgen -W "$signals" -- $cur))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
cond)
|
|
||||||
case "${lastword}" in
|
|
||||||
set|clear)
|
|
||||||
compopt -o nospace
|
|
||||||
COMPREPLY=($(compgen -W "usr/" -- $cur))
|
|
||||||
;;
|
|
||||||
get)
|
|
||||||
COMPREPLY=($(compgen -W "$(_cond)" -- $cur))
|
|
||||||
;;
|
|
||||||
dump)
|
|
||||||
COMPREPLY=($(compgen -W "$cond_types" -- $cur))
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
COMPREPLY=($(compgen -W "$cond_cmds" -- $cur))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
COMPREPLY=($(compgen -W "$commands" -- $cur))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ $cur == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$options" -- $cur))
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _initctl initctl
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
.deps/*
|
|
||||||
.libs/*
|
|
||||||
.dirstamp
|
|
||||||
*.lo
|
|
||||||
libsystemd.*
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
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}
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
/* 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;
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#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_ */
|
|
||||||
+23
-19
@@ -1,6 +1,8 @@
|
|||||||
# From https://github.com/collectd/collectd/blob/master/configure.ac
|
# From https://github.com/collectd/collectd/blob/master/configure.ac
|
||||||
# Dependency handling currently unused
|
# Dependency handling currently unused
|
||||||
|
|
||||||
|
define([toupper], [translit([$1], [a-z], [A-Z])])
|
||||||
|
define([sanitize], [translit([$1], [-], [_])])
|
||||||
define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
||||||
|
|
||||||
# AC_PLUGIN(name, default, info)
|
# AC_PLUGIN(name, default, info)
|
||||||
@@ -8,25 +10,27 @@ define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
|||||||
AC_DEFUN([AC_PLUGIN],[
|
AC_DEFUN([AC_PLUGIN],[
|
||||||
m4_divert_once([HELP_ENABLE], [
|
m4_divert_once([HELP_ENABLE], [
|
||||||
Optional Plugins:])
|
Optional Plugins:])
|
||||||
define(PLUGGY, m4_translit([$1],[a-z-][A-Z-]))dnl
|
|
||||||
AC_ARG_ENABLE([$1-plugin], AS_HELP_STRING([--enadis($2)-$1-plugin], [$3]), [
|
|
||||||
if test "x$enableval" = "xyes"; then
|
|
||||||
enable_plugin="yes"
|
|
||||||
else
|
|
||||||
enable_plugin="no"
|
enable_plugin="no"
|
||||||
fi], [
|
define(pluggy, sanitize($1))
|
||||||
if test "x$enable_all_plugins" = "xauto"; then
|
define(PLUGGY, toupper(pluggy))
|
||||||
if test "x$2" = "xyes"; then
|
AC_ARG_ENABLE([$1-plugin], AS_HELP_STRING([--enadis($2)-$1-plugin], [$3]), [
|
||||||
enable_plugin="yes"
|
if test "x$enableval" = "xyes"; then
|
||||||
|
enable_plugin="yes"
|
||||||
else
|
else
|
||||||
enable_plugin="no"
|
enable_plugin="no"
|
||||||
|
fi], [
|
||||||
|
if test "x$enable_all_plugins" = "xauto"; then
|
||||||
|
if test "x$2" = "xyes"; then
|
||||||
|
enable_plugin="yes"
|
||||||
|
else
|
||||||
|
enable_plugin="no"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
enable_plugin="$enable_all_plugins"
|
||||||
|
fi])
|
||||||
|
if test "x$enable_plugin" = "xyes"; then
|
||||||
|
AC_DEFINE([HAVE_]PLUGGY[_PLUGIN], 1, [Define to 1 if the $1 plugin is enabled.])
|
||||||
|
plugins="$1 $plugins"
|
||||||
fi
|
fi
|
||||||
else
|
AM_CONDITIONAL([BUILD_]PLUGGY[_PLUGIN], test "x$enable_plugin" = "xyes")
|
||||||
enable_plugin="$enable_all_plugins"
|
enable_pluggy="$enable_plugin"])
|
||||||
fi])
|
|
||||||
if test "x$enable_plugin" = "xyes"; then
|
|
||||||
AC_DEFINE(HAVE_[]m4_translit($1,[-a-z],[_A-Z])_PLUGIN, 1, [Define to 1 if the $1 plugin is enabled.])
|
|
||||||
plugins="$1 $plugins"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_[]m4_translit($1,[-a-z],[_A-Z])_PLUGIN, test "x$enable_plugin" = "xyes")])
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
dist_man8_MANS = finit.8 initctl.8
|
|
||||||
dist_man5_MANS = finit.conf.5
|
|
||||||
-348
@@ -1,348 +0,0 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
|
||||||
.\" First parameter, NAME, should be all caps
|
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
|
||||||
.Dd Apr 22, 2023
|
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
|
||||||
.Dt FINIT 8 SMM
|
|
||||||
.Os Linux
|
|
||||||
.Sh NAME
|
|
||||||
.Nm finit
|
|
||||||
.Nd Fast init for Linux systems
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm /sbin/finit
|
|
||||||
.Op --
|
|
||||||
.Op debug
|
|
||||||
.Op finit.cond=foo[,bar[,baz]]
|
|
||||||
.Op finit.config=/path/to/alt/finit.conf
|
|
||||||
.Op finit.debug
|
|
||||||
.Op finit.fstab=/etc/fstab.alt
|
|
||||||
.Op finit.status=<on,off>
|
|
||||||
.Op finit.status_style=<classic,modern>
|
|
||||||
.Op loglevel=<0-7>
|
|
||||||
.Op panic=SEC
|
|
||||||
.Op quiet
|
|
||||||
.Op rescue | recover
|
|
||||||
.Op single | S
|
|
||||||
.Nm /sbin/telinit
|
|
||||||
.Op Fl hv
|
|
||||||
.Op q | Q | 0-9
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
Fast init for Linux systems. Reverse engineered from the EeePC
|
|
||||||
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
|
||||||
DNA ...". Focus is on small and embedded systems, although Finit is
|
|
||||||
fully usable on server and desktop systems as well.
|
|
||||||
.Pp
|
|
||||||
Features include:
|
|
||||||
.Bl -bullet -width 1n -compact
|
|
||||||
.It
|
|
||||||
Runlevels, defined per service
|
|
||||||
.It
|
|
||||||
One-shot tasks, services (daemons), or SysV init start/stop scripts
|
|
||||||
.It
|
|
||||||
Runparts and
|
|
||||||
.Pa /etc/rc.local
|
|
||||||
support
|
|
||||||
.It
|
|
||||||
Process supervision similar to
|
|
||||||
.Xr systemd 8
|
|
||||||
.It
|
|
||||||
Sourcing environment files
|
|
||||||
.It
|
|
||||||
Conditions for network/process/custom dependencies
|
|
||||||
.It
|
|
||||||
Process readiness notification for synchronizing system startup as well
|
|
||||||
as reconfiguration at runtime. Natively PID files are used, but systemd
|
|
||||||
.Cm sd_notify()
|
|
||||||
and s6 notification is also supported.
|
|
||||||
.It
|
|
||||||
Limited support for
|
|
||||||
.Xr tmpfiles.d 5 ,
|
|
||||||
no aging, attributes, or subvolumes
|
|
||||||
.It
|
|
||||||
Pre/Post script actions
|
|
||||||
.It
|
|
||||||
Tooling to enable/disable services
|
|
||||||
.It
|
|
||||||
Built-in getty
|
|
||||||
.It
|
|
||||||
Built-in watchdog, with support for hand-over to
|
|
||||||
.Lk https://troglobit.com/watchdogd.html watchdogd
|
|
||||||
.It
|
|
||||||
Built-in support for Debian/BusyBox
|
|
||||||
.Pa /etc/network/interfaces
|
|
||||||
.It
|
|
||||||
Cgroups v2, both configuration and monitoring in `initctl top`
|
|
||||||
.It
|
|
||||||
Plugin support for customization
|
|
||||||
.It
|
|
||||||
Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
|
||||||
.El
|
|
||||||
.Sh BOOTPARAM
|
|
||||||
.Nm
|
|
||||||
support the following command line parameters to alter the behavior
|
|
||||||
at boot. Notice the
|
|
||||||
.Cm --
|
|
||||||
separator needed to tell the kernel which paramters should be given to
|
|
||||||
PID 1. For more information on this, and available kernel command line
|
|
||||||
options, see
|
|
||||||
.Xr bootparam 7 .
|
|
||||||
.Bl -tag -width pid -offset indent
|
|
||||||
.It Cm debug
|
|
||||||
Enable kernel debug. Debug messages are printed to the console until
|
|
||||||
Finit starts up, unless
|
|
||||||
.Cm loglevel=7
|
|
||||||
(below) is used.
|
|
||||||
.It Cm finit.cond=foo[,bar[,baz]]
|
|
||||||
set
|
|
||||||
.Cm <boot/foo>
|
|
||||||
condition, optionally multiple conditions can be set using the same
|
|
||||||
option, separated with a comma. Alternatively, multiple
|
|
||||||
.Cm foo.cond=arg
|
|
||||||
can be given. Each will result in a
|
|
||||||
.Cm <boot/arg>
|
|
||||||
condition being set to control the rest of the system bootstrap.
|
|
||||||
.Pp
|
|
||||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
|
||||||
firmware upgrade, or rescue mode.
|
|
||||||
.Pp
|
|
||||||
.Sy Note:
|
|
||||||
.Cm <boot/...>
|
|
||||||
conditions cannot be cleared with
|
|
||||||
.Nm initctl !
|
|
||||||
.It Cm finit.config=/path/to/alternative/finit.conf
|
|
||||||
override the compile-time bootstrap config file, default:
|
|
||||||
.Bd -unfilled -offset indent
|
|
||||||
./configure --with-config=/etc/finit.conf
|
|
||||||
.Ed
|
|
||||||
Useful when starting up in various rescue mode, factory, or
|
|
||||||
production test setups. Use the top-level configuration file
|
|
||||||
directive
|
|
||||||
.Cm rcsd Ar /path/to/finit.d
|
|
||||||
to override the default rcS.d directory.
|
|
||||||
.It Cm finit.debug
|
|
||||||
Enable Finit debug messages on system console and log. Sometimes useful
|
|
||||||
when doing board bringup. Before the system log daemon has started,
|
|
||||||
Finit use the kernel ring buffer,
|
|
||||||
.Pa /dev/kmsg .
|
|
||||||
.It Cm finit.fstab=/path/to/fstab.alt
|
|
||||||
Tell
|
|
||||||
.Nm
|
|
||||||
to use an alternate
|
|
||||||
.Cm fstab
|
|
||||||
to mount the file system from. Remember, this file must be on the
|
|
||||||
.Cm root=...
|
|
||||||
file system provided to Finit from the kernel. If this file is missing,
|
|
||||||
.Nm
|
|
||||||
falls back to its built-in default, which can be changed at build time
|
|
||||||
using the
|
|
||||||
.Cm --with-fstab=/path/to/footab
|
|
||||||
configure option. It is even possible to completely disable the
|
|
||||||
built-in using
|
|
||||||
.Cm --without-fstab ,
|
|
||||||
meaning
|
|
||||||
.Nm
|
|
||||||
.Sy must
|
|
||||||
be started with the
|
|
||||||
.Cm finit.fstab
|
|
||||||
option.
|
|
||||||
.Pp
|
|
||||||
Should
|
|
||||||
.Nm
|
|
||||||
discover that there is no fstab file available, including the fallback,
|
|
||||||
it triggers the same failure mode as when
|
|
||||||
.Cm fsck
|
|
||||||
fails, starting
|
|
||||||
.Xr sulogin 8 ,
|
|
||||||
if that is availble. When
|
|
||||||
.Cm sulogin
|
|
||||||
is missing, or when the user exits from
|
|
||||||
.Cm sulogin ,
|
|
||||||
the system is rebooted.
|
|
||||||
.Pp
|
|
||||||
Default fstab, unless changed at build-time:
|
|
||||||
.Pa /etc/fstab
|
|
||||||
.It Cm finit.status=<on,off>
|
|
||||||
Control finit boot progress, including banner. This used to be called
|
|
||||||
.Cm finit.show_status ,
|
|
||||||
which still works but is deprecated.
|
|
||||||
.It Cm finit.status_style=<classic,modern>
|
|
||||||
Set Finit boot progress style, when enabled.
|
|
||||||
.It Cm loglevel=<0-7>
|
|
||||||
set the kernel's log level, which is more granular than
|
|
||||||
.Cm debug .
|
|
||||||
Also, when
|
|
||||||
.Cm loglevel=7 ,
|
|
||||||
Finit will
|
|
||||||
.Em not disable
|
|
||||||
kernel logs to the console. This is very useful when debugging the
|
|
||||||
kernel at system bring-up. Since
|
|
||||||
.Cm loglevel=7
|
|
||||||
is the same as
|
|
||||||
.Cm debug
|
|
||||||
this means you have to use
|
|
||||||
.Cm quiet
|
|
||||||
for a quiet boot, until sysklogd takes over logging of kernel events.
|
|
||||||
.It Cm panic=SEC
|
|
||||||
By default the kernel does not reboot after a kernel panic. This
|
|
||||||
setting will cause a kernel reboot after
|
|
||||||
.Ar SEC
|
|
||||||
seconds.
|
|
||||||
.It Cm quiet
|
|
||||||
Suppress kernel logging to console, except for warnings and errors.
|
|
||||||
Also, see
|
|
||||||
.Cm loglevel
|
|
||||||
and
|
|
||||||
.Cm quiet
|
|
||||||
above.
|
|
||||||
.It Cm rescue | recover
|
|
||||||
Start rescue/maintenance mode. If your system comes with the bundled
|
|
||||||
.Cm sulogin
|
|
||||||
program (Finit, or from util-linux/Busybox), you will be given a root
|
|
||||||
login to a maintenance shell. However, if
|
|
||||||
.Cm sulogin
|
|
||||||
is missing, the file
|
|
||||||
.Pa /lib/finit/rescue.conf
|
|
||||||
is read and the system booted in a limited fallback mode. See
|
|
||||||
.Xr finit.conf 5
|
|
||||||
for more information.
|
|
||||||
.It Cm single | S
|
|
||||||
Single user mode, runlevel 1, in Finit. Useful to debug problems with
|
|
||||||
the regular runlevel. All services and TTYs in
|
|
||||||
.Cm [1]
|
|
||||||
will be started, e.g., a
|
|
||||||
.Cm tty [1] @console nologin
|
|
||||||
configuration presents you with a root console without login.
|
|
||||||
.Pp
|
|
||||||
.Sy Note:
|
|
||||||
by definition, single user mode does not have networking enabled. This
|
|
||||||
is also true for runlevel 1.
|
|
||||||
.El
|
|
||||||
.Sh BOOTING
|
|
||||||
.Pp
|
|
||||||
Before laucnhing services, the system needs to be bootstrapped. This
|
|
||||||
involves mounting all filesystems (not already mounted by an initramfs)
|
|
||||||
in
|
|
||||||
.Pa /etc/fstab ,
|
|
||||||
or any alternate
|
|
||||||
.Pa fstab
|
|
||||||
file provided on the Finit command line using
|
|
||||||
.Cm finit.fstab ,
|
|
||||||
ensuring that necessary filesystems like:
|
|
||||||
.Pa /dev ,
|
|
||||||
.Pa /proc ,
|
|
||||||
.Pa /sys ,
|
|
||||||
and
|
|
||||||
.Pa /run
|
|
||||||
are available and can provide the system with the services required.
|
|
||||||
.Pp
|
|
||||||
With that out of the way, a set of plugins take over:
|
|
||||||
.Pp
|
|
||||||
.Bl -tag -width bootmisc.so -offset indent
|
|
||||||
.It Cm bootmisc.so
|
|
||||||
Cleans up stale files from previous boots and default directories are
|
|
||||||
created in tmpfs filesystems
|
|
||||||
.It Cm modprobe.so
|
|
||||||
Probes kernel modules required by the system
|
|
||||||
.It Cm procps.so
|
|
||||||
Set kernel variables from
|
|
||||||
.Pa /etc/sysctl.conf
|
|
||||||
et al
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
When the plugins are done, finit reads
|
|
||||||
.Pa /etc/finit.conf
|
|
||||||
and all other enabled services in
|
|
||||||
.Pa /etc/finit.d/* .
|
|
||||||
First all services, run/tasks in runlevel S (bootStrap) are started,
|
|
||||||
When all run/tasks have completed, Finit changes to the configured
|
|
||||||
runlevel (default 2), Processes are started in parallel, in dependency
|
|
||||||
order according to their conditions.
|
|
||||||
.Pp
|
|
||||||
When all services and run/tasks have been started, the console progress
|
|
||||||
is disabled and all configured getty services are started.
|
|
||||||
.Sh CONDITIONS
|
|
||||||
The condition subysystem in Finit was initially created to track PID
|
|
||||||
files of daemons. If service/task B requires service A to have started,
|
|
||||||
Finit waits for the PID file of service A to be created/updated before
|
|
||||||
it starts service B. Conversely, if service A is stopped and its PID
|
|
||||||
file removed, service B is also stopped.
|
|
||||||
.Pp
|
|
||||||
The following condition families are available today:
|
|
||||||
.Pp
|
|
||||||
.Bl -tag -width service -offset indent
|
|
||||||
.It Cm net
|
|
||||||
Linux netlink events, e.g. net/route/default, net/eth0/up, and
|
|
||||||
net/et0/running
|
|
||||||
.It Cm pid
|
|
||||||
PID files based on the service declaration
|
|
||||||
.Cm name:id ,
|
|
||||||
gives the condition pid/name:id
|
|
||||||
.It Cm service
|
|
||||||
Tracks run/task/service state stansitions, including readiness. E.g.,
|
|
||||||
.Cm service/foo/ready
|
|
||||||
can be used as a condition for service
|
|
||||||
.Cm bar ,
|
|
||||||
provided
|
|
||||||
.Cm foo
|
|
||||||
properly signals its readiness to Finit.
|
|
||||||
.It Cm sys
|
|
||||||
System conditions, e.g. sys/key/ctrlaltdel and sys/pwr/fail
|
|
||||||
.It Cm usr
|
|
||||||
User conditions, assert and deassert using
|
|
||||||
.Cm initctl cond [set|clr] foo
|
|
||||||
.El
|
|
||||||
.Sh SIGNALS
|
|
||||||
PID 1 is the only process that by default blocks all signals. Finit
|
|
||||||
allows for the following signals to control operation, but recommends
|
|
||||||
instead using the
|
|
||||||
.Xr initctl 8
|
|
||||||
tool.
|
|
||||||
.Pp
|
|
||||||
.Bl -tag -width TERM
|
|
||||||
.It HUP
|
|
||||||
Tell
|
|
||||||
.Nm
|
|
||||||
to reload its configuration file(s), same as
|
|
||||||
.Cm initctl reload
|
|
||||||
.It USR1
|
|
||||||
Restart API
|
|
||||||
.Cm ( initctl )
|
|
||||||
socket.
|
|
||||||
.It USR2
|
|
||||||
Tell
|
|
||||||
.Nm
|
|
||||||
to perform a system shutdown, same as
|
|
||||||
.Cm initctl poweroff
|
|
||||||
.It TERM
|
|
||||||
Like SIGUSR2 but performs a reboot, same as
|
|
||||||
.Cm initctl reboot
|
|
||||||
.It INT
|
|
||||||
Sent from kernel when Ctrl-Alt-Del is pressed (on the console), this
|
|
||||||
asserts the sys/key/ctrlaltdel condition, which can be used to start
|
|
||||||
tasks or services
|
|
||||||
.It PWR
|
|
||||||
Sent from a a power daemon on changes to UPS status, Finit asserts
|
|
||||||
the sys/pwr/fail condition
|
|
||||||
.El
|
|
||||||
.Sh FILES
|
|
||||||
.Bl -tag -width /etc/finit.d/available/*.conf -compact
|
|
||||||
.It Pa /etc/finit.conf
|
|
||||||
Main configuration file
|
|
||||||
.It Pa /etc/finit.d/*.conf
|
|
||||||
Static service definitions
|
|
||||||
.It Pa /etc/finit.d/available/*.conf
|
|
||||||
Available services
|
|
||||||
.It Pa /etc/finit.d/enabled/*.conf
|
|
||||||
Symlinks from available
|
|
||||||
.It Pa /run/finit/
|
|
||||||
Runtime files, including the condition subsystem
|
|
||||||
.El
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr finit.conf 5
|
|
||||||
.Xr initctl 8
|
|
||||||
.Xr tmpfiles.d 5
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Nm
|
|
||||||
was conceived and reverse engineered by Claudio Matsuoka. Since v1.0,
|
|
||||||
maintained by Joachim Wiberg, with contributions by many others.
|
|
||||||
-1003
File diff suppressed because it is too large
Load Diff
-277
@@ -1,277 +0,0 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
|
||||||
.\" First parameter, NAME, should be all caps
|
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
|
||||||
.Dd June 6, 2021
|
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
|
||||||
.Dt INITCTL 8 SMM
|
|
||||||
.Os Linux
|
|
||||||
.Sh NAME
|
|
||||||
.Nm initctl
|
|
||||||
.Nd Control tool for Finit
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm /sbin/initctl
|
|
||||||
.Op Fl bcfhjlpqtvV
|
|
||||||
.Op COMMAND
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
is the official tool for interacting with
|
|
||||||
.Xr finit 8 .
|
|
||||||
It comes with functions for showing status, querying health of services,
|
|
||||||
as well as editing, enabling and disabling services.
|
|
||||||
.Sh OPTIONS
|
|
||||||
This program follows the usual UNIX command line syntax, with long
|
|
||||||
options starting with two dashes (`-'). The options are as follows:
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Fl b, -batch
|
|
||||||
Batch mode, no screen size probing. Useful for scripting.
|
|
||||||
.It Fl c, -create
|
|
||||||
Create missing paths (and files) as needed. Useful with the
|
|
||||||
.Cm edit
|
|
||||||
command.
|
|
||||||
.It Fl f, -force
|
|
||||||
Ignore missing files and arguments, never prompt.
|
|
||||||
.It Fl h, -help
|
|
||||||
Show built-in help text.
|
|
||||||
.It Fl j, -json
|
|
||||||
JSON output in
|
|
||||||
.Ar status
|
|
||||||
and
|
|
||||||
.Ar cond
|
|
||||||
commands.
|
|
||||||
.It Fl n, -noerr
|
|
||||||
When scripting
|
|
||||||
.Nm
|
|
||||||
to stop, start, restart, or signal a task or service, this option can be
|
|
||||||
used to ignore error 69 (no such task or service) and instead return 0
|
|
||||||
(OK).
|
|
||||||
.It Fl 1, -once
|
|
||||||
Only one lap in commands like top.
|
|
||||||
.It Fl p, -plain
|
|
||||||
Use plain table headings, no ANSI control characters.
|
|
||||||
.It Fl q, -quiet
|
|
||||||
Silent, only return status of command.
|
|
||||||
.It Fl t, -no-heading
|
|
||||||
Skip table headings.
|
|
||||||
.It Fl v, -verbose
|
|
||||||
Verbose output, where applicable.
|
|
||||||
.It Fl V, -version
|
|
||||||
Show program version.
|
|
||||||
.El
|
|
||||||
.Sh COMMANDS
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Nm Ar debug
|
|
||||||
Toggle
|
|
||||||
.Nm finit
|
|
||||||
(daemon) debug to
|
|
||||||
.Pa /dev/console
|
|
||||||
.It Nm Ar help
|
|
||||||
Show built-in help text.
|
|
||||||
.It Nm Ar version
|
|
||||||
Show program version.
|
|
||||||
.It Nm Ar ls | list
|
|
||||||
List all
|
|
||||||
.Cm *.conf
|
|
||||||
files in
|
|
||||||
.Pa /etc/finit.d
|
|
||||||
.It Nm Ar create Ar CONF
|
|
||||||
Create
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available .
|
|
||||||
.Pp
|
|
||||||
Piping the contents into
|
|
||||||
.Nm
|
|
||||||
works as one would expect:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
echo "task name:foo /tmp/foo.sh -- Foo logger" | initctl create foo
|
|
||||||
initctl enable foo
|
|
||||||
initctl reload
|
|
||||||
.Ed
|
|
||||||
.It Nm Ar delete Ar CONF
|
|
||||||
Delete
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available
|
|
||||||
.It Nm Ar show Ar CONF
|
|
||||||
Show
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available
|
|
||||||
.It Nm Ar edit Ar CONF
|
|
||||||
Edit
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available
|
|
||||||
.It Nm Ar touch Ar CONF
|
|
||||||
Change (mark as modified)
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available ,
|
|
||||||
like
|
|
||||||
.Ar edit
|
|
||||||
this tells
|
|
||||||
.Nm finit
|
|
||||||
that a configuration has been changed and is a candidate to be restarted
|
|
||||||
(or SIGHUP'ed) on
|
|
||||||
.Cm initctl reload
|
|
||||||
.It Nm Ar enable Ar CONF
|
|
||||||
Enable
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/available ,
|
|
||||||
i.e., add symlink in
|
|
||||||
.Pa /etc/finit.d/enabled
|
|
||||||
.It Nm Ar disable Ar CONF
|
|
||||||
Disable
|
|
||||||
.Cm .conf
|
|
||||||
in
|
|
||||||
.Pa /etc/finit.d/enabled ,
|
|
||||||
i.e., removes symlink.
|
|
||||||
.It Nm Ar reload
|
|
||||||
Reload
|
|
||||||
.Cm *.conf in
|
|
||||||
.Pa /etc/finit.d ,
|
|
||||||
i.e., activates changes.
|
|
||||||
.It Nm Ar cond set Ar COND Op COND ...
|
|
||||||
Set (assert) user-defined condition,
|
|
||||||
.Cm +usr/COND
|
|
||||||
.It Nm Ar cond get Ar COND
|
|
||||||
Get (quietly) the status of any condition. Defaults to user-defined
|
|
||||||
condions, but if a slash is detected, e.g.,
|
|
||||||
.Cm pid/foo
|
|
||||||
or
|
|
||||||
.Cm net/eth0/exist ,
|
|
||||||
then any condition can be read.
|
|
||||||
.Pp
|
|
||||||
The command is geared for scripting, check the exit code to get the
|
|
||||||
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
|
||||||
verbose output, use the
|
|
||||||
.Fl v
|
|
||||||
option.
|
|
||||||
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
|
||||||
Clear (deassert) user-defined condition,
|
|
||||||
.Cm -usr/COND
|
|
||||||
.It Nm Ar cond status
|
|
||||||
Show condition status, default
|
|
||||||
.Cm cond
|
|
||||||
command. Also supports the
|
|
||||||
.Fl j
|
|
||||||
option for detailed JSON output.
|
|
||||||
.It Nm Ar cond dump Op Cm TYPE
|
|
||||||
Dump all, or a given type of, conditions and their status. Also
|
|
||||||
supports the
|
|
||||||
.Fl j
|
|
||||||
option for detailed JSON output.
|
|
||||||
.It Nm Ar ident Op Cm NAME
|
|
||||||
Display indentities of all run/task/services, or only instances
|
|
||||||
matching
|
|
||||||
.Cm NAME .
|
|
||||||
A partial string, e.g.,
|
|
||||||
.Cm NAM ,
|
|
||||||
will not match anything.
|
|
||||||
.It Nm Ar log Op Cm NAME
|
|
||||||
Show ten last Finit, or
|
|
||||||
.Cm NAME ,
|
|
||||||
messages from syslog.
|
|
||||||
.It Nm Ar start Cm NAME[:ID]
|
|
||||||
Start service by name, with optional ID, e.g.,
|
|
||||||
.Cm initctl start tty:1
|
|
||||||
.It Nm Ar stop Cm NAME[:ID]
|
|
||||||
Stop/Pause a running service by name.
|
|
||||||
.It Nm Ar reload Cm NAME[:ID]
|
|
||||||
Reload service as if its configuration had changed. Internally,
|
|
||||||
.Nm finit
|
|
||||||
marks the named service as "dirty" and turns the state machine,
|
|
||||||
resulting in a SIGHUP or restart of (at least) the named service.
|
|
||||||
Any dependant services are also restarted.
|
|
||||||
.Pp
|
|
||||||
.Sy Note:
|
|
||||||
no .conf file is reloaded with this variant of the command. Essentially
|
|
||||||
it is the same as calling
|
|
||||||
.Cm restart .
|
|
||||||
Except for two things:
|
|
||||||
.Bl -enum -offset indent -compact
|
|
||||||
.It
|
|
||||||
if the service supports HUP, it's signaled instead of stop-started, and
|
|
||||||
.It
|
|
||||||
it allows restarting run/task in the same runlevel -- which is otherwise
|
|
||||||
restricted.
|
|
||||||
.El
|
|
||||||
.It Nm Ar signal Cm NAME:[ID] S
|
|
||||||
Send signal S to service, by name.
|
|
||||||
.Cm S
|
|
||||||
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP).
|
|
||||||
.It Nm Ar restart Cm NAME[:ID]
|
|
||||||
Restart (stop/start) service by name.
|
|
||||||
.It Nm Ar status Cm NAME[:ID]
|
|
||||||
Show service status, by name. If only
|
|
||||||
.Cm NAME
|
|
||||||
is given and multiple instances exits, a summary of all matching
|
|
||||||
instances are shown. Only an exact match displays detailed status
|
|
||||||
for a given instance.
|
|
||||||
.Pp
|
|
||||||
With the
|
|
||||||
.Fl q
|
|
||||||
option this command is silent, provided the
|
|
||||||
.Ar NAME[:ID]
|
|
||||||
selection matches a single run/task/service. The exit code of
|
|
||||||
.Nm
|
|
||||||
is non-zero if there is a problem. Zero is returned if a run/task has
|
|
||||||
run (at least) once in the current runlevel, and when a service is running
|
|
||||||
(as expected). See the
|
|
||||||
.Fl j
|
|
||||||
option for detailed JSON output suitable for machine parsing.
|
|
||||||
.Pp
|
|
||||||
.Sy Tip:
|
|
||||||
.Xr jq 1
|
|
||||||
is a useful scripting tool in combination with JSON output.
|
|
||||||
.It Nm Ar status
|
|
||||||
Show status of all services, default command. Also supports the
|
|
||||||
.Fl j
|
|
||||||
option for detailed JSON output.
|
|
||||||
.It Nm Ar cgroup
|
|
||||||
List cgroup config overview.
|
|
||||||
.It Nm Ar ps
|
|
||||||
List processes based on cgroups.
|
|
||||||
.It Nm Ar top
|
|
||||||
Show top-like listing based on cgroups.
|
|
||||||
.It Nm Ar plugins
|
|
||||||
List installed plugins.
|
|
||||||
.It Nm Ar runlevel Op Ar 0-9
|
|
||||||
Show or set runlevel: 0 halt, 6 reboot.
|
|
||||||
.Pp
|
|
||||||
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
|
||||||
the change, effectively overriding the configured runlevel from
|
|
||||||
.Pa /etc/finit.conf .
|
|
||||||
Useful to trigger a fail-safe mode, or similar.
|
|
||||||
.It Nm Ar reboot
|
|
||||||
Reboot system, default if
|
|
||||||
.Cm reboot
|
|
||||||
is symlinked to
|
|
||||||
.Nm .
|
|
||||||
.It Nm Ar halt
|
|
||||||
Halt system, default if
|
|
||||||
.Cm halt
|
|
||||||
is symlinked to
|
|
||||||
.Nm .
|
|
||||||
.It Nm Ar poweroff
|
|
||||||
Power-off system, default if
|
|
||||||
.Cm poweroff
|
|
||||||
is symlinked to
|
|
||||||
.Nm .
|
|
||||||
.It Nm Ar suspend
|
|
||||||
Suspend system, default if
|
|
||||||
.Cm suspend
|
|
||||||
is symlinked to
|
|
||||||
.Nm .
|
|
||||||
.It Nm Ar utmp show
|
|
||||||
Raw dump of UTMP/WTMP db.
|
|
||||||
.El
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr finit.conf 5
|
|
||||||
.Xr finit 8
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Nm finit
|
|
||||||
was conceived and reverse engineered by Claudio Matsuoka. Since v1.0,
|
|
||||||
maintained by Joachim Wiberg, with contributions by many others.
|
|
||||||
+10
-42
@@ -1,13 +1,13 @@
|
|||||||
pkglibdir = $(plugin_path)
|
pkglibdir = $(plugin_path)
|
||||||
AM_LDFLAGS = -module -avoid-version -shared
|
AM_LDFLAGS = -module -avoid-version -shared
|
||||||
AM_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
AM_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/src
|
AM_CPPFLAGS = -I$(top_srcdir)/src -U_FORTIFY_SOURCE
|
||||||
AM_CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
AM_CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
||||||
AM_CPPFLAGS += -D__FINIT__ $(lite_CFLAGS) $(uev_CFLAGS)
|
AM_CPPFLAGS += $(lite_CFLAGS)
|
||||||
|
|
||||||
if STATIC
|
if STATIC
|
||||||
noinst_LTLIBRARIES = libplug.la
|
noinst_LTLIBRARIES = libplug.la
|
||||||
libplug_la_SOURCES = bootmisc.c pidfile.c procps.c sys.c usr.c
|
libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c pidfile.c procps.c tty.c urandom.c
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
libplug_la_SOURCES += alsa-utils.c
|
libplug_la_SOURCES += alsa-utils.c
|
||||||
@@ -17,12 +17,12 @@ if BUILD_DBUS_PLUGIN
|
|||||||
libplug_la_SOURCES += dbus.c
|
libplug_la_SOURCES += dbus.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_MODULES_LOAD_PLUGIN
|
if BUILD_HOTPLUG_PLUGIN
|
||||||
libplug_la_SOURCES += modules-load.c
|
libplug_la_SOURCES += hotplug.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_MODPROBE_PLUGIN
|
if BUILD_MODULES_LOAD_PLUGIN
|
||||||
libplug_la_SOURCES += modprobe.c
|
libplug_la_SOURCES += modules-load.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_NETLINK_PLUGIN
|
if BUILD_NETLINK_PLUGIN
|
||||||
@@ -33,24 +33,8 @@ if BUILD_RESOLVCONF_PLUGIN
|
|||||||
libplug_la_SOURCES += resolvconf.c
|
libplug_la_SOURCES += resolvconf.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_RTC_PLUGIN
|
|
||||||
libplug_la_SOURCES += rtc.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_TTY_PLUGIN
|
|
||||||
libplug_la_SOURCES += tty.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_URANDOM_PLUGIN
|
|
||||||
libplug_la_SOURCES += urandom.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_X11_COMMON_PLUGIN
|
|
||||||
libplug_la_SOURCES += x11-common.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
else
|
else
|
||||||
pkglib_LTLIBRARIES = bootmisc.la pidfile.la procps.la sys.la usr.la
|
pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la pidfile.la procps.la tty.la urandom.la
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
pkglib_LTLIBRARIES += alsa-utils.la
|
pkglib_LTLIBRARIES += alsa-utils.la
|
||||||
@@ -60,18 +44,14 @@ if BUILD_DBUS_PLUGIN
|
|||||||
pkglib_LTLIBRARIES += dbus.la
|
pkglib_LTLIBRARIES += dbus.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_HOOK_SCRIPTS_PLUGIN
|
if BUILD_HOTPLUG_PLUGIN
|
||||||
pkglib_LTLIBRARIES += hook-scripts.la
|
pkglib_LTLIBRARIES += hotplug.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_MODULES_LOAD_PLUGIN
|
if BUILD_MODULES_LOAD_PLUGIN
|
||||||
pkglib_LTLIBRARIES += modules-load.la
|
pkglib_LTLIBRARIES += modules-load.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_MODPROBE_PLUGIN
|
|
||||||
pkglib_LTLIBRARIES += modprobe.la
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_NETLINK_PLUGIN
|
if BUILD_NETLINK_PLUGIN
|
||||||
pkglib_LTLIBRARIES += netlink.la
|
pkglib_LTLIBRARIES += netlink.la
|
||||||
endif
|
endif
|
||||||
@@ -80,18 +60,6 @@ if BUILD_RESOLVCONF_PLUGIN
|
|||||||
pkglib_LTLIBRARIES += resolvconf.la
|
pkglib_LTLIBRARIES += resolvconf.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_RTC_PLUGIN
|
|
||||||
pkglib_LTLIBRARIES += rtc.la
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_TTY_PLUGIN
|
|
||||||
pkglib_LTLIBRARIES += tty.la
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_URANDOM_PLUGIN
|
|
||||||
pkglib_LTLIBRARIES += urandom.la
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_X11_COMMON_PLUGIN
|
if BUILD_X11_COMMON_PLUGIN
|
||||||
pkglib_LTLIBRARIES += x11-common.la
|
pkglib_LTLIBRARIES += x11-common.la
|
||||||
endif
|
endif
|
||||||
|
|||||||
+6
-21
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore ALSA sound settings using alsactl
|
/* Save and restore ALSA sound settings using alsactl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2021 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
|
||||||
@@ -21,12 +21,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
@@ -35,26 +30,16 @@
|
|||||||
|
|
||||||
static void save(void *arg)
|
static void save(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whichp(ALSACTL)) {
|
if (whichp(ALSACTL)) {
|
||||||
dbg("Saving sound settings ...");
|
_d("Saving sound settings ...");
|
||||||
run_interactive(ALSACTL " -g store", "Saving sound settings");
|
run_interactive(ALSACTL " -g store", "Saving sound settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore(void *arg)
|
static void restore(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whichp(ALSACTL)) {
|
if (whichp(ALSACTL)) {
|
||||||
dbg("Restoring sound settings ...");
|
_d("Restoring sound settings ...");
|
||||||
run_interactive(ALSACTL " -g restore", "Restoring sound settings");
|
run_interactive(ALSACTL " -g restore", "Restoring sound settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,12 +50,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+99
-75
@@ -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-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2021 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
|
||||||
@@ -21,18 +21,10 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h" /* Generated by configure script */
|
|
||||||
|
|
||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
#ifdef HAVE_MNTENT_H
|
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#endif
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
@@ -43,12 +35,10 @@
|
|||||||
|
|
||||||
static int is_tmpfs(char *path)
|
static int is_tmpfs(char *path)
|
||||||
{
|
{
|
||||||
struct mntent mount;
|
|
||||||
struct mntent *mnt;
|
|
||||||
char buf[256];
|
|
||||||
int tmpfs = 0;
|
int tmpfs = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
struct mntent *mnt;
|
||||||
|
|
||||||
/* If path is a symlink, check what it resolves to */
|
/* If path is a symlink, check what it resolves to */
|
||||||
dir = realpath(path, NULL);
|
dir = realpath(path, NULL);
|
||||||
@@ -61,7 +51,7 @@ static int is_tmpfs(char *path)
|
|||||||
return 0; /* Dunno, maybe not */
|
return 0; /* Dunno, maybe not */
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((mnt = getmntent_r(fp, &mount, buf, sizeof(buf)))) {
|
while ((mnt = getmntent(fp))) {
|
||||||
if (!strcmp(dir, mnt->mnt_dir))
|
if (!strcmp(dir, mnt->mnt_dir))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -75,25 +65,19 @@ static int is_tmpfs(char *path)
|
|||||||
return tmpfs;
|
return tmpfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bootclean(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
static int do_clean(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
||||||
{
|
{
|
||||||
if (ftw->level == 0)
|
if (ftw->level == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
dbg("Removing %s ...", fpath);
|
_d("Removing %s ...", fpath);
|
||||||
(void)remove(fpath);
|
(void)remove(fpath);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* We can safely skip tmpfs, nothing to clean from previous boot there */
|
||||||
* Cleanup stale files from previous boot, if any still linger on.
|
static void bootclean(void)
|
||||||
* Some systems, e.g. Alpine Linux, still have a persistent /run and
|
|
||||||
* /tmp, i.e. not tmpfs.
|
|
||||||
*
|
|
||||||
* We can safely skip tmpfs, nothing to clean there.
|
|
||||||
*/
|
|
||||||
static void clean(void *arg)
|
|
||||||
{
|
{
|
||||||
char *dir[] = {
|
char *dir[] = {
|
||||||
"/tmp/",
|
"/tmp/",
|
||||||
@@ -106,46 +90,7 @@ static void clean(void *arg)
|
|||||||
if (is_tmpfs(dir[i]))
|
if (is_tmpfs(dir[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nftw(dir[i], bootclean, 20, FTW_DEPTH);
|
nftw(dir[i], do_clean, 20, FTW_DEPTH);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kernel defines the following compulsory and recommended links
|
|
||||||
* https://github.com/torvalds/linux/blob/v5.18/Documentation/admin-guide/devices.rst#compulsory-links
|
|
||||||
*/
|
|
||||||
static void kernel_links(void)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
char *tgt, *lnk;
|
|
||||||
int optional;
|
|
||||||
} k[] = {
|
|
||||||
{ "/proc/self/fd", "/dev/fd", 0 },
|
|
||||||
{ "fd/0", "/dev/stdin", 0 },
|
|
||||||
{ "fd/1", "/dev/stdout", 0 },
|
|
||||||
{ "fd/2", "/dev/stderr", 0 },
|
|
||||||
{ "socksys", "/dev/nfsd", 0 },
|
|
||||||
{ "null", "/dev/X0R", 0 },
|
|
||||||
{ "/proc/kcore", "/dev/core", 1 },
|
|
||||||
{ "ram0", "/dev/ramdisk", 1 },
|
|
||||||
{ "qft0", "/dev/ftape", 1 },
|
|
||||||
{ "video0", "/dev/bttv0", 1 },
|
|
||||||
{ "radio0", "/dev/radio", 1 },
|
|
||||||
};
|
|
||||||
char *fn, buf[80];
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < NELEMS(k); i++) {
|
|
||||||
fn = k[i].tgt;
|
|
||||||
|
|
||||||
if (k[i].optional) {
|
|
||||||
if (fn[0] != '/') {
|
|
||||||
snprintf(buf, sizeof(buf), "/dev/%s", k[i].tgt);
|
|
||||||
fn = buf;
|
|
||||||
}
|
|
||||||
if (!fexist(fn))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ln(k[i].tgt, k[i].lnk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,35 +99,114 @@ static void kernel_links(void)
|
|||||||
*/
|
*/
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
mode_t prev;
|
int uid, gid;
|
||||||
|
|
||||||
prev = umask(0);
|
/* Cleanup stale files, if any still linger on. */
|
||||||
|
bootclean();
|
||||||
|
|
||||||
/* Kernel symlinks, e.g. /proc/self/fd -> /dev/fd */
|
_d("Setting up FHS structure in /var ...");
|
||||||
kernel_links();
|
umask(0);
|
||||||
|
makedir("/var/cache", 0755);
|
||||||
|
makedir("/var/db", 0755); /* _PATH_VARDB on some systems */
|
||||||
|
makedir("/var/games", 0755);
|
||||||
|
makedir("/var/lib", 0755);
|
||||||
|
makedir("/var/lib/misc", 0755); /* _PATH_VARDB on some systems */
|
||||||
|
makedir("/var/lib/alarm", 0755);
|
||||||
|
makedir("/var/lib/urandom",0755);
|
||||||
|
if (fisdir("/run")) {
|
||||||
|
_d("System with new /run tmpfs ...");
|
||||||
|
makedir("/run/lock", 1777);
|
||||||
|
symlink("/run/lock", "/var/lock");
|
||||||
|
symlink("/dev/shm", "/run/shm");
|
||||||
|
|
||||||
/* Create all system tmpfiles.d(5) */
|
/* compat only, should really be set up by OS/dist */
|
||||||
run_interactive(_PATH_TMPFILES " --create", "Creating required directories and files");
|
symlink("/run", "/var/run");
|
||||||
|
} else {
|
||||||
|
makedir("/var/lock", 1777);
|
||||||
|
makedir("/var/run", 0755);
|
||||||
|
}
|
||||||
|
makedir("/var/log", 0755);
|
||||||
|
makedir("/var/mail", 0755);
|
||||||
|
makedir("/var/opt", 0755);
|
||||||
|
makedir("/var/spool", 0755);
|
||||||
|
makedir("/var/spool/cron", 0755);
|
||||||
|
makedir("/var/tmp", 0755);
|
||||||
|
makedir("/var/empty", 0755);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If /etc/group or "utmp" group is missing,
|
||||||
|
* default to "root"/"wheel" group
|
||||||
|
*/
|
||||||
|
_d("Setting up necessary UTMP files ...");
|
||||||
|
gid = getgroup("utmp");
|
||||||
|
if (gid < 0)
|
||||||
|
gid = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UTMP actually needs multiple db files
|
||||||
|
*/
|
||||||
|
if (has_utmp()) {
|
||||||
|
create("/var/run/utmp", 0644, 0, gid); /* Currently logged in */
|
||||||
|
create("/var/log/wtmp", 0644, 0, gid); /* Login history */
|
||||||
|
create("/var/log/btmp", 0600, 0, gid); /* Failed logins */
|
||||||
|
create("/var/log/lastlog", 0644, 0, gid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set BOOT_TIME UTMP entry */
|
/* Set BOOT_TIME UTMP entry */
|
||||||
utmp_set_boot();
|
utmp_set_boot();
|
||||||
|
|
||||||
umask(prev);
|
#ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE
|
||||||
|
touch("/etc/network/run/ifstate");
|
||||||
|
#else
|
||||||
|
erase("/etc/network/run/ifstate");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_d("Setting up misc files ...");
|
||||||
|
makedir("/var/run/network",0755); /* Needed by Debian/Ubuntu ifupdown */
|
||||||
|
makedir("/var/run/lldpd", 0755); /* Needed by lldpd */
|
||||||
|
makedir("/var/run/pluto", 0755); /* Needed by Openswan */
|
||||||
|
makedir("/var/run/quagga", 0755); /* Needed by Quagga */
|
||||||
|
makedir("/var/log/quagga", 0755); /* Needed by Quagga */
|
||||||
|
makedir("/var/run/frr", 0755); /* Needed by FRR */
|
||||||
|
makedir("/var/log/frr", 0755); /* Needed by FRR */
|
||||||
|
makedir("/var/run/sshd", 01755); /* OpenSSH */
|
||||||
|
|
||||||
|
gid = getgroup("tty");
|
||||||
|
if (gid < 0)
|
||||||
|
gid = 0;
|
||||||
|
makefifo("/dev/xconsole", 0640); /* sysklogd */
|
||||||
|
chown("/dev/xconsole", 0, gid);
|
||||||
|
|
||||||
|
if (!fexist("/etc/mtab"))
|
||||||
|
symlink("../proc/self/mounts", "/etc/mtab");
|
||||||
|
|
||||||
|
/* Void Linux has a uuidd that runs as uuid:uuid and needs /run/uuid */
|
||||||
|
uid = getuser("uuidd", NULL);
|
||||||
|
if (uid >= 0) {
|
||||||
|
gid = getgroup("uuidd");
|
||||||
|
if (gid < 0)
|
||||||
|
gid = 0;
|
||||||
|
makedir("/var/run/uuidd", 0755);
|
||||||
|
chown("/var/run/uuidd", uid, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
umask(022);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_MOUNT_POST] = { .cb = clean },
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = setup },
|
.cb = setup
|
||||||
|
},
|
||||||
.depends = { "pidfile" },
|
.depends = { "pidfile" },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-120
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and start system message bus, D-Bus
|
/* Setup and start system message bus, D-Bus
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2021 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,11 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -35,143 +31,55 @@
|
|||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#define DBUS_DAEMON "dbus-daemon"
|
#define DAEMON "dbus-daemon"
|
||||||
#define DBUS_ARGS "--nofork --system --syslog-only"
|
#define ARGS "--nofork --system"
|
||||||
#define DBUS_DESC "D-Bus message bus daemon"
|
#define DESC "D-Bus message bus daemon"
|
||||||
|
|
||||||
#ifndef DBUS_DAEMONUSER
|
|
||||||
#define DBUS_DAEMONUSER "messagebus"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DBUS_DAEMONGROUP
|
|
||||||
#define DBUS_DAEMONGROUP "messagebus"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dumnpster diving for the D-Bus main configuration file
|
|
||||||
* where <pidfile> is defined.
|
|
||||||
*/
|
|
||||||
static char *dbus_pidfn(void)
|
|
||||||
{
|
|
||||||
char *alt[] = {
|
|
||||||
"/usr/share/dbus-1/system.conf",
|
|
||||||
"/etc/dbus-1/system.conf",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; alt[i]; i++) {
|
|
||||||
char *fn = alt[i];
|
|
||||||
char buf[256];
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
fp = fopen(fn, "r");
|
|
||||||
if (!fp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fn = NULL;
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
|
||||||
char *pos;
|
|
||||||
|
|
||||||
pos = strstr(buf, "<pidfile>");
|
|
||||||
if (!pos)
|
|
||||||
continue;
|
|
||||||
fn = pos + strlen("<pidfile>");
|
|
||||||
pos = strstr(fn, "</pidfile>");
|
|
||||||
if (!pos) {
|
|
||||||
fn = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*pos = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
if (fn)
|
|
||||||
return strdup(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
char *group = DBUS_DAEMONGROUP;
|
|
||||||
char *user = DBUS_DAEMONUSER;
|
|
||||||
char line[256];
|
|
||||||
char *pidfn;
|
|
||||||
mode_t prev;
|
|
||||||
char *cmd;
|
char *cmd;
|
||||||
|
char line[256];
|
||||||
|
|
||||||
if (rescue) {
|
cmd = which(DAEMON);
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = which(DBUS_DAEMON);
|
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
dbg("Skipping plugin, %s is not installed.", DBUS_DAEMON);
|
_d("Skipping plugin, %s is not installed.", DAEMON);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getuser(user, NULL) == -1) {
|
umask(0);
|
||||||
if (getuser("dbus", NULL) == -1)
|
|
||||||
user = "root"; /* fallback */
|
|
||||||
else
|
|
||||||
user = "dbus"; /* e.g., Buildroot */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getgroup(group) == -1) {
|
makedir("/var/run/dbus", 0755);
|
||||||
if (getgroup("dbus") == -1)
|
makedir("/var/lock/subsys", 0755);
|
||||||
group = "root"; /* fallback */
|
makedir("/var/lock/subsys/messagebus", 0755);
|
||||||
else
|
if (whichp("dbus-uuidgen"))
|
||||||
group = "dbus"; /* e.g., Buildroot */
|
run("dbus-uuidgen --ensure");
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up from any previous pre-bootstrap run */
|
/* Clean up from any previous pre-bootstrap run */
|
||||||
pidfn = dbus_pidfn();
|
erase("/var/run/dbus/pid");
|
||||||
if (pidfn)
|
|
||||||
remove(pidfn);
|
|
||||||
|
|
||||||
dbg("Creating D-Bus Required Directories ...");
|
/* Register service with Finit */
|
||||||
prev = umask(0);
|
snprintf(line, sizeof(line), "[S12345] pid:!/run/dbus/pid log:prio:daemon.info,tag:dbus %s %s -- %s", cmd, ARGS, DESC);
|
||||||
mksubsys("/var/run/dbus", 0755, user, group);
|
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
||||||
mksubsys("/var/run/lock/subsys", 0755, user, group);
|
_pe("Failed registering %s", DAEMON);
|
||||||
mksubsys("/var/lib/dbus", 0755, user, group);
|
|
||||||
mksubsys("/tmp/dbus", 0755, user, group);
|
|
||||||
umask(prev);
|
|
||||||
|
|
||||||
/* Generate machine id for dbus */
|
|
||||||
if (whichp("dbus-uuidgen"))
|
|
||||||
run_interactive("dbus-uuidgen --ensure", "Verifying D-Bus machine UUID");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register service with Finit
|
|
||||||
* Note: dbus drops privs after starting up.
|
|
||||||
*/
|
|
||||||
if (pidfn) {
|
|
||||||
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus pid:!%s %s %s -- %s",
|
|
||||||
pidfn, cmd, DBUS_ARGS, DBUS_DESC);
|
|
||||||
free(pidfn);
|
|
||||||
} else
|
|
||||||
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus %s %s -- %s",
|
|
||||||
cmd, DBUS_ARGS, DBUS_DESC);
|
|
||||||
|
|
||||||
conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf");
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
||||||
|
umask(022);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
.hook[HOOK_NETWORK_UP] = {
|
||||||
|
.cb = setup
|
||||||
|
},
|
||||||
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
/* Trigger scripts to run from finit's hooks
|
|
||||||
*
|
|
||||||
* Copyright (c) 2022 Tobias Waldekranz <tobias@waldekranz.com>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "finit.h"
|
|
||||||
#include "helpers.h"
|
|
||||||
#include "plugin.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
extern void plugin_script_run(hook_point_t no);
|
|
||||||
|
|
||||||
static void hscript_run_parts(hook_point_t no)
|
|
||||||
{
|
|
||||||
plugin_script_run(no);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_banner(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_BANNER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_rootfs_up(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_ROOTFS_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_mount_error(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_MOUNT_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_mount_post(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_MOUNT_POST);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_basefs_up(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_BASEFS_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_network_up(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_NETWORK_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_svc_up(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_SVC_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_system_up(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_SYSTEM_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hscript_shutdown(void *arg)
|
|
||||||
{
|
|
||||||
hscript_run_parts(HOOK_SHUTDOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
|
||||||
.name = __FILE__,
|
|
||||||
.hook[HOOK_BANNER] = { .cb = hscript_banner },
|
|
||||||
.hook[HOOK_ROOTFS_UP] = { .cb = hscript_rootfs_up },
|
|
||||||
.hook[HOOK_MOUNT_ERROR] = { .cb = hscript_mount_error },
|
|
||||||
.hook[HOOK_MOUNT_POST] = { .cb = hscript_mount_post },
|
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = hscript_basefs_up },
|
|
||||||
.hook[HOOK_NETWORK_UP] = { .cb = hscript_network_up },
|
|
||||||
.hook[HOOK_SVC_UP] = { .cb = hscript_svc_up },
|
|
||||||
.hook[HOOK_SYSTEM_UP] = { .cb = hscript_system_up },
|
|
||||||
.hook[HOOK_SHUTDOWN] = { .cb = hscript_shutdown },
|
|
||||||
/*
|
|
||||||
* We have exited here, so these are handled a bit differently by Finit,
|
|
||||||
* when hook scripts are enabled, just to provide the user with the same
|
|
||||||
* interface:
|
|
||||||
*
|
|
||||||
* .hook[HOOK_SVC_DN] = { .cb = hscript_svc_down },
|
|
||||||
* .hook[HOOK_SYS_DN] = { .cb = hscript_system_down },
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
|
||||||
{
|
|
||||||
plugin_register(&plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
|
||||||
{
|
|
||||||
plugin_unregister(&plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Local Variables:
|
|
||||||
* indent-tabs-mode: t
|
|
||||||
* c-file-style: "linux"
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/* Heuristically find and initialize a suitable hotplug daemon
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "finit.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "service.h"
|
||||||
|
|
||||||
|
static void setup(void *arg)
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Populate /dev and prepare for runtime events from kernel.
|
||||||
|
* Prefer udev if mdev is also available on the system.
|
||||||
|
*/
|
||||||
|
path = which("udevd");
|
||||||
|
if (!path)
|
||||||
|
path = which("/lib/systemd/systemd-udevd");
|
||||||
|
if (path) {
|
||||||
|
/* Register udevd as a monitored service */
|
||||||
|
snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd name:udevd log %s "
|
||||||
|
"-- Device event managing daemon", path);
|
||||||
|
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
|
||||||
|
_pe("Failed registering %s", path);
|
||||||
|
} else {
|
||||||
|
snprintf(cmd, sizeof(cmd), ":1 [S] <pid/udevd> log "
|
||||||
|
"udevadm trigger -c add -t devices "
|
||||||
|
"-- Requesting device events");
|
||||||
|
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd), ":2 [S] <pid/udevd> log "
|
||||||
|
"udevadm trigger -c add -t subsystems "
|
||||||
|
"-- Requesting subsystem events");
|
||||||
|
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
/* Debian has this little script to copy generated
|
||||||
|
* rules while the system was read-only. TODO: When
|
||||||
|
* this functionality was hardcoded in finit.c, this
|
||||||
|
* call was made in crank_worker(). Now that
|
||||||
|
* filesystems are mounted earlier we should be able
|
||||||
|
* to make this call directly after the triggers have
|
||||||
|
* run, but this has not been tested AT ALL. */
|
||||||
|
if (fexist("/lib/udev/udev-finish"))
|
||||||
|
run_interactive("/lib/udev/udev-finish", "Finalizing udev");
|
||||||
|
} else {
|
||||||
|
path = which("mdev");
|
||||||
|
if (path) {
|
||||||
|
/* Embedded Linux systems usually have BusyBox mdev */
|
||||||
|
if (debug)
|
||||||
|
touch("/dev/mdev.log");
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd), "%s -s", path);
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
run_interactive(cmd, "Populating device tree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = __FILE__,
|
||||||
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
|
.cb = setup
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_INIT(plugin_init)
|
||||||
|
{
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_EXIT(plugin_exit)
|
||||||
|
{
|
||||||
|
plugin_unregister(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
+17
-80
@@ -1,6 +1,6 @@
|
|||||||
/* Coldplug modules using modalias magic
|
/* Coldplug modules using modalias magic
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021 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
|
||||||
@@ -40,15 +40,11 @@
|
|||||||
#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>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "util.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
struct module {
|
struct module {
|
||||||
@@ -71,14 +67,14 @@ static int modprobe(char *alias)
|
|||||||
pid = fork();
|
pid = fork();
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
case -1:
|
case -1:
|
||||||
err(1, "Failed forking modprobe child");
|
_pe("Failed forking modprobe child");
|
||||||
return 1;
|
return 1;
|
||||||
case 0:
|
case 0:
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!complete(args[0], pid))
|
if (!complete(args[0], pid))
|
||||||
dbg("Successful modprobe of %s", alias);
|
_d("Successful modprobe of %s", alias);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +102,7 @@ static void alias_remove(struct module *m)
|
|||||||
TAILQ_REMOVE(&modules, m, link);
|
TAILQ_REMOVE(&modules, m, link);
|
||||||
free(m->alias);
|
free(m->alias);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alias_exist(char *alias)
|
static int alias_exist(char *alias)
|
||||||
{
|
{
|
||||||
@@ -120,86 +116,27 @@ static int alias_exist(char *alias)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alias_add_uniq(char *alias)
|
static int scan_alias(const char *path, const struct stat *st, int flag, struct FTW *unused)
|
||||||
{
|
{
|
||||||
if (alias_exist(alias))
|
|
||||||
return;
|
|
||||||
|
|
||||||
alias_add(alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FILE *maybe_fopen_alias(const char *file, const char *path)
|
|
||||||
{
|
|
||||||
const char *basename;
|
|
||||||
|
|
||||||
basename = basenm(path);
|
|
||||||
if (!strcmp(basename, path))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strcmp(file, basename))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return fopen(path, "r");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int scan_modalias(const char *path)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
fp = maybe_fopen_alias("modalias", path);
|
if (fnmatch("*/modalias", path, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fp = fopen(path, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return 1;
|
return 0;
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), fp)) {
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
chomp(buf);
|
chomp(buf);
|
||||||
alias_add_uniq(buf);
|
if (!alias_exist(buf))
|
||||||
|
alias_add(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int scan_uevent(const char *path)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
fp = maybe_fopen_alias("uevent", path);
|
|
||||||
if (!fp)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
|
||||||
if (strstr(buf, "MODALIAS=") != buf)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
chomp(buf);
|
|
||||||
|
|
||||||
alias_add_uniq(buf + strlen("MODALIAS="));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int scan_alias(const char *path, const struct stat *st,
|
|
||||||
int flag, struct FTW *unused)
|
|
||||||
{
|
|
||||||
/* Sanity check: is this a regular file we can read? */
|
|
||||||
if (!(S_ISREG(st->st_mode) && (st->st_mode & S_IRUSR)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!scan_uevent(path))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
scan_modalias(path);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coldplug(void *arg)
|
static void coldplug(void *arg)
|
||||||
{
|
{
|
||||||
struct module *m, *tmp;
|
struct module *m, *tmp;
|
||||||
@@ -232,12 +169,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", }
|
.depends = { "bootmisc", }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-171
@@ -21,37 +21,10 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#include <lite/lite.h>
|
||||||
* This plugin scans files in /etc/modules-load.d/, for each line in the
|
|
||||||
* file it assumes the name of a kernel module, with optional arguments.
|
|
||||||
* Each module is loaded when entering runlevel 2, 3, 4, or 5, using the
|
|
||||||
* modprobe tool.
|
|
||||||
*
|
|
||||||
* Loading is done by inserting a `task` stanza in Finit, ensuring all
|
|
||||||
* modules are loaded in parallel, with other modules and programs.
|
|
||||||
* Each `task` stanza is by default given the name:modprobe.module and
|
|
||||||
* indexed with `:ID`, starting with 1.
|
|
||||||
*
|
|
||||||
* Indexing can be disabled per file in /etc/modules-load.d/, anywwhere
|
|
||||||
* in a file, by putting the keyword `noindex` on a line of its own. A
|
|
||||||
* noindex command can appear anywhere in the file, and up to the point
|
|
||||||
* it is read, tasks will be indexed with an incrementing `:ID`. When
|
|
||||||
* `noindex` is read indexing is disabled and all subseequent tasks will
|
|
||||||
* not have any `:ID` at all.
|
|
||||||
*
|
|
||||||
* Please note, the :ID is there for your benefit, it ensures that tasks
|
|
||||||
* in Finit are unique. If you have two tasks with the same name and ID
|
|
||||||
* (or no ID), the last one read replaces any preceding one!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#ifdef _LIBITE_LITE
|
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -62,166 +35,68 @@
|
|||||||
#ifndef MODULES_LOAD_PATH
|
#ifndef MODULES_LOAD_PATH
|
||||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||||
#endif
|
#endif
|
||||||
#define MODPROBE_PATH "/sbin/modprobe"
|
|
||||||
#define SERVICE_LINE \
|
#define SERVICE_LINE \
|
||||||
"cgroup.init name:modprobe.%s :%d [%s] %s %s %s --"
|
":%d name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s"
|
||||||
#define SERVICE_LINE_NOINDEX \
|
|
||||||
"cgroup.init name:modprobe.%s [%s] %s %s %s --"
|
|
||||||
|
|
||||||
static int modules_load(const char *file, int index)
|
|
||||||
{
|
|
||||||
char module_path[PATH_MAX];
|
|
||||||
char *modprobe_path;
|
|
||||||
int num = 0;
|
|
||||||
char *line;
|
|
||||||
char *lvl;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
|
|
||||||
strlcat(module_path, file, sizeof(module_path));
|
|
||||||
|
|
||||||
fp = fopen(module_path, "r");
|
|
||||||
if (!fp) {
|
|
||||||
warnx("failed opening %s for reading, skipping ...", module_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
modprobe_path = strdup(MODPROBE_PATH);
|
|
||||||
if (!modprobe_path) {
|
|
||||||
fail:
|
|
||||||
warnx("failed allocating memory in modules-load plugin.");
|
|
||||||
fclose(fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lvl = strdup("S");
|
|
||||||
if (!lvl) {
|
|
||||||
free(modprobe_path);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((line = fparseln(fp, NULL, NULL, NULL, 0))) {
|
|
||||||
char cmd[CMD_SIZE], *mod, *args, *set;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* fparseln() skips regular UNIX comments only.
|
|
||||||
* This is for modules-load.d(5) compat.
|
|
||||||
*/
|
|
||||||
if (line[0] == ';')
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
/* trim whitespace */
|
|
||||||
mod = strip_line(line);
|
|
||||||
if (!mod[0])
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
/* Finit extension 'set foo bar' */
|
|
||||||
if ((set = fgetval(mod, "set", "= \t"))) {
|
|
||||||
char *val = mod;
|
|
||||||
|
|
||||||
if (!strcmp(set, "noindex")) {
|
|
||||||
index = 0;
|
|
||||||
free(set);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((val = fgetval(set, "index", "= \t"))) {
|
|
||||||
index = atoi(val);
|
|
||||||
free(set);
|
|
||||||
free(val);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((val = fgetval(set, "runlevel", "= \t"))) {
|
|
||||||
free(lvl);
|
|
||||||
lvl = val;
|
|
||||||
free(set);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((val = fgetval(set, "modprobe", "= \t"))) {
|
|
||||||
if (access(val, X_OK)) {
|
|
||||||
warn("%s: cannot use %s", module_path, val);
|
|
||||||
free(set);
|
|
||||||
free(val);
|
|
||||||
free(line);
|
|
||||||
goto skip;
|
|
||||||
} else {
|
|
||||||
free(modprobe_path);
|
|
||||||
modprobe_path = val;
|
|
||||||
}
|
|
||||||
free(set);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unknown 'set' command, ignore. */
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod = strtok_r(mod, " ", &args);
|
|
||||||
if (!mod)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
if (!index)
|
|
||||||
snprintf(cmd, sizeof(cmd), SERVICE_LINE_NOINDEX, mod, lvl, modprobe_path, mod, args);
|
|
||||||
else
|
|
||||||
snprintf(cmd, sizeof(cmd), SERVICE_LINE, mod, index++, lvl, modprobe_path, mod, args);
|
|
||||||
|
|
||||||
dbg("task %s", cmd);
|
|
||||||
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
|
||||||
num++;
|
|
||||||
next:
|
|
||||||
free(line);
|
|
||||||
}
|
|
||||||
skip:
|
|
||||||
free(modprobe_path);
|
|
||||||
free(lvl);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: check here for .conf only? */
|
|
||||||
static int module_filter(const struct dirent *d)
|
|
||||||
{
|
|
||||||
if (d->d_type == DT_DIR)
|
|
||||||
return 0;
|
|
||||||
if (d->d_name[0] == '.')
|
|
||||||
return 0; /* skip dot files */
|
|
||||||
if (d->d_name[strlen(d->d_name) - 1] == '~')
|
|
||||||
return 0; /* skip backup files */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load(void *arg)
|
static void load(void *arg)
|
||||||
{
|
{
|
||||||
struct dirent **dentry;
|
FILE *fp;
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *direntp;
|
||||||
|
char line[256];
|
||||||
int index = 1;
|
int index = 1;
|
||||||
int i, num;
|
|
||||||
|
|
||||||
dbg("Scanning " MODULES_LOAD_PATH " for config files ...");
|
_d("Scanning " MODULES_LOAD_PATH " for config files ...");
|
||||||
num = scandir(MODULES_LOAD_PATH, &dentry, module_filter, alphasort);
|
|
||||||
if (num > 0) {
|
dirp = opendir(MODULES_LOAD_PATH);
|
||||||
for (i = 0; i < num; i++) {
|
if (!dirp) return;
|
||||||
index += modules_load(dentry[i]->d_name, index);
|
|
||||||
free(dentry[i]);
|
while ((direntp = readdir(dirp)))
|
||||||
|
{
|
||||||
|
char module_path[PATH_MAX];
|
||||||
|
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
|
||||||
|
strlcat(module_path, direntp->d_name, sizeof(module_path));
|
||||||
|
|
||||||
|
fp = fopen(module_path, "r");
|
||||||
|
if (!fp) continue;
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), fp)) {
|
||||||
|
char cmd[CMD_SIZE], *mod, *args;
|
||||||
|
|
||||||
|
mod = strip_line(line);
|
||||||
|
if (!*mod) continue;
|
||||||
|
|
||||||
|
mod = chomp(mod);
|
||||||
|
if (!mod || !*mod) continue;
|
||||||
|
|
||||||
|
mod = strtok_r(mod, " ", &args);
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd), SERVICE_LINE,
|
||||||
|
index, mod, mod, args, mod);
|
||||||
|
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
||||||
|
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
free(dentry);
|
|
||||||
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
|
.cb = load
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+82
-306
@@ -1,8 +1,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-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (C) 2009-2021 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
|
||||||
@@ -18,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net/if.h> /* IFNAMSIZ */
|
#include <net/if.h> /* IFNAMSIZ */
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -29,90 +27,70 @@
|
|||||||
|
|
||||||
#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"
|
|
||||||
|
|
||||||
#define NL_BUFSZ 4096
|
static int nlmsg_validate(struct nlmsghdr *nh, size_t len)
|
||||||
|
{
|
||||||
|
if (!NLMSG_OK(nh, len))
|
||||||
|
return 1;
|
||||||
|
|
||||||
struct nl_request {
|
if (nh->nlmsg_type == NLMSG_DONE) {
|
||||||
struct nlmsghdr nh;
|
_d("Done with netlink messages.");
|
||||||
union {
|
return 1;
|
||||||
struct rtmsg rtm;
|
}
|
||||||
struct ifinfomsg ifi;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
static int nl_defidx;
|
if (nh->nlmsg_type == NLMSG_ERROR) {
|
||||||
static int nl_ifdown;
|
_d("Netlink reports error.");
|
||||||
static char *nl_buf;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
static void nl_route(struct nlmsghdr *nlmsg)
|
||||||
{
|
{
|
||||||
char daddr[INET_ADDRSTRLEN];
|
|
||||||
char gaddr[INET_ADDRSTRLEN];
|
|
||||||
struct in_addr ind, ing;
|
|
||||||
struct rtmsg *r;
|
struct rtmsg *r;
|
||||||
struct rtattr *a;
|
struct rtattr *a;
|
||||||
int plen = 0;
|
|
||||||
int dst = 0;
|
|
||||||
int idx = 0;
|
|
||||||
int gw = 0;
|
|
||||||
int la;
|
int la;
|
||||||
|
int gw = 0, dst = 0, mask = 0, idx = 0;
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
||||||
errx(1, "Packet too small or truncated!");
|
_e("Packet too small or truncated!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = NLMSG_DATA(nlmsg);
|
r = NLMSG_DATA(nlmsg);
|
||||||
a = RTM_RTA(r);
|
a = RTM_RTA(r);
|
||||||
la = RTM_PAYLOAD(nlmsg);
|
la = RTM_PAYLOAD(nlmsg);
|
||||||
if (la >= len) {
|
|
||||||
errx(1, "Packet too large!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (RTA_OK(a, la)) {
|
while (RTA_OK(a, la)) {
|
||||||
void *data = RTA_DATA(a);
|
void *data = RTA_DATA(a);
|
||||||
|
|
||||||
switch (a->rta_type) {
|
switch (a->rta_type) {
|
||||||
case RTA_GATEWAY:
|
case RTA_GATEWAY:
|
||||||
gw = *((int *)data);
|
gw = *((int *)data);
|
||||||
//dbg("GW: 0x%04x", gw);
|
//_d("GW: 0x%04x", gw);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTA_DST:
|
case RTA_DST:
|
||||||
dst = *((int *)data);
|
dst = *((int *)data);
|
||||||
plen = r->rtm_dst_len;
|
mask = r->rtm_dst_len;
|
||||||
//dbg("Prefix LEN: 0x%04x", plen);
|
//_d("MASK: 0x%04x", mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTA_OIF:
|
case RTA_OIF:
|
||||||
idx = *((int *)data);
|
idx = *((int *)data);
|
||||||
//dbg("IDX: 0x%04x", idx);
|
//_d("IDX: 0x%04x", idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = RTA_NEXT(a, la);
|
a = RTA_NEXT(a, la);
|
||||||
}
|
}
|
||||||
|
|
||||||
ind.s_addr = dst;
|
if ((!dst && !mask) && (gw || idx)) {
|
||||||
ing.s_addr = gw;
|
if (nlmsg->nlmsg_type == RTM_DELROUTE)
|
||||||
inet_ntop(AF_INET, &ind, daddr, sizeof(daddr));
|
|
||||||
inet_ntop(AF_INET, &ing, gaddr, sizeof(gaddr));
|
|
||||||
dbg("Got gw %s dst/len %s/%d ifindex %d", gaddr, daddr, plen, idx);
|
|
||||||
|
|
||||||
if ((!dst && !plen) && (gw || idx)) {
|
|
||||||
if (nlmsg->nlmsg_type == RTM_DELROUTE) {
|
|
||||||
cond_clear("net/route/default");
|
cond_clear("net/route/default");
|
||||||
nl_defidx = 0;
|
else
|
||||||
} else {
|
|
||||||
cond_set("net/route/default");
|
cond_set("net/route/default");
|
||||||
nl_defidx = idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,277 +105,83 @@ static void net_cond_set(char *ifname, char *cond, int set)
|
|||||||
cond_clear(msg);
|
cond_clear(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int validate_ifname(const char *ifname)
|
static void nl_link(struct nlmsghdr *nlmsg)
|
||||||
{
|
{
|
||||||
if (!ifname || !ifname[0])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (strnlen(ifname, IFNAMSIZ) == IFNAMSIZ)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!strcmp(ifname, ".") || !strcmp(ifname, ".."))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
while (*ifname) {
|
|
||||||
if (*ifname == '/' || *ifname == ':' || isspace(*ifname))
|
|
||||||
return 1;
|
|
||||||
ifname++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if this interface was associated with the default route
|
|
||||||
* previously, or if it's been removed. If so, trigger a recheck
|
|
||||||
* of the system default route.
|
|
||||||
*/
|
|
||||||
static void nl_check_default(char *ifname)
|
|
||||||
{
|
|
||||||
int idx = (int)if_nametoindex(ifname);
|
|
||||||
|
|
||||||
if ((nl_defidx > 0 && nl_defidx == idx) || (idx == 0 && errno == ENODEV))
|
|
||||||
nl_ifdown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|
||||||
{
|
|
||||||
char ifname[IFNAMSIZ + 1];
|
|
||||||
struct ifinfomsg *i;
|
|
||||||
struct rtattr *a;
|
|
||||||
int la;
|
int la;
|
||||||
|
char ifname[IFNAMSIZ + 1];
|
||||||
|
struct rtattr *a;
|
||||||
|
struct ifinfomsg *i;
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
||||||
errx(1, "Packet too small or truncated!");
|
_e("Packet too small or truncated!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = NLMSG_DATA(nlmsg);
|
i = NLMSG_DATA(nlmsg);
|
||||||
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
||||||
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
||||||
if (la >= len) {
|
|
||||||
errx(1, "Packet too large!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; RTA_OK(a, la); a = RTA_NEXT(a, la)) {
|
|
||||||
if (a->rta_type != IFLA_IFNAME)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
|
||||||
if (validate_ifname(ifname)) {
|
|
||||||
dbg("Invalid interface name '%s', skipping ...", ifname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (nlmsg->nlmsg_type) {
|
|
||||||
case RTM_NEWLINK:
|
|
||||||
/*
|
|
||||||
* New interface has appeared, or interface flags has changed.
|
|
||||||
* Check ifi_flags here to see if the interface is UP/DOWN
|
|
||||||
*/
|
|
||||||
dbg("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
|
||||||
net_cond_set(ifname, "exist", 1);
|
|
||||||
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
|
||||||
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
|
||||||
if (!(i->ifi_flags & IFF_UP) || !(i->ifi_flags & IFF_RUNNING))
|
|
||||||
nl_check_default(ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_DELLINK:
|
|
||||||
/* NOTE: Interface has disappeared, not link down ... */
|
|
||||||
dbg("%s: Delete link", ifname);
|
|
||||||
net_cond_set(ifname, "exist", 0);
|
|
||||||
net_cond_set(ifname, "up", 0);
|
|
||||||
net_cond_set(ifname, "running", 0);
|
|
||||||
nl_check_default(ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_NEWADDR:
|
|
||||||
dbg("%s: New Address", ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_DELADDR:
|
|
||||||
dbg("%s: Deconfig Address", ifname);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
dbg("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nl_parse(int sd)
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
struct nlmsghdr *nh;
|
|
||||||
ssize_t len;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
while ((len = recv(sd, nl_buf, NL_BUFSZ, 0)) < 0) {
|
|
||||||
switch (errno) {
|
|
||||||
case EAGAIN: /* Nothing more right now. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case EINTR: /* Signal */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case ENOBUFS: /* netlink(7) */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
err(1, "recv()");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbg("recv %zd bytes", len);
|
|
||||||
l = (size_t)len;
|
|
||||||
for (nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, l); nh = NLMSG_NEXT(nh, l)) {
|
|
||||||
struct nlmsgerr *nle;
|
|
||||||
|
|
||||||
switch (nh->nlmsg_type) {
|
|
||||||
case NLMSG_DONE:
|
|
||||||
// dbg("Done with netlink messages.");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case NLMSG_ERROR:
|
|
||||||
// dbg("Kernel netlink comm. error.");
|
|
||||||
nle = NLMSG_DATA(nh);
|
|
||||||
if (nle) {
|
|
||||||
errno = -nle->error;
|
|
||||||
err(1, "Kernel netlink error %d", errno);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case RTM_NEWROUTE:
|
|
||||||
case RTM_DELROUTE:
|
|
||||||
// dbg("Netlink route ...");
|
|
||||||
nl_route(nh, len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
while (RTA_OK(a, la)) {
|
||||||
|
if (a->rta_type == IFLA_IFNAME) {
|
||||||
|
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
||||||
|
switch (nlmsg->nlmsg_type) {
|
||||||
case RTM_NEWLINK:
|
case RTM_NEWLINK:
|
||||||
|
/*
|
||||||
|
* New interface has appeared, or interface flags has changed.
|
||||||
|
* Check ifi_flags here to see if the interface is UP/DOWN
|
||||||
|
*/
|
||||||
|
_d("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
||||||
|
net_cond_set(ifname, "exist", 1);
|
||||||
|
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
||||||
|
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
||||||
|
break;
|
||||||
|
|
||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
// dbg("Netlink link ...");
|
/* NOTE: Interface has disappeared, not link down ... */
|
||||||
nl_link(nh, len);
|
_d("%s: Delete link", ifname);
|
||||||
|
net_cond_set(ifname, "exist", 0);
|
||||||
|
net_cond_set(ifname, "up", 0);
|
||||||
|
net_cond_set(ifname, "running", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
_d("%s: New Address", ifname);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_DELADDR:
|
||||||
|
_d("%s: Deconfig Address", ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
warnx("unhandled netlink message, type %d", nh->nlmsg_type);
|
_d("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a = RTA_NEXT(a, la);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl_request(int sd, unsigned int seq, int type)
|
|
||||||
{
|
|
||||||
struct nl_request *nlr = (struct nl_request *)nl_buf;
|
|
||||||
|
|
||||||
memset(nlr, 0, sizeof(struct nl_request));
|
|
||||||
nlr->nh.nlmsg_type = type;
|
|
||||||
nlr->nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
|
||||||
nlr->nh.nlmsg_seq = seq;
|
|
||||||
nlr->nh.nlmsg_pid = 1;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case RTM_GETROUTE:
|
|
||||||
// dbg("RTM_GETROUTE");
|
|
||||||
nlr->rtm.rtm_family = AF_INET;
|
|
||||||
nlr->rtm.rtm_table = RT_TABLE_MAIN;
|
|
||||||
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTM_GETLINK:
|
|
||||||
// dbg("RTM_GETLINK");
|
|
||||||
nlr->ifi.ifi_family = AF_UNSPEC;
|
|
||||||
nlr->ifi.ifi_change = 0xFFFFFFFF;
|
|
||||||
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
warnx("Cannot resync, unhandled message type %d", type);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send(sd, nlr, nlr->nh.nlmsg_len, 0) < 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return nl_parse(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_resync_routes(int sd, unsigned int seq)
|
|
||||||
{
|
|
||||||
if (nl_request(sd, seq, RTM_GETROUTE))
|
|
||||||
err(1, "Failed netlink route request");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_resync_ifaces(int sd, unsigned int seq)
|
|
||||||
{
|
|
||||||
if (nl_request(sd, seq, RTM_GETLINK))
|
|
||||||
err(1, "Failed netlink link request");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We've potentially lost netlink events, let's resync with kernel.
|
|
||||||
*/
|
|
||||||
static void nl_resync(int all)
|
|
||||||
{
|
|
||||||
unsigned int seq = 0;
|
|
||||||
int sd;
|
|
||||||
|
|
||||||
sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
|
||||||
if (sd < 0) {
|
|
||||||
err(1, "netlink socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all) {
|
|
||||||
dbg("============================ RESYNC =================================");
|
|
||||||
/* this doesn't update conditions, and thus does not stop services */
|
|
||||||
cond_deassert("net/");
|
|
||||||
|
|
||||||
nl_resync_ifaces(sd, seq++);
|
|
||||||
nl_resync_routes(sd, seq++);
|
|
||||||
|
|
||||||
/* delayed update after we've corrected things */
|
|
||||||
service_step_all(SVC_TYPE_ANY);
|
|
||||||
dbg("=========================== RESYNCED ================================");
|
|
||||||
} else
|
|
||||||
nl_resync_routes(sd, seq++);
|
|
||||||
|
|
||||||
close(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_callback(void *arg, int sd, int events)
|
static void nl_callback(void *arg, int sd, int events)
|
||||||
{
|
{
|
||||||
if (nl_parse(sd) < 0) {
|
ssize_t len;
|
||||||
if (errno == ENOBUFS) { /* netlink(7) */
|
static char buf[4096];
|
||||||
warnx("busy system, resynchronizing with kernel.");
|
struct nlmsghdr *nh;
|
||||||
nl_resync(1);
|
|
||||||
return;
|
memset(buf, 0, sizeof(buf));
|
||||||
}
|
len = recv(sd, buf, sizeof(buf), 0);
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno != EINTR) /* Signal */
|
||||||
|
_pe("recv()");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
for (nh = (struct nlmsghdr *)buf; !nlmsg_validate(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
||||||
* Linux doesn't send route changes when interfaces go down, so
|
//_d("Well formed netlink message received. type %d ...", nh->nlmsg_type);
|
||||||
* we need to check ourselves, e.g. for loss of default route.
|
if (nh->nlmsg_type == RTM_NEWROUTE || nh->nlmsg_type == RTM_DELROUTE)
|
||||||
*/
|
nl_route(nh);
|
||||||
if (nl_ifdown) {
|
else
|
||||||
dbg("interface down, checking default route.");
|
nl_link(nh);
|
||||||
if (nl_defidx > 0) {
|
|
||||||
nl_defidx = 0;
|
|
||||||
nl_resync(0);
|
|
||||||
if (nl_defidx <= 0) {
|
|
||||||
cond_clear("net/route/default");
|
|
||||||
nl_defidx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nl_ifdown = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,31 +199,24 @@ static plugin_t plugin = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl sa;
|
|
||||||
int sd;
|
int sd;
|
||||||
|
struct sockaddr_nl sa;
|
||||||
|
|
||||||
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
err(1, "socket()");
|
_pe("socket()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.nl_family = AF_NETLINK;
|
sa.nl_family = AF_NETLINK;
|
||||||
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK;
|
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK; // | RTMGRP_NOTIFY | RTMGRP_IPV4_IFADDR;
|
||||||
sa.nl_pid = getpid();
|
sa.nl_pid = getpid();
|
||||||
|
|
||||||
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||||
err(1, "bind()");
|
_pe("bind()");
|
||||||
close(sd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nl_buf = malloc(NL_BUFSZ);
|
|
||||||
if (!nl_buf) {
|
|
||||||
err(1, "malloc()");
|
|
||||||
close(sd);
|
close(sd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -448,10 +225,9 @@ PLUGIN_INIT(__init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
close(plugin.io.fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+39
-110
@@ -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-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2021 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,13 +52,13 @@ 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 %s", path);
|
_d("Path too deep, skipping.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE);
|
return iwatch_add(iw, path, IN_ONLYDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||||
@@ -66,95 +66,36 @@ 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);
|
||||||
|
_d("path: %s, mask: %08x", fn, mask);
|
||||||
|
|
||||||
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
|
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dbg("path: %s, mask: %08x", fn, mask);
|
|
||||||
|
|
||||||
svc = svc_find_by_pidfile(fn);
|
svc = svc_find_by_pidfile(fn);
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
dbg("No matching svc for %s", fn);
|
_d("No matching svc for %s", fn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (svc->state) {
|
_d("Found svc %s for %s with pid %d", svc->name, fn, svc->pid);
|
||||||
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));
|
||||||
|
if (mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
||||||
nm = svc_ident(svc, NULL, 0);
|
svc_started(svc);
|
||||||
dbg("Found svc %s for %s with pid %d", nm, fn, svc->pid);
|
|
||||||
if (svc_is_stopping(svc)) {
|
|
||||||
dbg("Ignoring pidfile death rattles while service %s is %s", nm, svc_status(svc));
|
|
||||||
goto sneaky_zebra;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
|
||||||
/*
|
|
||||||
* only mark native services as started, the s6 and
|
|
||||||
* systemd style services rely on their respective
|
|
||||||
* readiness notification. Issue #343
|
|
||||||
*/
|
|
||||||
if (svc->notify == SVC_NOTIFY_PID)
|
|
||||||
svc_started(svc);
|
|
||||||
|
|
||||||
if (!svc_has_pidfile(svc)) {
|
|
||||||
dbg("Setting %s PID file to %s", svc->name, fn);
|
|
||||||
pid_file_set(svc, fn, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (svc_is_forking(svc)) {
|
if (svc_is_forking(svc)) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = pid_file_read(fn);
|
pid = pid_file_read(pid_file(svc));
|
||||||
if (pid == -1) {
|
_d("Forking service %s changed PID from %d to %d",
|
||||||
/* handle case when service dies immediately */
|
svc->cmd, svc->pid, pid);
|
||||||
if (!fexist(fn))
|
svc->pid = pid;
|
||||||
cond_clear(cond);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Service is not crashing, let's tell state machine! */
|
|
||||||
service_forked(svc);
|
|
||||||
|
|
||||||
if (pid != svc->pid) {
|
|
||||||
dbg("Forking service %s (cmd %s) changed PID from %d to %d",
|
|
||||||
svc_ident(svc, NULL, 0), svc->cmd, svc->pid, pid);
|
|
||||||
svc->pid = pid;
|
|
||||||
|
|
||||||
/* Complement log in service.c for non-forking services */
|
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svc->notify == SVC_NOTIFY_PID)
|
cond_set(cond);
|
||||||
cond_set(cond);
|
} else if (mask & IN_DELETE)
|
||||||
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
|
||||||
service_ready(svc, 1);
|
|
||||||
} else if (mask & IN_DELETE) {
|
|
||||||
sneaky_zebra:
|
|
||||||
cond_clear(cond);
|
cond_clear(cond);
|
||||||
if (svc->notify == SVC_NOTIFY_PID)
|
|
||||||
service_ready(svc, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* synthesize events in case of new run dirs */
|
/* synthesize events in case of new run dirs */
|
||||||
@@ -176,7 +117,7 @@ static void pidfile_scandir(struct iwatch *iw, char *dir, int len)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
dbg("scan found %s", gl.gl_pathv[i]);
|
_d("scan found %s", gl.gl_pathv[i]);
|
||||||
pidfile_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
pidfile_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
@@ -191,7 +132,7 @@ static void pidfile_handle_dir(struct iwatch *iw, char *dir, char *name, int mas
|
|||||||
struct iwatch_path *iwp;
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
paste(path, sizeof(path), dir, name);
|
paste(path, sizeof(path), dir, name);
|
||||||
dbg("path: %s", path);
|
_d("path: %s", path);
|
||||||
|
|
||||||
iwp = iwatch_find_by_path(iw, path);
|
iwp = iwatch_find_by_path(iw, path);
|
||||||
|
|
||||||
@@ -210,29 +151,24 @@ static void pidfile_callback(void *arg, int fd, int events)
|
|||||||
{
|
{
|
||||||
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
struct inotify_event *ev;
|
struct inotify_event *ev;
|
||||||
ssize_t sz;
|
ssize_t sz, off;
|
||||||
size_t off;
|
|
||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
err(1, "invalid inotify event");
|
_pe("invalid inotify event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
for (off = 0; off < sz; off += sizeof(*ev) + ev->len) {
|
||||||
struct iwatch_path *iwp;
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
if (off + sizeof(*ev) > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ev = (struct inotify_event *)&ev_buf[off];
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!ev->mask)
|
if (!ev->mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
_d("name %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
|
|
||||||
/* Find base path for this event */
|
/* Find base path for this event */
|
||||||
iwp = iwatch_find_by_wd(&iw_pidfile, ev->wd);
|
iwp = iwatch_find_by_wd(&iw_pidfile, ev->wd);
|
||||||
if (!iwp)
|
if (!iwp)
|
||||||
@@ -243,7 +179,12 @@ static void pidfile_callback(void *arg, int fd, int events)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev->mask & (IN_CLOSE_WRITE | IN_DELETE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO))
|
if (ev->mask & IN_DELETE) {
|
||||||
|
_d("pidfile %s/%s removed ...", iwp->path, ev->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->mask & (IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO))
|
||||||
pidfile_update_conds(iwp->path, ev->name, ev->mask);
|
pidfile_update_conds(iwp->path, ev->name, ev->mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,9 +208,6 @@ static void pidfile_reconf(void *arg)
|
|||||||
if (svc_is_changed(svc) || svc_is_starting(svc))
|
if (svc_is_changed(svc) || svc_is_starting(svc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (svc->notify == SVC_NOTIFY_PID)
|
|
||||||
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)
|
||||||
continue;
|
continue;
|
||||||
@@ -278,9 +216,9 @@ static void pidfile_reconf(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This calls service_step(), which in turn schedules itself as
|
* This will call service_step(), which in turn will schedule itself
|
||||||
* long as stepped services change state. Services going from
|
* as long as stepped services change state. Services going from
|
||||||
* PAUSED to RUNNING reassert their conditions in that loop,
|
* WAITING to RUNNING will reassert their conditions in that loop,
|
||||||
* which in turn may unlock other services, and so on.
|
* which in turn may unlock other services, and so on.
|
||||||
*/
|
*/
|
||||||
service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK);
|
service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK);
|
||||||
@@ -288,14 +226,8 @@ static void pidfile_reconf(void *arg)
|
|||||||
|
|
||||||
static void pidfile_init(void *arg)
|
static void pidfile_init(void *arg)
|
||||||
{
|
{
|
||||||
char piddir[MAX_ARG_LEN];
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (mkpath(pid_runpath(_PATH_CONDPID, piddir, sizeof(piddir)), 0755) && errno != EEXIST) {
|
|
||||||
err(1, "Failed creating %s condition directory, %s", COND_PID, _PATH_CONDPID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The bootmisc plugin is responsible for setting up /var/run.
|
* The bootmisc plugin is responsible for setting up /var/run.
|
||||||
* and/or /run, with proper symlinks etc. We depend on bootmisc
|
* and/or /run, with proper symlinks etc. We depend on bootmisc
|
||||||
@@ -303,18 +235,15 @@ static void pidfile_init(void *arg)
|
|||||||
*/
|
*/
|
||||||
path = realpath(_PATH_VARRUN, NULL);
|
path = realpath(_PATH_VARRUN, NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
dbg("Failed querying realpath(%s): %s", _PATH_VARRUN, strerror(errno));
|
|
||||||
path = realpath("/run", NULL);
|
path = realpath("/run", NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
errx(1, "System does not have %s or /run, aborting.", _PATH_VARRUN);
|
_e("System does not have %s or /run, aborting.", _PATH_VARRUN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile_add_path(&iw_pidfile, path))
|
if (pidfile_add_path(&iw_pidfile, path))
|
||||||
iwatch_exit(&iw_pidfile);
|
iwatch_exit(&iw_pidfile);
|
||||||
|
|
||||||
free(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -327,18 +256,18 @@ static void pidfile_init(void *arg)
|
|||||||
*
|
*
|
||||||
* service <net/iface/lo> /sbin/dropbear ...
|
* service <net/iface/lo> /sbin/dropbear ...
|
||||||
*
|
*
|
||||||
* This service provides the <pid/dropbear> condition, which will not be
|
* Which provides the <pid/dropbear> condition, will not be set by
|
||||||
* set by pidfile.so during `initctl reload` because dropbear is still
|
* pidfile.so during `initctl reload` because dropbear is still
|
||||||
* SIGSTP:ed (in state PAUSED) waiting for <net/iface/lo>.
|
* SIGSTP:ed waiting for <net/iface/lo>.
|
||||||
*/
|
*/
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
||||||
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
||||||
.depends = { "netlink" }, /* bootmisc depends on us */
|
.depends = { "netlink" },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -353,10 +282,10 @@ PLUGIN_INIT(__init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
|
||||||
iwatch_exit(&iw_pidfile);
|
iwatch_exit(&iw_pidfile);
|
||||||
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+8
-28
@@ -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-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2021 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,30 +22,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.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)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
glob_t gl;
|
glob_t gl;
|
||||||
|
char buf[160];
|
||||||
if (rescue) {
|
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glob("/run/sysctl.d/*.conf", 0, NULL, &gl);
|
glob("/run/sysctl.d/*.conf", 0, NULL, &gl);
|
||||||
glob("/etc/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
glob("/etc/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
||||||
@@ -55,13 +39,9 @@ static void setup(void *arg)
|
|||||||
glob("/mnt/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
glob("/mnt/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
||||||
glob("/etc/sysctl.conf", GLOB_APPEND, NULL, &gl);
|
glob("/etc/sysctl.conf", GLOB_APPEND, NULL, &gl);
|
||||||
if (gl.gl_pathc > 0) {
|
if (gl.gl_pathc > 0) {
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
char cmd[160];
|
snprintf(buf, sizeof(buf), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
||||||
|
run(buf);
|
||||||
snprintf(cmd, sizeof(cmd), "%s -e -p %s >/dev/null", SYSCTL_PATH, gl.gl_pathv[i]);
|
|
||||||
run(cmd, "sysctl");
|
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
}
|
}
|
||||||
@@ -76,12 +56,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary files for resolvconf
|
/* Setup necessary files for resolvconf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2021 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
|
||||||
@@ -21,11 +21,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -37,7 +33,7 @@
|
|||||||
*/
|
*/
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
dbg("Setting up the resolver ...");
|
_d("Setting up the resolver ...");
|
||||||
mkpath("/etc/resolvconf", 0755);
|
mkpath("/etc/resolvconf", 0755);
|
||||||
mkpath("/etc/resolvconf/run", 0755);
|
mkpath("/etc/resolvconf/run", 0755);
|
||||||
mkpath("/var/run/resolvconf", 0755);
|
mkpath("/var/run/resolvconf", 0755);
|
||||||
@@ -45,7 +41,7 @@ static void setup(void *arg)
|
|||||||
|
|
||||||
touch("/etc/resolvconf/run/enable-updates");
|
touch("/etc/resolvconf/run/enable-updates");
|
||||||
chdir("/etc/resolvconf/run/interface");
|
chdir("/etc/resolvconf/run/interface");
|
||||||
run_parts("/etc/resolvconf/update.d", "-i", NULL, 0, 0);
|
run_parts("/etc/resolvconf/update.d", "-i");
|
||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,12 +53,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-217
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore RTC using hwclock
|
/* Save and restore RTC using hwclock
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2021 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
|
||||||
@@ -21,43 +21,17 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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. The
|
|
||||||
* on NTP sync the driver can also update the RTC every 11 mins. We use
|
|
||||||
* the same update interval to handle manual time set and file save.
|
|
||||||
*/
|
|
||||||
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
|
||||||
#define RTC_FMT "%Y-%m-%d %H:%M:%S"
|
|
||||||
#define RTC_PERIOD (11 * 60 * 1000)
|
|
||||||
|
|
||||||
#ifdef RTC_TIMESTAMP_CUSTOM
|
|
||||||
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
|
||||||
#else
|
|
||||||
static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
|
||||||
#endif
|
|
||||||
static time_t rtc_date_fallback = 946684800LL;
|
|
||||||
|
|
||||||
static char *rtc_file = RTC_FILE;
|
|
||||||
static uev_t rtc_timer;
|
|
||||||
|
|
||||||
|
/* Kernel RTC driver validates against this date for sanity check */
|
||||||
|
#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */
|
||||||
|
|
||||||
static void tz_set(char *tz, size_t len)
|
static void tz_set(char *tz, size_t len)
|
||||||
{
|
{
|
||||||
@@ -82,125 +56,6 @@ 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[] = {
|
||||||
@@ -224,124 +79,107 @@ 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) {
|
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = rtc_open();
|
fd = rtc_open();
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((rc = time_get(&tm))) {
|
tz_set(tz, sizeof(tz));
|
||||||
|
rc = gettimeofday(&tv, NULL);
|
||||||
|
if (rc < 0 || tv.tv_sec < RTC_TIMESTAMP_BEGIN_2000) {
|
||||||
print_desc(NULL, "System clock invalid, not saving to RTC");
|
print_desc(NULL, "System clock invalid, not saving to RTC");
|
||||||
} else {
|
invalid:
|
||||||
print_desc(NULL, "Saving system clock (UTC) to RTC");
|
logit(LOG_ERR, "System clock invalid, before 2000-01-01 00:00, not saving 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) {
|
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = rtc_open();
|
fd = rtc_open();
|
||||||
if (fd < 0) {
|
if (fd < 0)
|
||||||
file_restore(arg);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if ((rc = ioctl(fd, RTC_RD_TIME, &tm)) < 0) {
|
tz_set(tz, sizeof(tz));
|
||||||
|
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 {
|
|
||||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
invalid:
|
||||||
rc = time_set(&tm);
|
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
||||||
|
if (EINVAL == errno)
|
||||||
|
logit(LOG_ERR, "RTC time is too old (before 2000-01-01 00:00)");
|
||||||
|
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));
|
||||||
|
rc = 2;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||||
logit(LOG_WARNING, "Failed restoring system clock from RTC.");
|
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||||
if (EINVAL == errno)
|
tv.tv_sec = mktime(&tm);
|
||||||
logit(LOG_WARNING, "RTC time is too old (before %s)", rtc_timestamp);
|
if (tv.tv_sec < RTC_TIMESTAMP_BEGIN_2000) {
|
||||||
else if (ENOENT == errno)
|
errno = EINVAL;
|
||||||
logit(LOG_WARNING, "RTC has no previously saved (valid) time.");
|
goto invalid;
|
||||||
else
|
}
|
||||||
logit(LOG_WARNING, "RTC error code %d: %s", errno, strerror(errno));
|
|
||||||
|
|
||||||
print(2, NULL);
|
if (settimeofday(&tv, NULL) == -1)
|
||||||
|
rc = 1;
|
||||||
/* 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 = save
|
.cb = rtc_save
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
|
||||||
|
|
||||||
if (!strptime(rtc_timestamp, RTC_FMT, &tm)) {
|
|
||||||
logit(LOG_WARNING, "Invalid restore date '%s', reverting to '%s'",
|
|
||||||
rtc_timestamp, RTC_TIMESTAMP_BEGIN_2000);
|
|
||||||
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
|
||||||
} else
|
|
||||||
rtc_date_fallback = mktime(&tm);
|
|
||||||
|
|
||||||
uev_timer_init(ctx, &rtc_timer, update, NULL, RTC_PERIOD, RTC_PERIOD);
|
|
||||||
|
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
uev_timer_stop(&rtc_timer);
|
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-213
@@ -1,213 +0,0 @@
|
|||||||
/* System condition event monitor for the Finit condition engine
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#include <glob.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <paths.h>
|
|
||||||
|
|
||||||
#include "finit.h"
|
|
||||||
#include "cond.h"
|
|
||||||
#include "pid.h"
|
|
||||||
#include "plugin.h"
|
|
||||||
#include "iwatch.h"
|
|
||||||
|
|
||||||
static struct iwatch iw_sys;
|
|
||||||
|
|
||||||
|
|
||||||
static int sys_add_path(struct iwatch *iw, char *path)
|
|
||||||
{
|
|
||||||
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* unlink conditions with no active task/service, otherwise they may
|
|
||||||
* trigger inadvertently when calling `initctl reload` to activate
|
|
||||||
* a new configuration.
|
|
||||||
*/
|
|
||||||
static void sys_update_conds(char *dir, char *name, uint32_t mask)
|
|
||||||
{
|
|
||||||
char path[256];
|
|
||||||
char *cond;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
ptr = strrchr(name, '/');
|
|
||||||
if (ptr)
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", dir, ++ptr);
|
|
||||||
else
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", dir, name);
|
|
||||||
|
|
||||||
cond = strstr(path, COND_BASE);
|
|
||||||
if (!cond)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond += strlen(COND_BASE) + 1;
|
|
||||||
dbg("cond: %s set: %d", cond, (mask & IN_CREATE) ? 1 : 0);
|
|
||||||
if (!cond_update(cond))
|
|
||||||
unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* synthesize events in case of new run dirs */
|
|
||||||
static void sys_scandir(struct iwatch *iw, char *dir, int len)
|
|
||||||
{
|
|
||||||
glob_t gl;
|
|
||||||
size_t i;
|
|
||||||
char path[len + 6];
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/*", dir);
|
|
||||||
rc = glob(path, GLOB_NOSORT, NULL, &gl);
|
|
||||||
if (rc && rc != GLOB_NOMATCH)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
|
||||||
dbg("scan found %s", gl.gl_pathv[i]);
|
|
||||||
sys_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
|
||||||
}
|
|
||||||
globfree(&gl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create/remove sub-directory in monitored directory
|
|
||||||
*/
|
|
||||||
static void sys_handle_dir(struct iwatch *iw, char *dir, char *name, int mask)
|
|
||||||
{
|
|
||||||
char path[strlen(dir) + strlen(name) + 2];
|
|
||||||
struct iwatch_path *iwp;
|
|
||||||
|
|
||||||
paste(path, sizeof(path), dir, name);
|
|
||||||
dbg("path: %s", path);
|
|
||||||
|
|
||||||
iwp = iwatch_find_by_path(iw, path);
|
|
||||||
|
|
||||||
if (mask & IN_CREATE) {
|
|
||||||
if (!iwp) {
|
|
||||||
if (!sys_add_path(iw, path))
|
|
||||||
sys_scandir(iw, path, sizeof(path));
|
|
||||||
}
|
|
||||||
} else if (mask & IN_DELETE) {
|
|
||||||
if (iwp)
|
|
||||||
iwatch_del(&iw_sys, iwp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sys_callback(void *arg, int fd, int events)
|
|
||||||
{
|
|
||||||
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
|
||||||
struct inotify_event *ev;
|
|
||||||
ssize_t sz;
|
|
||||||
size_t off;
|
|
||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
|
||||||
if (sz <= 0) {
|
|
||||||
err(1, "invalid inotify event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ev_buf[sz] = 0;
|
|
||||||
|
|
||||||
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
|
||||||
struct iwatch_path *iwp;
|
|
||||||
|
|
||||||
if (off + sizeof(*ev) > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ev = (struct inotify_event *)&ev_buf[off];
|
|
||||||
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
dbg("name %s, event: 0x%08x", ev->name, ev->mask);
|
|
||||||
if (!ev->mask)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Find base path for this event */
|
|
||||||
iwp = iwatch_find_by_wd(&iw_sys, ev->wd);
|
|
||||||
if (!iwp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ev->mask & IN_ISDIR) {
|
|
||||||
sys_handle_dir(&iw_sys, iwp->path, ev->name, ev->mask);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev->mask & (IN_CREATE | IN_DELETE))
|
|
||||||
sys_update_conds(iwp->path, ev->name, ev->mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sys_init(void *arg)
|
|
||||||
{
|
|
||||||
char sysdir[MAX_ARG_LEN];
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
mkpath(_PATH_COND, 0755);
|
|
||||||
if (mkpath(pid_runpath(_PATH_CONDSYS, sysdir, sizeof(sysdir)), 0755) && errno != EEXIST) {
|
|
||||||
err(1, "Failed creating %s condition directory, %s", COND_SYS, _PATH_CONDSYS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = realpath(_PATH_CONDSYS, NULL);
|
|
||||||
if (!path) {
|
|
||||||
err(1, "Cannot figure out real path to %s, aborting", _PATH_CONDSYS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iwatch_add(&iw_sys, path, IN_ONLYDIR))
|
|
||||||
iwatch_exit(&iw_sys);
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
|
||||||
.name = __FILE__,
|
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = sys_init },
|
|
||||||
.depends = { "bootmisc", },
|
|
||||||
};
|
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = iwatch_init(&iw_sys);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
plugin.io.fd = fd;
|
|
||||||
plugin.io.cb = sys_callback;
|
|
||||||
plugin.io.flags = PLUGIN_IO_READ;
|
|
||||||
|
|
||||||
plugin_register(&plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
|
||||||
{
|
|
||||||
plugin_unregister(&plugin);
|
|
||||||
iwatch_exit(&iw_sys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Local Variables:
|
|
||||||
* indent-tabs-mode: t
|
|
||||||
* c-file-style: "linux"
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
+32
-57
@@ -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-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2013-2021 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,24 +27,18 @@
|
|||||||
#include <unistd.h> /* read() */
|
#include <unistd.h> /* read() */
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef _LIBITE_LITE
|
#include <lite/lite.h>
|
||||||
# include <libite/lite.h>
|
|
||||||
#else
|
|
||||||
# include <lite/lite.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.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 watcher(void *arg, int fd, int events);
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.io = {
|
.io = {
|
||||||
.cb = tty_watcher,
|
.cb = watcher,
|
||||||
.flags = PLUGIN_IO_READ,
|
.flags = PLUGIN_IO_READ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -56,70 +50,51 @@ static void setup(void)
|
|||||||
|
|
||||||
plugin.io.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
plugin.io.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0)
|
if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0)
|
||||||
err(1, "Failed starting TTY watcher");
|
_pe("Failed starting TTY watcher");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_tty(char *tty, size_t len, int creat)
|
static void watcher(void *arg, int fd, int events)
|
||||||
{
|
{
|
||||||
char name[len + 6];
|
char buf[EVENT_SIZE];
|
||||||
svc_t *svc;
|
int len = 0;
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "/dev/%s", tty);
|
while ((len = read(fd, buf, sizeof(buf)))) {
|
||||||
svc = svc_find_by_tty(name);
|
struct inotify_event *notified = (struct inotify_event *)buf;
|
||||||
if (svc) {
|
char name[notified->len + 6];
|
||||||
if (svc_is_blocked(svc) && creat) {
|
struct tty *entry;
|
||||||
dbg("%s: blocked, re-enabling", svc_ident(svc, NULL, 0));
|
|
||||||
svc_start(svc);
|
if (-1 == len) {
|
||||||
} else if (svc->pid) {
|
if (errno == EINVAL)
|
||||||
dbg("%s: missing ...", svc_ident(svc, NULL, 0));
|
setup();
|
||||||
svc_missing(svc);
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break; /* Likely EAGAIN */
|
||||||
}
|
}
|
||||||
|
|
||||||
service_step_all(SVC_TYPE_TTY);
|
snprintf(name, sizeof(name), "/dev/%s", notified->name);
|
||||||
|
entry = tty_find(name);
|
||||||
|
if (entry && tty_enabled(entry)) {
|
||||||
|
if (notified->mask & IN_CREATE)
|
||||||
|
tty_start(entry);
|
||||||
|
else if (entry->pid)
|
||||||
|
tty_stop(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tty_watcher(void *arg, int fd, int events)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
|
||||||
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
|
||||||
struct inotify_event *ev;
|
|
||||||
ssize_t sz;
|
|
||||||
size_t off;
|
|
||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
|
||||||
if (sz <= 0) {
|
|
||||||
err(1, "invalid inotify event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ev_buf[sz] = 0;
|
|
||||||
|
|
||||||
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
|
||||||
if (off + sizeof(*ev) > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ev = (struct inotify_event *)&ev_buf[off];
|
|
||||||
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!ev->mask)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
dbg("tty %s, event: 0x%08x", ev->name, ev->mask);
|
|
||||||
do_tty(ev->name, ev->len, ev->mask & IN_CREATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN_INIT(__init)
|
|
||||||
{
|
{
|
||||||
setup();
|
setup();
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(__exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
|
||||||
if (plugin.io.fd)
|
if (plugin.io.fd)
|
||||||
close(plugin.io.fd);
|
close(plugin.io.fd);
|
||||||
|
|
||||||
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user