Compare commits

..
28 Commits
Author SHA1 Message Date
Joachim Nilsson 9b361864fa Fix make dist target for v1.11 release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-24 16:16:13 +01:00
Joachim Nilsson 41b0dc41a6 Update ChangeLog for v1.11 release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-24 16:13:46 +01:00
Joachim Nilsson cab339c857 Simplify build example.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-24 16:07:55 +01:00
Joachim Nilsson dcb42602c9 Cleanup README for release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-24 16:04:54 +01:00
Joachim Nilsson 9e446557b4 Change Coverity Scan branch to use 'dev' instead of master.
We don't want to run out of scan tokens for every README update.  This
also means the introduction of a new workflow.  All new development must
be staged to the dev branch before being merged to master.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-24 15:29:16 +01:00
Joachim Nilsson a3d76c58a4 Expand on how plugins can interact with system bootstrap.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-21 19:34:01 +01:00
Joachim Nilsson e0e0581d10 Trim slogan ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-21 13:29:35 +01:00
Joachim Nilsson ef75d5ec31 Cleanup Introduction and add Bootstrap section.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-21 13:25:24 +01:00
Joachim Nilsson dfeabd8bae Improve inetd syntax proposal
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-21 13:15:16 +01:00
Joachim Nilsson 7aa687bad9 Reindent to more 'pure' Markdown and remove fixed event lib TODO.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-19 21:24:06 +01:00
Joachim Nilsson c2ea2c1193 Reindent to more 'pure' Markdown.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-19 21:12:14 +01:00
Joachim Nilsson 291b22e987 Give up and add actual link to GIT commit.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 23:46:21 +01:00
Joachim Nilsson a091b69dd6 Another try ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 23:45:16 +01:00
Joachim Nilsson 887c84a0d1 Attempt to fix GIT commit auto linking.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 23:44:27 +01:00
Joachim Nilsson 5009d54ab8 Reindent to more 'pure' Markdown.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 23:43:04 +01:00
Joachim Nilsson 840ade6da7 Bump version for next release, fix make dist and rename NEWS --> CHANGELOG
- Bump version for coming 1.11 release
- Update `make dist` to use Kentzo's `git-archive-all` from
  https://github.com/Kentzo/git-archive-all
- Rename NEWS --> CHANGELOG and update for coming release
- Update CHANGELOG with info on the libuEv migration

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 23:22:39 +01:00
Joachim Nilsson 030aa70842 Simplify.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 22:29:34 +01:00
Joachim Nilsson dea3ae857b Steal controlling TTY on fallback console to enable job control.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 22:25:04 +01:00
Joachim Nilsson 9f5172b0d1 Try removing delayed start of TTYs, should not be needed anymore.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 21:40:09 +01:00
Joachim Nilsson e0529a5597 Unblock all signals blocked by finit when starting children
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 21:40:05 +01:00
Joachim Nilsson 425cd17e57 Initial conversion to use libuEv for all event handling.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 00:53:14 +01:00
Joachim Nilsson 0669a9cb81 Fix missing #include for copyfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-18 00:46:06 +01:00
Joachim Nilsson 5e040449c4 Add libuEv as submodule for event handling.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-07 02:59:21 +01:00
Joachim Nilsson 074686b520 Use vfork() instead of fork() before exec()
If running on older Linux systems, or any BSD UNIX, vfork()
is more efficient when we are about to call exec() anyway.

For more info on vfork() vs fork(), see Stack Exchange:
http://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork-and-vfork

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-06 23:38:47 +01:00
Joachim Nilsson d40f52357e Restructure and add section on Watchdog process supervision
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-06 21:45:14 +01:00
Joachim Nilsson 076f77a31b Update TODO: more on inetd and at support.
Also a minor fix to the README.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-06 20:54:52 +01:00
Joachim Nilsson 8f1c16a8a5 Update TODO with section on Cron.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-01 02:04:50 +01:00
Joachim Nilsson b149dbc73e Update TODO
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-01-01 00:11:44 +01:00
23 changed files with 803 additions and 590 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "libuev"]
path = libuev
url = https://github.com/troglobit/libuev.git
+2 -2
View File
@@ -13,9 +13,9 @@ addons:
coverity_scan: coverity_scan:
project: project:
name: "troglobit/finit" name: "troglobit/finit"
description: "finit | Fast Init Replacement" description: "finit | Fast & Extensible init for Linux"
notification_email: troglobit@gmail.com notification_email: troglobit@gmail.com
build_command: "make" build_command: "make"
branch_pattern: master branch_pattern: dev
script: make script: make
Symlink
+1
View File
@@ -0,0 +1 @@
CHANGELOG.md
+278
View File
@@ -0,0 +1,278 @@
Change Log
==========
All notable changes to the project are documented in this file.
[1.11] - 2015-01-24
-------------------
The [libuEv] release.
### Changes
* Now using the asynchronous libuEv library for handling all events:
signals, timers and listening to sockets or file descriptors.
* Rename NEWS.md --> CHANGELOG.md, with symlinks for `make install`
* Attempt to align with http://keepachangelog.com/ for this file.
* Travis CI now only invokes Coverity Scan from the 'dev' branch. This
means that all development, except documentation updates, must go into
that branch.
### Fixes
* Fix bug with finit dying when no `tty` is defined in `finit.conf`, now
even the fallback shell has control over its TTY, see fix in GIT
commit [dea3ae8] for this.
[1.10] - 2014-11-27
-------------------
Major bug fix release.
### Changes
* Project now relies on static code analysis from Coverity, so this
release contains many serious bug fixes.
* Convert to use Markdown for README, NEWS and TODO.
* Serious update to README and slight pruning of finished TODO items.
### Fixes
* Fix serious file descriptor and memory leaks in the following
functions. In particular the leaks in `run_interactive()` are very
serious since that function is called every time a service is started
and/or restarted! For details, see the GIT log:
* `helpers.c:run()`
* `helpers.c:run_interactive()`
* `helpers.c:set_hostname()`
* `helpers.c:procname_kill()`
* `svc.c:svc_start()`: Fix swapped arguments to dup2() and add close(fd)
to prevent descriptor leak.
* `svc.c:svc_start()`: Fix out of bounds write to local stack variable,
wrote off-by-one outside array.
* Several added checks for return values to `mknod()`, `mkdir()`,
`remove()`, etc.
[1.9] - 2014-04-21
------------------
### Changes
* Add support for an include directive to `.conf` files
* Fallback to `/bin/sh` if user forgets tty setting
* Initial support for restarting lost services during `norespwan`
### Fixes
* Bug fixes, code cleanup
* Handle `SIGHUP` from service callback properly when switching runlevel
* Misc. major (memleak) and minor fixes and additions to `libite/lite.h`
[1.8] - 2013-06-07
------------------
### Changes
* Support for runlevels, with a bootstrap runlevel 'S'
* Support for saving previous and current runlevel to UTMP
* Support for new `finit.conf` commands: run, task, and runlevel
* Support for tty and console commands in `finit.conf`, like services
but for launching multiple getty logins
* New tty plugin to monitor TTYs coming and going, like USB TTYs
### Fixes
* Bugfixes to libite
[1.7] - 2012-10-08
------------------
### Changes
* Show `__FILE__` in `_d()` debug messages, useful for plugins with
similarily named callbacks. Also, only in debug mode anyway
* Make sure to cleanup recorded PID when a service is lost. Required by
service plugins for their callbacks to work.
* Only clear screen when in verbose mode. Maybe this should be removed
altogether?
### Fixes
* Bugfix: Do not `free()` static string in `finit.conf` parser
[1.6] - 2012-10-06
------------------
### Changes
* Skip `.` and `..` in plugin loader and display error when failing to
load plugins
* Support for overriding `/etc/finit.d` with `runparts DIR` in
`finit.conf`
* Revoke support for starting services not starting with a slash.
* Prevent endless restart of non-existing services in `finit.conf`
* Support for sysvinit style startstop scripts in `/etc/finit.d`
### Fixes
* Minor fix to alsa-utils plugin to silence on non-existing cards
[1.5] - 2012-10-03
------------------
### Changes
* Use bootmisc plugin to setup standard FHS 2.3 structure in `/var`
* Added `FLOG_WARN()` syslog macro, for plugins
* Add plugin dependency resolver. Checks `plugin_t` for `.depends`
[1.4] - 2012-10-02
------------------
### Changes
* Start refactoring helpers.c into a libite.so (-lite). This means
other user space applications/daemons can make use of the neat toolbox
available in finit
* Use short-form -s/-w -u to work with BusyBox hwclock as well
* Use RTLD_GLOBAL flag to tell dynamic loader to load dependent .so
files as well. Lets other plugins use global symbols.
* Greatly simplify svc hook for external plugins and cleanup plugin API.
* And more ... see the GIT log for more details.
### Fixes
* Fix I/O plugin watcher and load plugins earlier for a new hook
[1.3] - 2012-09-28
------------------
### Changes
* Cleanup public plugin API a bit and add new pid/pidfile funcs
* Add plugin hook to end of service startup
* Remove finit.h from svc.h, plugins should not need this.
* Move utility macros etc. to helpers.h
* Make `finit.h` daemon internal, only
* Move defines of FIFO, conf and rcS.d to Makefile => correct paths
* Add support for installing required headers in system include dir
* Better support for distributions and packagers with install-exec,
install-data, and install-dev targets in Makefile. Useful if you want
to call targets with different `$DESTDIR`!
* Makefile fixes for installation, paths encoded wrong
* Strip binaries + .so files, support for `$(CROSS)` toolchain strip
* Default install is now to `/sbin/finit` and `/usr/`
* Note change in `$PLUGIN_DIR` environemnt variable to `$plugindir`
[1.2] - 2012-09-27
------------------
### Changes
* Update README with section on building and enviroment variables
### Fixes
* Fix installation paths encoded in finit binary
[1.1] - 2012-09-27
------------------
### Changes
* Rename signal.[ch]-->sig.[ch] to avoid name clash w/ system headers
### Fixes
* Build fixes for ARM eabi/uClibc
[1.0] - 2012-09-26
------------------
### Changes
* New plugin based system for all odd extensions
* New service monitor that restarts services if they die
* New maintainer at GitHub http://github.com/troglobit/finit
* Add standard LICENSE and AUTHORS files
* New focus: embedded systems and small headless servers
[0.6] - 2010-06-14
------------------
* Don't start consolekit manually, dbus starts it (rtp)
* Unmount all filesystems before rebooting
* Disable `USE_VAR_RUN_RESOLVCONF` for Mandriva
* Unset terminal type in Mandriva before running X
* Remove extra sleep in finit-alt before calling services.sh (caio)
[0.5] - 2008-08-21
------------------
* Add option to start dbus and consolekit before the X server
* finit-alt listens to `/dev/initctl` to work with `reboot(8)` (smurfy)
* Write runlevel to utmp, needed by Printerdrake (Pascal Terjan)
* Fix ownership of `/var/run/utmp` (reported by Pascal Terjan)
* Remove obsolete code to load AGP drivers
* Conditional build of `/etc/resolveconf/run` support
* Add support to `/var/run/resolvconf` in Mandriva (blino)
[0.4] - 2008-05-16
------------------
* Default username for finit-alt configurable in Makefile
* Create loopback device node in finit-alt (for squashfs)
* Add option to use built-in run-parts instead of `/bin/run-parts`
* Ignore signal instead of setting to an empty handler (Metalshark)
* Handle pam_console permissions in finit-alt for Mandriva
* Add services.sh example and nash-hotplug patch for Mandriva
* Mount `/proc/bus/usb` in Mandriva
* Add runtime debug to finit-alt if finit_debug parameter is specified
* Read configuration from `/etc/finit.conf`
* Run getty with openvt on the virtual terminal
[0.3] - 2008-02-23
------------------
* Change poweroff method to `reboot(RB_POWER_OFF)` (Metalshark)
* Remove duplicate `unionctl()` reimplementation error
* Fix string termination in path creation
* Mount `/var/lock` and `/var/run` as tmpfs
[0.2] - 2008-02-19
------------------
* Replace `system("touch")` with `touch()` in finit-mod (Metalshark)
* Disable `NO_HCTOSYS` by default to match stock Eeepc kernel
* Drop `system("rm -f")` to clean `/tmp`, its a fresh mounted tmpfs
* Write ACPI sleep state to `/sys/power/state` instead of
`/proc/acpi/sleep` (Metalshark)
* Use direct calls to set loopback instead of `system("ifconfig")`
* Replace `system("cat")` and `system("dd")` with C implementation
* Moved finit-mod and finit-alt helpers to `helpers.c`
* Replace `system("echo;cat")` to draw shutdown splash with C calls
0.1 - 2008-02-14
----------------
* Initial release
[libuEv]: https://github.com/troglobit/libuev
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
[1.11]: https://github.com/troglobit/finit/compare/1.10...HEAD
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
+28 -13
View File
@@ -26,14 +26,16 @@
uninstall-exec uninstall-data uninstall-dev uninstall-exec uninstall-data uninstall-dev
#VERSION ?= $(shell git tag -l | tail -1) #VERSION ?= $(shell git tag -l | tail -1)
VERSION ?= 1.10 VERSION ?= 1.11
NAME = finit NAME = finit
PKG = $(NAME)-$(VERSION) PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev DEV = $(NAME)-dev
ARCHIVE = $(PKG).tar.xz ARCHTOOL = `which git-archive-all`
ARCHIVE = $(PKG).tar
ARCHIVEZ = ../$(ARCHIVE).xz
EXEC = finit reboot EXEC = finit reboot
HEADERS = plugin.h svc.h helpers.h queue.h HEADERS = plugin.h svc.h helpers.h queue.h
DISTFILES = LICENSE README NEWS finit.conf services DISTFILES = LICENSE README CHANGELOG finit.conf services
OBJS = finit.o conf.o helpers.o sig.o svc.o plugin.o tty.o OBJS = finit.o conf.o helpers.o sig.o svc.o plugin.o tty.o
SRCS = $(OBJS:.o=.c) SRCS = $(OBJS:.o=.c)
DEPS = $(addprefix .,$(SRCS:.c=.d)) DEPS = $(addprefix .,$(SRCS:.c=.d))
@@ -57,22 +59,24 @@ FINIT_RCSD ?= $(sysconfdir)/finit.d
CFLAGS += -W -Wall -Werror -Os CFLAGS += -W -Wall -Werror -Os
# Disable annoying gcc warning for "warn_unused_result", see GIT 37af997 # Disable annoying gcc warning for "warn_unused_result", see GIT 37af997
CPPFLAGS += -U_FORTIFY_SOURCE CPPFLAGS += -U_FORTIFY_SOURCE
CPPFLAGS += -Ilibite -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE CPPFLAGS += -Ilibite -Ilibuev
CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\" CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\"
CPPFLAGS += -DFINIT_FIFO=\"$(FINIT_FIFO)\" -DFINIT_CONF=\"$(FINIT_CONF)\" CPPFLAGS += -DFINIT_FIFO=\"$(FINIT_FIFO)\" -DFINIT_CONF=\"$(FINIT_CONF)\"
CPPFLAGS += -DFINIT_RCSD=\"$(FINIT_RCSD)\" -DPLUGIN_PATH=\"$(plugindir)\" CPPFLAGS += -DFINIT_RCSD=\"$(FINIT_RCSD)\" -DPLUGIN_PATH=\"$(plugindir)\"
LDFLAGS += -rdynamic -L$(TOPDIR)/libite LDFLAGS += -rdynamic -L$(TOPDIR)/libite
DEPLIBS = libite/libite.so DEPLIBS = libite/libite.so libuev/libuev.a
LDLIBS += -ldl -lite LDLIBS += -ldl -lite
include common.mk include common.mk
export libdir plugindir incdir ROOTDIR CPPFLAGS LDFLAGS LDLIBS export libdir plugindir incdir ROOTDIR CPPFLAGS LDFLAGS LDLIBS
all: $(DEPLIBS) $(EXEC) all: $(DEPLIBS) $(EXEC)
$(MAKE) -C plugins $@ +$(MAKE) -C plugins $@
$(DEPLIBS): Makefile $(DEPLIBS): Makefile
$(MAKE) -C libite all +$(MAKE) -C libite all
+$(MAKE) -C libuev all
$(OBJS): Makefile $(OBJS): Makefile
@@ -133,21 +137,32 @@ uninstall: uninstall-exec uninstall-data uninstall-dev
clean: clean:
-@$(RM) $(OBJS) $(DEPS) $(EXEC) -@$(RM) $(OBJS) $(DEPS) $(EXEC)
$(MAKE) -C libite $@ +$(MAKE) -C plugins $@
$(MAKE) -C plugins $@ +$(MAKE) -C libite $@
+$(MAKE) -C libuev $@
distclean: clean distclean: clean
-@$(RM) $(JUNK) unittest *.o .*.d -@$(RM) $(JUNK) unittest *.o .*.d
$(MAKE) -C libite $@ +$(MAKE) -C plugins $@
$(MAKE) -C plugins $@ +$(MAKE) -C libite $@
+$(MAKE) -C libuev $@
check: check:
$(CHECK) *.c plugins/*.c libite/*.c $(CHECK) *.c plugins/*.c libite/*.c
dist: dist:
@if [ x"$(ARCHTOOL)" = x"" ]; then \
echo "Missing git-archive-all from https://github.com/Kentzo/git-archive-all"; \
exit 1; \
fi
@if [ -e $(ARCHIVEZ) ]; then \
echo "Distribution already exists."; \
exit 1; \
fi
@echo "Building xz tarball of $(PKG) in parent dir..." @echo "Building xz tarball of $(PKG) in parent dir..."
git archive --format=tar --prefix=$(PKG)/ $(VERSION) | xz >../$(ARCHIVE) @$(ARCHTOOL) ../$(ARCHIVE)
@(cd ..; md5sum $(ARCHIVE) | tee $(ARCHIVE).md5) @xz ../$(ARCHIVE)
@md5sum $(ARCHIVEZ) | tee $(ARCHIVEZ).md5
dev: distclean dev: distclean
@echo "Building unstable xz $(DEV) in parent dir..." @echo "Building unstable xz $(DEV) in parent dir..."
-1
View File
@@ -1 +0,0 @@
NEWS.md
-206
View File
@@ -1,206 +0,0 @@
NEWS
====
1.10 (2014-11-27)
-----------------
Major bug fix release.
* Project now relies on static code analysis from Coverity, so this
release contains many serious bug fixes.
* Fix serious file descriptor and memory leaks in the following
functions. In particular the leaks in `run_interactive()` are very
serious since that function is called every time a service is
started and/or restarted! For details, see the GIT log:
* `helpers.c:run()`
* `helpers.c:run_interactive()`
* `helpers.c:set_hostname()`
* `helpers.c:procname_kill()`
* `svc.c:svc_start()`: Fix swapped arguments to dup2() and add
close(fd) to prevent descriptor leak.
* `svc.c:svc_start()`: Fix out of bounds write to local stack
variable, wrote off-by-one outside array.
* Several added checks for return values to `mknod()`, `mkdir()`,
`remove()`, etc.
* Convert to use Markdown for README, NEWS and TODO.
* Serious update to README and slight pruning of finished TODO items.
1.9 (2014-04-21)
----------------
* Bug fixes, code cleanup
* Add support for an include directive to `.conf` files
* Fallback to `/bin/sh` if user forgets tty setting
* Handle `SIGHUP` from service callback properly when switching runlevel
* Initial support for restarting lost services during `norespwan`
* Misc. major (memleak) and minor fixes and additions to `libite/lite.h`
1.8 (2013-06-07)
----------------
* Support for runlevels, with a bootstrap runlevel 'S'
* Support for saving previous and current runlevel to UTMP
* Support for new `finit.conf` commands: run, task, and runlevel
* Support for tty and console commands in `finit.conf`, like services
but for launching multiple getty logins
* New tty plugin to monitor TTYs coming and going, like USB TTYs
* Bugfixes to libite
1.7 (2012-10-08)
----------------
* Show `__FILE__` in `_d()` debug messages, useful for plugins with
similarily named callbacks. Also, only in debug mode anyway
* Make sure to cleanup recorded PID when a service is lost. Required
by service plugins for their callbacks to work.
* Bugfix: Do not `free()` static string in `finit.conf` parser
* Only clear screen when in verbose mode. Maybe this should be removed
altogether?
1.6 (2012-10-06)
----------------
* Skip . and .. in plugin loader and display error on failed plugins
* Support for overriding `/etc/finit.d` with `runparts DIR` in
`finit.conf`
* Revoke support for starting services not starting with a slash.
* Prevent endless restart of non-existing services in `finit.conf`
* Support for sysvinit style startstop scripts in `/etc/finit.d`
* Minor fix to alsa-utils plugin to silence on non-existing cards
1.5 (2012-10-03)
----------------
* Use bootmisc plugin to setup standard FHS 2.3 structure in `/var`
* Added `FLOG_WARN()` syslog macro, for plugins
* Add plugin dependency resolver. Checks `plugin_t` for `.depends`
1.4 (2012-10-02)
----------------
* Fix I/O plugin watcher and load plugins earlier for a new hook
* Start refactoring helpers.c into a libite.so (-lite). This means
other user space applications/daemons can make use of the neat toolbox
available in finit
* Use short-form -s/-w -u to work with BusyBox hwclock as well
* Use RTLD_GLOBAL flag to tell dynamic loader to load dependent .so
files as well. Lets other plugins use global symbols.
* Greatly simplify svc hook for external plugins and cleanup plugin API.
* And more ... see the GIT log for more details.
1.3 (2012-09-28)
----------------
* Cleanup public plugin API a bit and add new pid/pidfile funcs
* Add plugin hook to end of service startup
* Remove finit.h from svc.h, plugins should not need this.
* Move utility macros etc. to helpers.h
* Make `finit.h` daemon internal, only
* Move defines of FIFO, conf and rcS.d to Makefile => correct paths
* Add support for installing required headers in system include dir
* Better support for distributions and packagers with install-exec,
install-data, and install-dev targets in Makefile. Useful if you want
to call targets with different `$DESTDIR`!
* Makefile fixes for installation, paths encoded wrong
* Strip binaries + .so files, support for `$(CROSS)` toolchain strip
* Default install is now to `/sbin/finit` and `/usr/`
* Note change in `$PLUGIN_DIR` environemnt variable to `$plugindir`
1.2 (2012-09-27)
----------------
* Fix installation paths encoded in finit binary
* Update README with section on building and enviroment variables
1.1 (2012-09-27)
----------------
* Build fixes for ARM eabi/uClibc
* Rename signal.[ch]-->sig.[ch] to avoid name clash w/ system headers
1.0 (2012-09-26)
----------------
* New plugin based system for all odd extensions
* New service monitor that restarts services if they die
* New maintainer at GitHub http://github.com/troglobit/finit
* Add standard LICENSE and AUTHORS files
* New focus: embedded systems and small headless servers
0.6 (2010-06-14)
----------------
* don't start consolekit manually, dbus starts it (rtp)
* unmount all filesystems before rebooting
* disable `USE_VAR_RUN_RESOLVCONF` for Mandriva
* unset terminal type in Mandriva before running X
* remove extra sleep in finit-alt before calling services.sh (caio)
0.5 (2008-08-21)
----------------
* add option to start dbus and consolekit before the X server
* finit-alt listens to `/dev/initctl` to work with `reboot(8)` (smurfy)
* write runlevel to utmp, needed by Printerdrake (Pascal Terjan)
* fix ownership of `/var/run/utmp` (reported by Pascal Terjan)
* remove obsolete code to load AGP drivers
* conditional build of `/etc/resolveconf/run` support
* add support to `/var/run/resolvconf` in Mandriva (blino)
O.4 (2008-05-16)
----------------
* default username for finit-alt configurable in Makefile
* create loopback device node in finit-alt (for squashfs)
* add option to use built-in run-parts instead of `/bin/run-parts`
* ignore signal instead of setting to an empty handler (Metalshark)
* handle pam_console permissions in finit-alt for Mandriva
* add services.sh example and nash-hotplug patch for Mandriva
* mount `/proc/bus/usb` in Mandriva
* add runtime debug to finit-alt if finit_debug parameter is specified
* read configuration from `/etc/finit.conf`
* run getty with openvt on the virtual terminal
0.3 (2008-02-23)
----------------
* Change poweroff method to `reboot(RB_POWER_OFF)` (Metalshark)
* Remove duplicate `unionctl()` reimplementation error
* Fix string termination in path creation
* Mount `/var/lock` and `/var/run` as tmpfs
0.2 (2008-02-19)
----------------
* replace` system("touch")` with `touch()` in finit-mod (Metalshark)
* disable `NO_HCTOSYS` by default to match stock Eeepc kernel
* drop `system("rm -f")` to clean `/tmp`, its a fresh mounted tmpfs
* write ACPI sleep state to `/sys/power/state` instead of
`/proc/acpi/sleep` (Metalshark)
* use direct calls to set loopback instead of `system("ifconfig")`
* replace `system("cat")` and `system("dd")` with C implementation
* moved finit-mod and finit-alt helpers to `helpers.c`
* replace `system("echo;cat")` to draw shutdown splash with C calls
0.1 (2008-02-14)
----------------
* initial release
+241 -163
View File
@@ -1,36 +1,57 @@
README Finit | Fast & Extensible init for Linux
====== ========================================
[![Build Status](https://travis-ci.org/troglobit/finit.png?branch=master)](https://travis-ci.org/troglobit/finit) [![Build Status](https://travis-ci.org/troglobit/finit.png?branch=master)](https://travis-ci.org/troglobit/finit)
[![Coverity Scan Status](https://scan.coverity.com/projects/3545/badge.svg)](https://scan.coverity.com/projects/3545) [![Coverity Scan Status](https://scan.coverity.com/projects/3545/badge.svg)](https://scan.coverity.com/projects/3545)
![Original Finit homepage image](images/finit.jpg "Finit in action!")
Table of Contents
-----------------
* [Introduction](#introduction)
* [Features](#features)
* [/etc/finit.conf](#etcfinitconf)
* [/etc/finit.d](#etcfinitd)
* [Bootstrap](#bootstrap)
* [Runlevels](#runlevels)
* [Hooks, Callbacks & Plugins](#hooks-callbacks--plugins)
* [Rebooting and Halting](#rebooting-and-halting)
* [Building](#building)
* [Running](#running)
* [Debugging](#debugging)
* [Origin & References](#origin--references)
Introduction
------------
Init is the first process to run once a UNIX kernel has booted, it Init is the first process to run once a UNIX kernel has booted, it
always has PID 1 and is responsible for starting up the rest of the always has PID 1 and is responsible for starting up the rest of the
system. Finit is a very small plugin based init with built in system. Finit is plugin-based with built in [process supervision][1]
[process supervision](https://en.wikipedia.org/wiki/Process_supervision) similar to that of D.J. Bernstein's [daemontools][2] and Gerrit Pape's
similar to that of D.J. Bernstein's [runit][3]. The main focus of Finit is on small and embedded GNU/Linux
[daemontools](http://cr.yp.to/daemontools.html) and Gerrit Pape's systems, yet fully functional on standard server and desktop
[runit](http://smarden.org/runit/). Its focus is on small and embedded installations as well.
GNU/Linux systems, although fully functional on standard server and
desktop installations.
Finit is fast because it is "scripted" with C and starts services in Traditional [SysV init][4] style systems are scripted. For low-resource
parallel. Services are supervised and automatically restarted if they embedded systems this can be quite resource intensive and cause longer
fail. Services can have callbacks that are called before a service is boot times. Finit is optimized to reduce context switches and forking
(re)started. For instance, before attempting to start a heavily of processes to provide a very basic bootstrap written entirely in C.
resource intensive service like IPsec or OpenVPN, a callback can check Hence, there is no `/etc/init.d/rcS` script, or similar, but instead a
if the outbound interface is up and has an IP address, or just check if human-readable `/etc/finit.conf`. This file details what kernel modules
the service is disabled -- much like what a SysV init start script to load, programs to run and daemons to supervise.
usually does.
To extend finit with new functionality, hooks can be added at certain The command line arguments given in `/etc/finit.conf` to each service
points in the boot process that execute in sequence, which is useful for provide a default. Each service can register callbacks, using plugins,
certain satisfying preconditions or for synchronization purposes. One to override and modify the behavior to suit the current runlevel and
can also create plugins to functionality to suit your own needs, the system configuration. For instance, before starting a heavily resource
initctl compatibility plugin that comes with finit is one such plugin. intensive service like IPsec or OpenVPN, a callback can check if the
outbound interface is up and has an IP address, or just check if the
service is disabled -- much like what a SysV init start script usually
does.
Finit is not only fast, it's arguably one of the easiest to get started See [TroglOS][9] for an example of how to boot a small embedded system
with. A complete system can be booted with one simple configuration with Finit.
file, `/etc/finit.conf`, see below for syntax.
Features Features
@@ -42,20 +63,27 @@ Start, monitor and restart services if they fail.
**Runlevels** **Runlevels**
Finit supports standard runlevels if you want, but you don't need them Runlevels is optional in Finit, but support for [SysV runlevels][5] is
for simple installations. available if needed. All services in runlevel S(1) are started first,
followed by the desired run-time runlevel. Runlevel S can be started in
sequence by using `run [S] cmd`. Changing runlevels at runtime is done
like any other init, e.g. <kbd>init 4</kbd>.
**Plugins** **Plugins**
Extend and modify finit behavior. See examples in plugins/ directory. Finit plugins can be either *boot hooks* into different stages of the
boot process or *service callbacks*, or both. A basic set of plugins
that extend and modify the basic behavior are bundled. See examples in
the `plugins/` directory.
Plugin capabilities: Plugin capabilities:
* Service callbacks — modify service arguments, run/restart/stop * Service callbacks -- modify service arguments, run/restart/stop
* Task/Run callbacks — a one-shot commands, executed in sequence * Task/Run callbacks -- a one-shot commands, executed in sequence
* Hooks — hook into the boot at predefined points to extend finit * Hooks -- hook into the boot at predefined points to extend finit
* I/O — listen to external events and control finit behavior/services * I/O -- listen to external events and control finit behavior/services
Extensions and functionality not purely related to what an /sbin/init Extensions and functionality not purely related to what an `/sbin/init`
needs to start a system are available as a set of plugins that either needs to start a system are available as a set of plugins that either
hook into the boot process or respond to various I/O. hook into the boot process or respond to various I/O.
@@ -63,77 +91,76 @@ hook into the boot process or respond to various I/O.
/etc/finit.conf /etc/finit.conf
--------------- ---------------
Contrary to most other script based init alternatives Contrary to most other script based init alternatives ([SysV init][4],
([SysV init](https://en.wikipedia.org/wiki/Init), [upstart][6], [systemd][7], [OpenRC][8], etc.) Finit reads its entire
[upstart](http://upstart.ubuntu.com/), configuration from `/etc/finit.conf`.
[systemd](http://www.freedesktop.org/wiki/Software/systemd/),
[OpenRC](http://www.gentoo.org/proj/en/base/openrc/) and the likes)
finit reads its configuration from `/etc/finit.conf`. Syntax:
* `check <DEV>` Syntax:
Run fsck on a file system before mounting it * `check <DEV>`
* `module <MODULE>` Run fsck on a file system before mounting it
Load a kernel module, with optional arguments * `module <MODULE>`
* `network <PATH>` Load a kernel module, with optional arguments
Script or program to bring up networking, with optional arguments * `network <PATH>`
* `runlevel <N>` Script or program to bring up networking, with optional arguments
N is the runlevel number 1-9, where 6 is reserved for reboot. * `runlevel <N>`
Default is 2. N is the runlevel number 1-9, where 6 is reserved for reboot.
* `run [LVLS] /path/to/cmd ARGS -- Optional description` Default is 2.
One-shot command to run in sequence when entering a runlevel, with * `run [LVLS] /path/to/cmd ARGS -- Optional description`
optional arguments and description. This command is guaranteed to
be completed before running the next command.
* `task LVLS] /path/to/cmd ARGS -- Optional description` One-shot command to run in sequence when entering a runlevel, with
optional arguments and description. This command is guaranteed to be
completed before running the next command.
One-shot like 'run', but starts in parallel with the next command * `task [LVLS] /path/to/cmd ARGS -- Optional description`
* `service [LVLS] /path/to/daemon ARGS -- Optional description` One-shot like 'run', but starts in parallel with the next command
Service, or daemon, to be monitored and automatically restarted if * `service [LVLS] /path/to/daemon ARGS -- Optional description`
it exits prematurely. Please note that you often need to provide
a --foreground or --no-background argument to most daemons to
prevent them from forking off to the background.
* `runparts <PATH>` Service, or daemon, to be monitored and automatically restarted if it
exits prematurely. Please note that you often need to provide a
--foreground or --no-background argument to most daemons to prevent
them from forking off to the background.
Call run-parts(8) on a directory other than default ``/etc/finit.d`` * `runparts <PATH>`
* `include <CONF>` Call run-parts(8) on a directory other than default ``/etc/finit.d``
Include another configuration file, ``/etc/finit.d``, or runparts * `include <CONF>`
path is prepended to file if the file is not found or an absolute
path is not given
* `tty [LVLS] <DEV | /bin/sh>` Include another configuration file, ``/etc/finit.d``, or runparts path
is prepended to file if the file is not found or an absolute path is
not given
Start a getty on the given TTY device, in the given runlevels. When * `tty [LVLS] <DEV | /bin/sh>`
no tty setting is given in `finit.conf`, or if `/bin/sh` is given as
argument instead of a device path, a single shell is started on the
default console. Useful for really bare-bones systems
See `finit.h` for the `#define GETTY` that is called, along with the Start a getty on the given TTY device, in the given runlevels. When
default baud rate. no tty setting is given in `finit.conf`, or if `/bin/sh` is given as
argument instead of a device path, a single shell is started on the
default console. Useful for really bare-bones systems
* `console <DEV>` See `finit.h` for the `#define GETTY` that is called, along with the
default baud rate.
Some embedded systems have a dedicated console port. This command * `console <DEV>`
tells finit to not start getty, but instead print a friendly message
and wait for the user to activate the console with a key press before
starting getty.
When running `make install` no default `/etc/finit.conf` will be Some embedded systems have a dedicated console port. This command
provided since the system requirements differ too much. Try out the tells finit to not start getty, but instead print a friendly message
and wait for the user to activate the console with a key press before
starting getty.
When running <kbd>make install</kbd> no default `/etc/finit.conf` will
be installed since system requirements differ too much. Try out the
Debian 6.0 example `/usr/share/doc/finit/finit.conf` configuration that Debian 6.0 example `/usr/share/doc/finit/finit.conf` configuration that
is capable of service monitoring SSH, sysklogd, gdm and a console getty! is capable of service monitoring SSH, sysklogd, gdm and a console getty!
@@ -142,13 +169,55 @@ is capable of service monitoring SSH, sysklogd, gdm and a console getty!
------------ ------------
At the end of the boot, when networking and all services are up, finit At the end of the boot, when networking and all services are up, finit
calls its built-in run-parts(8) on the `/etc/finit.d/` directory, if calls its built-in run-parts(8) on the `/etc/finit.d/` directory, if it
it exists. Similar to how the `/ec/rc.local` file works in most other exists. Similar to how the `/ec/rc.local` file works in most other init
init daemons, only finit runs a directory of scripts. This replaces the daemons, only finit runs a directory of scripts. This replaces the
earlier support for a `/usr/sbin/services.sh` script in the original earlier support for a `/usr/sbin/services.sh` script in the original
finit. finit.
Bootstrap
---------
1. Setup `/dev`
2. Parse `/etc/finit.conf`
3. Load all `.so` plugins
4. Remount/Pivot `/` to get R+W
5. Call 1st level hooks, `HOOK_ROOTFS_UP`
6. Mount `/etc/fstab` and swap, if available
7. Cleanup stale files from `/tmp/*` et al
8. Enable SysV init signals
9. Call 2nd level hooks, `HOOK_BASEFS_UP`
10. Start all 'S' runlevel tasks and services
11. Setup `/etc/sysctl.conf`
12. Setup hostname and loopback
13. Call `network` script, if set in `/etc/finit.conf`
14. Call 3rd level hooks, `HOOK_NETWORK_UP`
15. Switch to active runlevel, as set in `/etc/finit.conf`, default 2.
Here is where the rest of all tasks and services are started.
16. Call 4th level hooks, `HOOK_SVC_UP`
17. Run-parts in `/etc/finit.d`, if any
18. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
19. Start TTYs defined in `/etc/finit.conf`, or rescue on `/dev/console`
20. Enter main monitor loop
In (10) and (15) tasks and services defined in `/etc/finit.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 file with only
`run` statments.
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.
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.
Runlevels Runlevels
--------- ---------
@@ -158,8 +227,9 @@ commands and TTYs listed without a set of runlevels get a default set
`[234]` assigned. The default runlevel after boot is 2. `[234]` assigned. The default runlevel after boot is 2.
To specify an allowed set of runlevels for a `service`, `run` command, `task`, To specify an allowed set of runlevels for a `service`, `run` command, `task`,
or `tty`, add `[NNN]` to it in your `finit.conf`, like this: or `tty`, add `[NNN]` to it in your `/etc/finit.conf`, like this:
service [S12345] /sbin/syslogd -n -x -- System log daemon
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
task [S] /etc/init.d/kbd start -- Preparing console task [S] /etc/init.d/kbd start -- Preparing console
service [S12345] /sbin/klogd -n -x -- Kernel log daemon service [S12345] /sbin/klogd -n -x -- Kernel log daemon
@@ -170,21 +240,19 @@ or `tty`, add `[NNN]` to it in your `finit.conf`, like this:
tty [2] /dev/tty5 tty [2] /dev/tty5
tty [2] /dev/tty6 tty [2] /dev/tty6
In this example acpid is started once at bootstrap using a conventional In this example syslogd is first started, in parallel, and then acpid is
SysV init script. Here the run command was used, meaning the following called using a conventional SysV init script. It is called with the run
task command is not run until the init script has fully completed. Then command, meaning the following task command to start the kbd script is
the keyboard setup script is called in parallel with spawning klogd as not called until the acpid init script has fully completed. Then the
a monitored service. keyboard setup script is called in parallel with klogd as a monitored
service.
Tasks and services are started in parallel, while run commands are run Again, tasks and services are started in parallel, while run commands
in the order listed and subsequent commands are not started until a run are called in the order listed and subsequent commands are not started
command has completed. until a run command has completed.
Existing finit.conf files that lack runlevel setting will get a default
runlevel assigned, `[234]`.
Switching between runlevels can be done by calling init with a single Switching between runlevels can be done by calling init with a single
argument, e.g., `init 5` switches to runlevel 5. argument, e.g. <kbd>init 5</kbd> switches to runlevel 5.
Hooks, Callbacks & Plugins Hooks, Callbacks & Plugins
@@ -196,27 +264,26 @@ however come with support for hooks, service callbacks and plugins that
can used to extend finit with. For your convenience a set of *optional* can used to extend finit with. For your convenience a set of *optional*
plugins are available: plugins are available:
* *alsa-utils.so*: Restore and save ALSA sound settings on * *alsa-utils.so*: Restore and save ALSA sound settings on
startup/shutdown. startup/shutdown.
* *bootmisc.so*: Setup necessary files for UTMP, tracking logins * *bootmisc.so*: Setup necessary files for UTMP, tracks logins at boot.
at boot.
* *dbus.so*: Setup and start system message bus, D-Bus, at boot. * *dbus.so*: Setup and start system message bus, D-Bus, at boot.
* *hwclock.so*: Restore and save system clock from/to RTC on * *hwclock.so*: Restore and save system clock from/to RTC on
startup/shutdown. startup/shutdown.
* *initctl.so*: Extends finit with a traditional initctl functionality. * *initctl.so*: Extends finit with a traditional initctl functionality.
* *resolvconf.so*: Setup necessary files for resolvconf at startup. * *resolvconf.so*: Setup necessary files for resolvconf at startup.
* *tty.so*: Watches /dev, using inotify, for new device nodes (TTY's) to * *tty.so*: Watches /dev, using inotify, for new device nodes (TTY's) to
start/stop getty consoles on them on demand. start/stop getty consoles on them on demand.
* *urandom.so*: Setup random seed at startup. * *urandom.so*: Setup random seed at startup.
* *x11-common.so*: Setup necessary files for X-Window. * *x11-common.so*: Setup necessary files for X-Window.
Usually you want to hook into the boot process once, simple hook plugins Usually you want to hook into the boot process once, simple hook plugins
like `bootmisc.so` are great for that purpose. They are called at each like `bootmisc.so` are great for that purpose. They are called at each
@@ -224,22 +291,22 @@ hook point in the boot process, useful to insert some pre-bootstrap
mechanisms, like generating configuration files, restoring HW device mechanisms, like generating configuration files, restoring HW device
state, etc. Available hook points are: state, etc. Available hook points are:
* `HOOK_ROOTFS_UP`: When `finit.conf` has been read and `/` has is * `HOOK_ROOTFS_UP`: When `finit.conf` has been read and `/` has is
mounted -- very early mounted -- very early
* `HOOK_BASEFS_UP`: All of `/etc/fstab` is mounted, swap is available * `HOOK_BASEFS_UP`: All of `/etc/fstab` is mounted, swap is available
and default init signals are setup and default init signals are setup
* `HOOK_NETWORK_UP`: System bootstrap, runlevel S, has completed and * `HOOK_NETWORK_UP`: System bootstrap, runlevel S, has completed and
networking is up (`lo` is up and the `network` script has run) networking is up (`lo` is up and the `network` script has run)
* `HOOK_SVC_UP`: All services in the active runlevel has been launched * `HOOK_SVC_UP`: All services in the active runlevel has been launched
* `HOOK_SYSTEM_UP`: All services *and* everything in `/etc/finit.d` * `HOOK_SYSTEM_UP`: All services *and* everything in `/etc/finit.d`
has been launched has been launched
* `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all * `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all
services are sent `SIGTERM` services are sent `SIGTERM`
Plugins like `initctl.so` and `tty.so` extend finit by acting on events, Plugins like `initctl.so` and `tty.so` extend finit by acting on events,
they are called I/O plugins and are called from the finit main loop when they are called I/O plugins and are called from the finit main loop when
@@ -275,56 +342,58 @@ alter the behavior of finit.
The following environment variables are checked by the makefiles and control The following environment variables are checked by the makefiles and control
what is built and where resulting binaries are installed. what is built and where resulting binaries are installed.
* `ROOTDIR=`: Top directory for building complete system, used in pretty * `ROOTDIR=`: Top directory for building complete system, used in pretty
printing. printing.
* `VERSION=`: Defaults to the currently released version of finit, * `VERSION=`: Defaults to the currently released version of finit,
e.g., 1.3 but can be overridden by packagers using this variable to e.g., 1.3 but can be overridden by packagers using this variable to
add a suffix or completely alter the version. add a suffix or completely alter the version.
* `CFLAGS=`: Default `CFLAGS` are inherited from the build environment. * `CFLAGS=`: Default `CFLAGS` are inherited from the environment.
* `CPPFLAGS=`: Default `CPPFLAGS` are inherited from the build * `CPPFLAGS=`: Default `CPPFLAGS` are inherited from the environment.
environment.
* `LDFLAGS=`: Default `LDFLAGS` are inherited from the build * `LDFLAGS=`: Default `LDFLAGS` are inherited from the environment.
environment.
* `LDLIBS=`: Default `LIBLIBS` are inherited from the build environment. * `LDLIBS=`: Default `LIBLIBS` are inherited from the environment.
* `prefix=`: Base prefix path for all files, except `sbinbdir` and * `prefix=`: Base prefix path for all files, except `sbinbdir` and
`sysconfdir`. Used in concert with the `DESTDIR` variable. `sysconfdir`. Used in concert with the `DESTDIR` variable.
Defaults to `/usr`. Defaults to `/usr`.
* `sbindir=`: Path to where resulting binaries should install to. Used * `sbindir=`: Path to where resulting binaries should install to. Used
in concert with the `DESTDIR` variable. in concert with the `DESTDIR` variable.
Defaults to `/sbin`. Defaults to `/sbin`.
* `sysconfdir=`: Path to where finit configuration files should install * `sysconfdir=`: Path to where finit configuration files should install
to. Used in concert with the `DESTDIR` variable. to. Used in concert with the `DESTDIR` variable.
Defaults to `/etc`, but is currently unused. Defaults to `/etc`, but is currently unused.
* `PLUGINS=`: List of stock finit plugins to build and install. * `PLUGINS=`: List of stock finit plugins to build and install.
* `plugindir=`: Absolute path to where finit should look for dynamically * `plugindir=`: Absolute path to where finit should look for dynamically
loadable plugins at runtime. At installation prepended by `DESTDIR` loadable plugins at runtime. At installation prepended by `DESTDIR`
and `prefix`. and `prefix`.
Defaults to `/lib/finit/plugins`. Defaults to `/lib/finit/plugins`.
* `DESTDIR=`: Used by packagers and distributions when building a * `DESTDIR=`: Used by packagers and distributions when building a
relocatable bundle of files. Always prepended to the `prefix` relocatable bundle of files. Always prepended to the `prefix`
destination directory. destination directory.
**Example** **Example**
$ tar xfJ finit-1.3.tar.xz First, unpack the archive:
$ PLUGINS="initctl.so hwclock.so" DESTDIR=/tmp/finit/dst \
make -C finit-1.3/ clean install <kbd>$ tar xfJ finit-1.3.tar.xz; cd finit-1.3/</kbd>
make: Entering directory `/home/troglobit/finit-1.3'
Then build and install:
<kbd>$ PLUGINS="initctl.so hwclock.so" DESTDIR=/tmp/finit make install</kbd>
CC finit.o CC finit.o
CC conf.o CC conf.o
CC helpers.o CC helpers.o
@@ -337,17 +406,14 @@ what is built and where resulting binaries are installed.
PLUGIN plugins/initctl.so PLUGIN plugins/initctl.so
CC plugins/hwclock.o CC plugins/hwclock.o
PLUGIN plugins/hwclock.so PLUGIN plugins/hwclock.so
INSTALL /tmp/finit/dst/sbin/finit INSTALL /tmp/finit/sbin/finit
INSTALL /tmp/finit/dst/lib/finit/plugins/initctl.so INSTALL /tmp/finit/lib/finit/plugins/initctl.so
INSTALL /tmp/finit/dst/lib/finit/plugins/hwclock.so INSTALL /tmp/finit/lib/finit/plugins/hwclock.so
make: Leaving directory `/home/troglobit/finit-1.3'
In this example the In this example the [finit-1.3.tar.xz][10] archive is unpacked to the
[finit-1.3.tar.xz](ftp://troglobit.com/finit/finit-1.3.tar.xz) user's home directory, built and installed to a temporary staging
archive is unpacked to the user's home directory, built and directory. The environment variables `DESTDIR` and `PLUGINS` are
installed to a temporary staging directory. The environment changed to suit this particular build.
variables `DESTDIR` and `PLUGINS` are changed to suit this
particular build.
Running Running
@@ -363,6 +429,8 @@ give the kernel the following extra command line:
init=/sbin/finit init=/sbin/finit
![Finit starting Debian 6.0](images/finit-screenshot.jpg "Finit screenshot")
Debugging Debugging
--------- ---------
@@ -374,8 +442,8 @@ enable trace messages. A console getty is always started, see the file
init=/sbin/finit --debug init=/sbin/finit --debug
Credits & Contact Origin & References
----------------- -------------------
This is the continuation of the [original finit](http://helllabs.org/finit/) This is the continuation of the [original finit](http://helllabs.org/finit/)
by [Claudio Matsuoka](https://github.com/cmatsuoka), which in turn was by [Claudio Matsuoka](https://github.com/cmatsuoka), which in turn was
@@ -388,3 +456,13 @@ Finit is currently being developed and maintained by
[GitHub](http://github.com/troglobit/finit). Please file bug reports, clone it, [GitHub](http://github.com/troglobit/finit). Please file bug reports, clone it,
or send pull requests for bug fixes and proposed extensions. or send pull requests for bug fixes and proposed extensions.
[1]: https://en.wikipedia.org/wiki/Process_supervision
[2]: http://cr.yp.to/daemontools.html
[3]: http://smarden.org/runit/
[4]: http://en.wikipedia.org/wiki/Init
[5]: http://en.wikipedia.org/wiki/Runlevel
[6]: http://upstart.ubuntu.com/
[7]: http://www.freedesktop.org/wiki/Software/systemd/
[8]: http://www.gentoo.org/proj/en/base/openrc/
[9]: https://github.com/troglobit/troglos
[10]: ftp://troglobit.com/finit/finit-1.3.tar.xz
+132 -65
View File
@@ -1,98 +1,165 @@
TODO Goals of Finit
==== ==============
Unsorted TODO list of features and points of investigation that could be The intent of finit is to monitor not just processes, but to supervise
useful for improving finit. But what is an improvement to finit? Well, an entire system and the behavior of certain processes that declare
similiar to launchd, the goal of finit is to be a FAST replacement for: themselves to be finit compliant. Similar to launchd, the goal of
finit is to be a replacement for:
* init * init
* inetd * inetd
* crond * crond
* watchdogd * watchdogd
A small and simple replacement, primarily for embedded systems, with a
very low dependency on external packages.
General
-------
* Add support for `init <q | reload-configuration>` and `SIGHUP` to
have finit reload its `finit.conf`, but also
* Add support for inotify to automatically reload `finit.conf`
* Implement `initctl stop|start|restart|reload|status <SVC>` and
`service <SVC> stop|start|restart|reload|status` on top
* Add PRE and POST hooks for when switching between runlevels
* Add support for `init -v,--version | version`
* Cleanup move sources from top-level directory to `src/` and `include/`
* Make sure to install `queue.h` to `$(PREFIX)/include/finit/queue.h`
* Move `finit.conf` "check" command to plugin which checks `/etc/fstab`
instead. This is the de-facto practice. But keep the check command
for really low-end systems w/o `/etc/fstab`.
Init
----
Finit in itself is not SysV Init compatible, it doesn't use `/etc/rc.d`
and `/etc/inet.d` scripts to boot the system. However, a plausible way
to achieve compatibility would be to add a plugin to finit which reads
`/etc/inittab` to be able to start standard Linux systems.
The main goal is to be FAST. Secondary goals are to be: small, simple
and with a very low dependency on external packages.
Inetd Inetd
----- -----
Simple way of running Internet services on demand, like the old inetd: Simple way of running Internet services on demand, like the old inetd:
inetd SVC [RUNLVL] /path/to/daemon args -- description inetd PROTO/SERVICE <wait|nowait> [@USER[:GROUP]] /path/to/daemon args
Example: Examples:
# Inetd services, launched on demand # Inetd services, launched on demand
inetd ssh [2345] /usr/sbin/sshd -i -- SSH Daemon inetd tcp/ssh nowait [2345] @root:root /usr/sbin/sshd -i
In keeping with the finit tradition, an optional callback can be setup In keeping with the finit tradition, an optional callback can be setup
to each inetd service. When a client connects the finit will call the to each inetd service. When a client connects the finit will call the
callback with a `struct in_pktinfo` argument which the callback then can callback with a `struct in_pktinfo` argument which the callback then can
allowed or deny. allowed or deny.
Alternatively, borrowing from TCP wrappers by Wietse Venema, a set of
`allow` and `deny` directives can be added to `finit.conf` to control
inetd services. It could be what IP addreses, networks or interfaces
are allowed to connect to the given inetd services. To start with the
easiest (and what we need for WeOS at Westermo) is allow/deny per iface.
Priority # Disable access to SSH
deny ssh all
# Allow SSH connections originating from eth0
allow ssh eth0
Another option, to further extend the Inetd capabilities, is a separate
`finetd.conf` to list services. This would be beneficial when running
an SSH service on different ports on different interfaces:
# Run SSH on port 22 on all interfaces except upstream
tcp ssh {
listen = *, !wan0
exec = dropbear -i
}
# Run SSH on non-standard port 222 for upstream interface
tcp 222 {
listen = wan0
exec = dropbear -i
wait = yes
}
# Run TFTP service on all interfaces except upstream interface
udp tftp {
listen = *, !wan0
exec = uftpd -i -t
user = root
}
Syntax very similar to [xinetd](http://en.wikipedia.org/wiki/Xinetd)
Crond
-----
Requirements are quite rudimentary, basic cron functionality, mainly
system-level timed periodic tasks:
* Periodically run a task, in a matching runlevel
* Optionally run as non-root (`crontab -e` as operator)
Proposed syntax:
# Crontab
cron @YY-mm-ddTHH:MM [LVLS] /path/to/cmd [ARGS] -- Optional descr
# One-shot 'at' command
at @YY-mm-ddTHH:MM [LVLS] /path/to/cmd [ARGS] -- Optional descr
Notice the ISO date in notation. The runlevels is extra filtering
sugar. E.g., if cron service is only allowed in runlevels two or three
it will not start if system currently is in runlevel four.
To run a command as another user the `.conf` file must have a that
owner. E.g., `/etc/finit.d/extra.conf` may be owned by operator and
only hold `cron ...` lines.
What would be extremely useful is if `initctl`, or a homegrown `at`,
could support the basic functionality of the `at` command directly from
the shell -- that way setting up one-time jobs would not entail
re-reading `/etc/finit.conf`
Watchdog
-------- --------
The intent of finit is to monitor not just processes, but also to Support for monitoring the health of the system and its processes.
be able to supervise the entire system and the behavior of certain
processes that declare themselves to be finit compliant.
* Integrate the ingenious libev to handle all events: signals, polling * Add support for a `/dev/watchdog` plugin to replace `watchdogd`
fd's, etc. Because "Event driven software improves concurrency" -- * Integrate system supervisor to optionally reboot the system when a
Dave Zarzycki, Apple. process stops responding, or when a respawn limit has been reached,
as well as when system load gets too high.
See the [launchd video](http://www.youtube.com/watch?v=cD_s6Fjdri8) * API for processes to register with the watchdog.
for more info! - Deeper monitoring of a process main loop
- If a process is not heard from within its subscribed period time
* Add support for a /dev/watchdog plugin to replace watchdogd reboot system or restart process.
* Separate `/etc/watchdog.conf` configuration file, or a perhaps
* Integrate watchdog plugin with process/system supervisor to optionally support for `/etc/finit.d/PLUGIN.conf`?
reboot the system when a process stops responding, or when a respawn * Support enable/disable watchdog features:
limit has been reached, as well as when system load gets too high. - Supervise processes,
- CPU loadavg,
- Watch for file descriptor leaks,
Configuration - etc.
-------------
* Add support for `init <q | reload-configuration>` and `SIGHUP` to
have finit reload its `finit.conf`, but also
* Add support for inotify to automatically reload `finit.conf`
Runlevels
---------
* Implement `initctl stop|start|restart|reload|status <SVC>` and
`service <SVC> stop|start|restart|reload|status` on top
* Add PRE and POST hooks for when switching between runlevels
Miscellaneous
-------------
* Add support for `init -v,--version | version`
* Cleanup move sources from top-level directory to `src/` and `include/`
* Make sure to install `queue.h` to `$(PREFIX)/include/finit/queue.h`
* Move `finit.conf` "check" command to plugin which checks `/etc/fstab`
instead. This is the de-facto practice. But keep the check command
for really low-end systems w/o `/etc/fstab`.
Documentation Documentation
------------- -------------
* Write man pages for finit and `finit.conf`, steal from the excellent * Write man pages for finit and `finit.conf`, steal from the excellent
`pimd` man pages ... `pimd` man pages ...
* Update Debian `finit.conf` example with runlevels, `tty/console` and * Update Debian `finit.conf` example with runlevels, `tty/console` and
dependency handling dependency handling for Debian 8 (the dreaded systemd release).
Investigation Investigation
------------- -------------
* [FHS changes](http://askubuntu.com/questions/57297/why-has-var-run-been-migrated-to-run) * [FHS changes](http://askubuntu.com/questions/57297/why-has-var-run-been-migrated-to-run)
affecting runtime status, plugins, etc. affecting runtime status, plugins, etc.
+13 -24
View File
@@ -131,27 +131,6 @@ static int client(int argc, char *argv[])
return 0; return 0;
} }
static int run_loop(void)
{
int delay = DELAY_TTY ?: 1;
_d("Entering main loop ...");
while (1) {
svc_monitor();
plugin_monitor();
/* Delayed start of TTYs to let the system stabilize
* after switching runlevels. */
if (delay) {
if (--delay == 0)
tty_runlevel(runlevel);
continue;
}
}
return 0;
}
static void banner(void) static void banner(void)
{ {
delline(); delline();
@@ -160,6 +139,8 @@ static void banner(void)
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
uev_ctx_t ctx;
if (getpid() != 1) if (getpid() != 1)
return client(argc, argv); return client(argc, argv);
@@ -173,6 +154,11 @@ int main(int argc, char* argv[])
*/ */
sig_init(); sig_init();
/*
* Initalize event context.
*/
uev_init(&ctx);
/* /*
* Mount base file system, kernel is assumed to run devtmpfs for /dev * Mount base file system, kernel is assumed to run devtmpfs for /dev
*/ */
@@ -208,7 +194,7 @@ int main(int argc, char* argv[])
* hook on to. * hook on to.
*/ */
print_desc("Loading plugins", NULL); print_desc("Loading plugins", NULL);
print_result(plugin_load_all(PLUGIN_PATH)); print_result(plugin_load_all(&ctx, PLUGIN_PATH));
/* /*
* Mount filesystems * Mount filesystems
@@ -232,7 +218,7 @@ int main(int argc, char* argv[])
run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories"); run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories");
/* Base FS up, enable standard SysV init signals */ /* Base FS up, enable standard SysV init signals */
sig_setup(); sig_setup(&ctx);
_d("Base FS up, calling hooks ..."); _d("Base FS up, calling hooks ...");
plugin_run_hooks(HOOK_BASEFS_UP); plugin_run_hooks(HOOK_BASEFS_UP);
@@ -279,10 +265,13 @@ int main(int argc, char* argv[])
/* Hooks that should run at the very end */ /* Hooks that should run at the very end */
plugin_run_hooks(HOOK_SYSTEM_UP); plugin_run_hooks(HOOK_SYSTEM_UP);
/* Start TTYs */
tty_runlevel(runlevel);
/* /*
* Enter main loop to monior /dev/initctl and services * Enter main loop to monior /dev/initctl and services
*/ */
return run_loop(); return uev_run(&ctx, 0);
} }
/** /**
-3
View File
@@ -65,9 +65,6 @@
# define DEFHOST "noname" # define DEFHOST "noname"
#endif #endif
/* Delay start of GETTY at boot. Must be > 0 */
#define DELAY_TTY 2
#define CMD_SIZE 256 #define CMD_SIZE 256
#define LINE_SIZE 1024 #define LINE_SIZE 1024
#define BUF_SIZE 4096 #define BUF_SIZE 4096
+14 -13
View File
@@ -446,7 +446,7 @@ int run(char *cmd)
return 1; return 1;
} }
pid = fork(); pid = vfork();
if (0 == pid) { if (0 == pid) {
int i; int i;
FILE *fp; FILE *fp;
@@ -466,7 +466,9 @@ int run(char *cmd)
dup2(fd, STDERR_FILENO); dup2(fd, STDERR_FILENO);
} }
sig_unblock();
execvp(args[0], args); execvp(args[0], args);
_exit(1); /* Only if execv() fails. */ _exit(1); /* Only if execv() fails. */
} else if (-1 == pid) { } else if (-1 == pid) {
_pe("%s", args[0]); _pe("%s", args[0]);
@@ -563,13 +565,11 @@ int run_interactive(char *cmd, char *fmt, ...)
pid_t run_getty(char *cmd, char *args[], int console) pid_t run_getty(char *cmd, char *args[], int console)
{ {
pid_t pid = fork(); pid_t pid = vfork();
if (!pid) { if (!pid) {
int i, fd; int fd;
char c; char c;
sigset_t nmask;
struct sigaction sa;
if (console) { if (console) {
/* Detach from initial controlling TTY */ /* Detach from initial controlling TTY */
@@ -590,13 +590,13 @@ pid_t run_getty(char *cmd, char *args[], int console)
prctl(PR_SET_NAME, "console", 0, 0, 0); prctl(PR_SET_NAME, "console", 0, 0, 0);
} }
sigemptyset(&nmask);
sigaddset(&nmask, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &nmask, NULL);
/* Reset signal handlers that were set by the parent process */ sig_unblock();
for (i = 1; i < NSIG; i++)
DFLSIG(sa, i, 0); setsid();
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
_pe("Failed TIOCSCTTY");
while (!fexist(SYNC_SHUTDOWN)) { while (!fexist(SYNC_SHUTDOWN)) {
static const char msg[] = "\nPlease press Enter to activate this console."; static const char msg[] = "\nPlease press Enter to activate this console.";
@@ -629,7 +629,7 @@ pid_t run_getty(char *cmd, char *args[], int console)
int run_parts(char *dir, char *cmd) int run_parts(char *dir, char *cmd)
{ {
struct dirent **e; struct dirent **e;
int i, num; volatile int i, num;
num = scandir(dir, &e, NULL, alphasort); num = scandir(dir, &e, NULL, alphasort);
if (num < 0) { if (num < 0) {
@@ -669,9 +669,10 @@ int run_parts(char *dir, char *cmd)
} }
args[j++] = NULL; args[j++] = NULL;
pid = fork(); pid = vfork();
if (!pid) { if (!pid) {
_d("Calling %s ...", path); _d("Calling %s ...", path);
sig_unblock();
execv(path, args); execv(path, args);
exit(0); exit(0);
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Submodule
+1
Submodule libuev added at 5c7a6f1163
+15 -57
View File
@@ -36,10 +36,8 @@
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd >= 0) #define is_io_plugin(p) ((p)->io.cb && (p)->io.fd >= 0)
static char *plugpath = NULL; /* Set by first load. */ static char *plugpath = NULL; /* Set by first load. */
static size_t num_fds = 0; static TAILQ_HEAD(, plugin) plugins = TAILQ_HEAD_INITIALIZER(plugins);
static struct pollfd fds[MAX_NUM_FDS];
static TAILQ_HEAD(, plugin) plugins = TAILQ_HEAD_INITIALIZER(plugins);
static void check_plugin_depends(plugin_t *plugin); static void check_plugin_depends(plugin_t *plugin);
@@ -69,15 +67,8 @@ int plugin_register(plugin_t *plugin)
check_plugin_depends(plugin); check_plugin_depends(plugin);
if (is_io_plugin(plugin)) { if (is_io_plugin(plugin))
if (num_fds + 1 >= MAX_NUM_FDS) {
num_fds = MAX_NUM_SVC;
errno = ENOMEM;
return 1;
}
num_fds++;
inuse++; inuse++;
}
if (plugin->svc.cb) { if (plugin->svc.cb) {
svc_t *svc = svc_find(plugin->name); svc_t *svc = svc_find(plugin->name);
@@ -189,62 +180,29 @@ void plugin_run_hooks(hook_point_t no)
} }
/* Generic libev I/O callback, looks up correct plugin and calls its callback */ /* Generic libev I/O callback, looks up correct plugin and calls its callback */
static void generic_io_cb(struct pollfd *io) static void generic_io_cb(uev_ctx_t *UNUSED(ctx), uev_t *w, void *arg, int events)
{ {
plugin_t *p, *tmp; plugin_t *p = (plugin_t *)arg;
/* Find matching plugin, pick first matching fd */ if (is_io_plugin(p) && p->io.fd == w->fd) {
PLUGIN_ITERATOR(p, tmp) { _d("Calling I/O %s from runloop...", basename(p->name));
if (is_io_plugin(p) && p->io.fd == io->fd) { p->io.cb(p->io.arg, w->fd, events);
_d("Calling I/O %s from runloop...", basename(p->name));
p->io.cb(p->io.arg, io->fd, io->events);
/* Update fd, may be changed by plugin callback, e.g., if FIFO */ /* Update fd, may be changed by plugin callback, e.g., if FIFO */
io->fd = p->io.fd; if (p->io.fd != w->fd)
io->events = p->io.flags; uev_io_set (w, p->io.fd, p->io.flags);
io->revents = 0;
break;
}
}
}
void plugin_monitor(void)
{
int ret;
size_t i;
while ((ret = poll(fds, num_fds, 500))) {
if (-1 == ret) {
if (EINTR == errno)
continue;
_e("Failed polling I/O plugin descriptors, error %d: %s",
errno, strerror(errno));
break;
}
/* Traverse all I/O fds and run callbacks */
for (i = 0; i < num_fds; i++) {
if (fds[i].revents)
generic_io_cb(&fds[i]);
}
break;
} }
} }
/* Setup any I/O callbacks for plugins that use them */ /* Setup any I/O callbacks for plugins that use them */
static void init_plugins(void) static void init_plugins(uev_ctx_t *ctx)
{ {
int i = 0;
plugin_t *p, *tmp; plugin_t *p, *tmp;
PLUGIN_ITERATOR(p, tmp) { PLUGIN_ITERATOR(p, tmp) {
if (is_io_plugin(p)) { if (is_io_plugin(p)) {
_d("Initializing plugin %s for I/O", basename(p->name)); _d("Initializing plugin %s for I/O", basename(p->name));
fds[i].revents = 0; uev_io_init(ctx, &p->watcher, generic_io_cb, p, p->io.fd, p->io.flags);
fds[i].events = p->io.flags;
fds[i++].fd = p->io.fd;
} }
} }
} }
@@ -318,7 +276,7 @@ static void check_plugin_depends(plugin_t *plugin)
} }
} }
int plugin_load_all(char *path) int plugin_load_all(uev_ctx_t *ctx, char *path)
{ {
int fail = 0; int fail = 0;
DIR *dp = opendir(path); DIR *dp = opendir(path);
@@ -341,7 +299,7 @@ int plugin_load_all(char *path)
} }
closedir(dp); closedir(dp);
init_plugins(); init_plugins(ctx);
return fail; return fail;
} }
+6 -3
View File
@@ -24,13 +24,13 @@
#ifndef FINIT_PLUGIN_H_ #ifndef FINIT_PLUGIN_H_
#define FINIT_PLUGIN_H_ #define FINIT_PLUGIN_H_
#include <poll.h>
#include "queue.h" /* BSD sys/queue.h API */ #include "queue.h" /* BSD sys/queue.h API */
#include "svc.h" #include "svc.h"
#include "libuev/uev.h"
#define PLUGIN_DEP_MAX 10 #define PLUGIN_DEP_MAX 10
#define PLUGIN_IO_READ POLLIN #define PLUGIN_IO_READ UEV_READ
#define PLUGIN_IO_WRITE POLLOUT #define PLUGIN_IO_WRITE UEV_WRITE
#define PLUGIN_INIT(x) static void __attribute__ ((constructor)) x(void) #define PLUGIN_INIT(x) static void __attribute__ ((constructor)) x(void)
#define PLUGIN_EXIT(x) static void __attribute__ ((destructor)) x(void) #define PLUGIN_EXIT(x) static void __attribute__ ((destructor)) x(void)
@@ -79,6 +79,9 @@ typedef struct plugin {
/* BSD sys/queue.h linked list node. */ /* BSD sys/queue.h linked list node. */
TAILQ_ENTRY(plugin) link; TAILQ_ENTRY(plugin) link;
/* Event loop handler, used internally by Finit */
uev_t watcher;
/* Plugin name, defaults to basename of plugin path if unset. /* Plugin name, defaults to basename of plugin path if unset.
* NOTE: Must be same as @cmd for service plugins! */ * NOTE: Must be same as @cmd for service plugins! */
char *name; char *name;
+3 -2
View File
@@ -26,16 +26,17 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "finit.h" #include "finit.h"
#include "libite/lite.h"
#include "helpers.h" #include "helpers.h"
#include "plugin.h" #include "plugin.h"
static void setup(void *UNUSED(arg)) static void setup(void *UNUSED(arg))
{ {
#ifdef RANDOMSEED #ifdef RANDOMSEED
copyfile(RANDOMSEED, "/dev/urandom", 0); copyfile(RANDOMSEED, "/dev/urandom", 0, 0);
unlink(RANDOMSEED); unlink(RANDOMSEED);
umask(077); umask(077);
copyfile("/dev/urandom", RANDOMSEED, 4096); copyfile("/dev/urandom", RANDOMSEED, 4096, 0);
umask(0); umask(0);
#endif #endif
} }
+2 -3
View File
@@ -29,11 +29,10 @@
#include "plugin.h" #include "plugin.h"
void svc_bootstrap (void); void svc_bootstrap (void);
void svc_monitor (void); void svc_monitor (pid_t lost);
void plugin_run_hooks (hook_point_t no); void plugin_run_hooks (hook_point_t no);
int plugin_load_all (char *path); int plugin_load_all (uev_ctx_t *ctx, char *path);
void plugin_monitor (void);
#endif /* FINIT_PRIVATE_H_ */ #endif /* FINIT_PRIVATE_H_ */
+57 -25
View File
@@ -47,9 +47,13 @@
#include "private.h" #include "private.h"
#include "sig.h" #include "sig.h"
static int stopped = 0; static int stopped = 0;
static uev_t sigint_watcher, sigpwr_watcher;
static uev_t sigchld_watcher;
static uev_t sigstop_watcher, sigtstp_watcher, sigcont_watcher;
void do_shutdown (int sig)
void do_shutdown(int sig)
{ {
touch(SYNC_SHUTDOWN); touch(SYNC_SHUTDOWN);
@@ -84,38 +88,35 @@ void do_shutdown (int sig)
} }
/* /*
* Shut down on INT USR1 USR2 * Shut down on INT PWR
*/ */
static void shutdown_handler(int sig, siginfo_t *info, void *UNUSED(ctx)) static void sigint_cb(uev_ctx_t *UNUSED(ctx), uev_t *w, void *UNUSED(arg), int UNUSED(events))
{ {
_d("Rebooting on signal %d from %s (PID %d)", do_shutdown(w->signo);
sig, pid_get_name(info->si_pid, NULL, 0), info->si_pid);
do_shutdown(sig);
} }
/* /*
* SIGCHLD: one of our children has died * SIGCHLD: one of our children has died
*/ */
static void chld_handler(int UNUSED(sig), siginfo_t *UNUSED(info), void *UNUSED(ctx)) static void sigchld_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
/* Do nothing, the svc_monitor() is the designated child reaper. */ svc_monitor(waitpid(-1, NULL, WNOHANG));
} }
/* /*
* SIGSTOP: Paused by user or netflash * SIGSTOP/SIGTSTP: Paused by user or netflash
*/ */
static void sigstop_handler(int sig, siginfo_t *info, void *UNUSED(ctx)) static void sigstop_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
_d("Received SIGSTOP(%d) from %s (PID %d)",
sig, pid_get_name(info->si_pid, NULL, 0), info->si_pid);
touch(SYNC_STOPPED); touch(SYNC_STOPPED);
stopped++; stopped++;
} }
static void sigcont_handler(int sig, siginfo_t *info, void *UNUSED(ctx))
/*
* SIGCONT: Restart service monitor
*/
static void sigcont_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
_d("Received SIGCONT(%d) from %s (PID %d)",
sig, pid_get_name(info->si_pid, NULL, 0), info->si_pid);
stopped = 0; stopped = 0;
erase(SYNC_STOPPED); erase(SYNC_STOPPED);
} }
@@ -131,6 +132,11 @@ int sig_stopped(void)
/* /*
* Inital signal setup - ignore everything but SIGCHLD until we're capable of responding * Inital signal setup - ignore everything but SIGCHLD until we're capable of responding
*/ */
static void chld_handler(int UNUSED(sig), siginfo_t *UNUSED(info), void *UNUSED(ctx))
{
/* NOP */
}
void sig_init(void) void sig_init(void)
{ {
int i; int i;
@@ -142,10 +148,33 @@ void sig_init(void)
SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART); SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART);
} }
/*
* Unblock all signals blocked by finit when starting children
*/
void sig_unblock(void)
{
int i;
sigset_t nmask;
struct sigaction sa;
sigemptyset(&nmask);
sigaddset(&nmask, SIGCHLD);
sigaddset(&nmask, SIGINT);
sigaddset(&nmask, SIGPWR);
sigaddset(&nmask, SIGSTOP);
sigaddset(&nmask, SIGTSTP);
sigaddset(&nmask, SIGCONT);
sigprocmask(SIG_UNBLOCK, &nmask, NULL);
/* Reset signal handlers that were set by the parent process */
for (i = 1; i < NSIG; i++)
DFLSIG(sa, i, 0);
}
/* /*
* Setup limited set of SysV compatible signals to respond to * Setup limited set of SysV compatible signals to respond to
*/ */
void sig_setup(void) void sig_setup(uev_ctx_t *ctx)
{ {
struct sigaction sa; struct sigaction sa;
@@ -156,12 +185,12 @@ void sig_setup(void)
erase(SYNC_STOPPED); erase(SYNC_STOPPED);
/* Standard SysV init calls ctrl-alt-delete handler */ /* Standard SysV init calls ctrl-alt-delete handler */
SETSIG(sa, SIGINT, shutdown_handler, 0); uev_signal_init(ctx, &sigint_watcher, sigint_cb, NULL, SIGINT);
SETSIG(sa, SIGPWR, shutdown_handler, 0); uev_signal_init(ctx, &sigpwr_watcher, sigint_cb, NULL, SIGPWR);
/* Ignore SIGUSR1/2 for now, only BusyBox init implements them as reboot+halt. */ /* Ignore SIGUSR1/2 for now, only BusyBox init implements them as reboot+halt. */
// SETSIG2(sa, SIGUSR1, reopen_initctl, 0); // uev_signal_init(&ctx, &sigusr1_watcher, reopen_initctl_cb, NULL, SIGUSR1);
// SETSIG2(sa, SIGUSR2, pwrdwn_handler, 0); // uev_signal_init(&ctx, &sigusr2_watcher, pwrdwn_cb, NULL, SIGUSR2);
/* Init must ignore SIGTERM. May otherwise get false SIGTERM in forked children! */ /* Init must ignore SIGTERM. May otherwise get false SIGTERM in forked children! */
IGNSIG(sa, SIGTERM, 0); IGNSIG(sa, SIGTERM, 0);
@@ -172,10 +201,13 @@ void sig_setup(void)
/* We don't have any /etc/inittab yet, reread finit.conf? */ /* We don't have any /etc/inittab yet, reread finit.conf? */
IGNSIG(sa, SIGHUP, 0); IGNSIG(sa, SIGHUP, 0);
/* After initial bootstrap of Finit we call the service monitor to reap children */
uev_signal_init(ctx, &sigchld_watcher, sigchld_cb, NULL, SIGCHLD);
/* Stopping init is a bit tricky. */ /* Stopping init is a bit tricky. */
SETSIG(sa, SIGSTOP, sigstop_handler, 0); uev_signal_init(ctx, &sigstop_watcher, sigstop_cb, NULL, SIGSTOP);
SETSIG(sa, SIGTSTP, sigstop_handler, 0); uev_signal_init(ctx, &sigtstp_watcher, sigstop_cb, NULL, SIGTSTP);
SETSIG(sa, SIGCONT, sigcont_handler, 0); uev_signal_init(ctx, &sigcont_watcher, sigcont_cb, NULL, SIGCONT);
/* Disable CTRL-ALT-DELETE from kernel, we handle shutdown gracefully with SIGINT, above */ /* Disable CTRL-ALT-DELETE from kernel, we handle shutdown gracefully with SIGINT, above */
reboot(RB_DISABLE_CAD); reboot(RB_DISABLE_CAD);
+3 -1
View File
@@ -26,6 +26,7 @@
#define FINIT_SIG_H_ #define FINIT_SIG_H_
#include <signal.h> #include <signal.h>
#include "libuev/uev.h"
#define SYNC_SHUTDOWN "/var/lock/finit.shutdown" #define SYNC_SHUTDOWN "/var/lock/finit.shutdown"
#define SYNC_STOPPED "/var/lock/finit.stopped" #define SYNC_STOPPED "/var/lock/finit.stopped"
@@ -57,7 +58,8 @@
void do_shutdown (int sig); void do_shutdown (int sig);
int sig_stopped (void); int sig_stopped (void);
void sig_init (void); void sig_init (void);
void sig_setup (void); void sig_unblock (void);
void sig_setup (uev_ctx_t *ctx);
#endif /* FINIT_SIG_H_ */ #endif /* FINIT_SIG_H_ */
+2 -7
View File
@@ -362,9 +362,8 @@ static void restart_any_lost_procs(void)
} }
} }
void svc_monitor(void) void svc_monitor(pid_t lost)
{ {
pid_t lost;
svc_t *svc; svc_t *svc;
if (was_stopped && !is_norespawn()) { if (was_stopped && !is_norespawn()) {
@@ -373,10 +372,6 @@ void svc_monitor(void)
return; return;
} }
lost = waitpid(-1, NULL, WNOHANG);
if (lost < 1)
return;
if (fexist(SYNC_SHUTDOWN) || lost <= 1) if (fexist(SYNC_SHUTDOWN) || lost <= 1)
return; return;
@@ -458,7 +453,7 @@ int svc_start(svc_t *svc)
sigaddset(&nmask, SIGCHLD); sigaddset(&nmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &nmask, &omask); sigprocmask(SIG_BLOCK, &nmask, &omask);
pid = fork(); pid = vfork();
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
if (pid == 0) { if (pid == 0) {
int i = 0; int i = 0;
+2 -2
View File
@@ -144,7 +144,7 @@ void tty_start(finit_tty_t *tty)
#elif defined(GETTY_BUSYBOX) #elif defined(GETTY_BUSYBOX)
snprintf(line, sizeof(line), "%s %d %s %s", GETTY, tty->baud, tty->name, tty->term ?: ""); snprintf(line, sizeof(line), "%s %d %s %s", GETTY, tty->baud, tty->name, tty->term ?: "");
#else #else
strlcpy(line, FALLBACK_CONSOLE, sizeof(line)); strlcpy(line, FALLBACK_SHELL, sizeof(line));
#endif #endif
} else { } else {
strlcpy(line, tty->name, sizeof(line)); strlcpy(line, tty->name, sizeof(line));
@@ -179,7 +179,7 @@ int tty_enabled(finit_tty_t *tty, int runlevel)
if (!ISSET(tty->runlevels, runlevel)) if (!ISSET(tty->runlevels, runlevel))
return 0; return 0;
else if (fexist(tty->name)) if (fexist(tty->name))
return 1; return 1;
return 0; return 0;