Compare commits

...
67 Commits
Author SHA1 Message Date
Joachim Nilsson 6d41725387 Bump version for v3.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 14:51:55 +01:00
Joachim Nilsson ceb91f746c Revert "Disable clang build during Coverity Scan run"
This reverts commit 22a69d8cca.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 14:45:24 +01:00
Joachim Nilsson a8802ab0d2 Mention Void Linux tutorial in README, change to bullet list
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 14:31:03 +01:00
Joachim Nilsson ad98f69560 Ignore return value from rename(), ofile may not exist yet.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 14:03:07 +01:00
Joachim Nilsson 5953090688 Document some relevant cmdline options
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 13:45:22 +01:00
Joachim Nilsson 22a69d8cca Disable clang build during Coverity Scan run
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 11:45:55 +01:00
Joachim Nilsson 710a3d2c8f Fix Coverity warning, array cannot be NULL
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 11:45:15 +01:00
Joachim Nilsson 658fb9b037 Check return value from rename(), fall back to truncate() on error
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 11:39:50 +01:00
Joachim Nilsson a84bb9042f Update and add ignore for WeOS build system files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 09:51:39 +01:00
Joachim Nilsson eeb13dba74 Toggle silent mode (progress) when toggling debug mode
Starting in debug mode and disabling debug at runtime did not exhibit
the same behavior as if starting in normal mode and toggling debug mode
at runtime.  This patch adds toggling of silent mode (progress output)
to runtime debug toggling.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 09:44:44 +01:00
Joachim Nilsson 3d20237959 Follow-up to f858d94, only reinitialize screen when toggling debug mode
The screen_init() call for each print() & C:o caused serious screen
artefacts in debug mode.  This patch reworks f858d94 to only re-init
screen when toggling debug.

Also, avoid screen_init() completely if started in debug mode.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 09:33:24 +01:00
Joachim Nilsson ddf1bce642 Add screen_exit() fn to restore screen defaults in debug mode
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 09:31:44 +01:00
Joachim Nilsson 93cd4116db Update ChangeLog and prepare for v3.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 01:21:37 +01:00
Joachim Nilsson 1df6a91a94 Document sufficiently complex, yet deceptively simple, function
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 00:44:40 +01:00
Joachim Nilsson c64a71ff30 Follow-up to ba2ab4b, crashing services may not have a PID rn
- Don't warn of missing PID, even if only _d(), perfectly normal
- Allow stopping restart timer of non-services (e.g. task/run)
- Allow stopping services with no PID rn, i.e. stop libuEv timer

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-23 00:17:02 +01:00
Joachim Nilsson b2b6fd25d8 Relocate service helper script to contrib/
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 22:28:18 +01:00
Joachim Nilsson 3ca548b681 Add list of major contributors, from Westermo
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 21:31:05 +01:00
Joachim Nilsson ba2ab4b446 Follow-up to 2683049, only stop running, non-inet, services
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 20:52:37 +01:00
Joachim Nilsson a8183b0559 Check if symlink exists before trying to create symlink
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 20:45:05 +01:00
Joachim Nilsson 227e4fa097 Create destination contrib/*/finit.d dir if missing
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 19:03:06 +01:00
Joachim Nilsson 3d68ebbf54 Fix off-by-one in condition reassert()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 15:24:11 +01:00
Joachim Nilsson 6e017025aa Fix bad string pointer arithmetic in condition reassert
On `initctl reload` we reassert conditions, i.e. bring each still viable
condition back in sync with the new reconf generation.  This patch fixes
an assumption in the reassert() callback that caused the following nasty
transformation:

	/run/finit/cond/net/lo/up --> /run/finit/cond/lo/up

The transformation was caused by the reassert() code assuming a /var/run
prefix rather than /run.  We must check the actual runpath, or like this
patch does, use a path neutral way to find the base condition string.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 15:17:07 +01:00
Joachim Nilsson 5f818f917e cond_init(): Create correct condition path, /var/run might not exist
The cond_init() function is called before the bootmisc.so plugin has
run.  It is responsble for setting up the /var/run symlink to /run on
systems with the new layout.  Therefore we must wrap COND_PATH with
pid_runpath() to create the correct runtime path.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 15:17:07 +01:00
Joachim Nilsson 0da1deb487 Add docs/*.md to distribution
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 09:02:19 +01:00
Joachim Nilsson 0337985422 Ignore generated files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 09:02:19 +01:00
Joachim Nilsson f59d41cdec Add silly process monitor script to distribution.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 09:02:18 +01:00
Joachim Nilsson 1cc998eb60 Distribute and install contrib/ directory with all examples
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 09:01:58 +01:00
Joachim Nilsson 8c1d84305d Minor, refactor
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-22 08:38:52 +01:00
Joachim Nilsson 7e4e5127c7 Preserve Markdown links on installed .md files in docs/ sub-directory
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-21 10:22:25 +01:00
Joachim Nilsson 3b813bca68 Ignore generated files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-20 20:48:26 +01:00
Joachim Nilsson a1f210bc70 Distribute and install relevant docs/*.md
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-20 20:47:33 +01:00
Joachim Nilsson 0ecf46d7a9 Prefer _exit() over exit() in forked service handlers
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:35:15 +01:00
Joachim Nilsson 268304927d Fix segfault, stop a crashing service before deleting it
Finit tries to restart crashing services.  If a service is removed
before Finit has given up restarting it, then the background timer
responsible the restart may dereference a free():d svc_t.

Hence, make sure to properly stop (and step) a service and its timer
callbacks in service_unregister() before calling svc_del().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:27:25 +01:00
Joachim Nilsson fa02b59db5 Refactor, set STOPPING state in service_stop()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:24:39 +01:00
Joachim Nilsson 2c904b5b44 service_unregister(): Also call inetd_del() for inetd services
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:07:22 +01:00
Joachim Nilsson 4191abc79f service_timeout_cb(): Check callback pointer before calling it
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:07:22 +01:00
Joachim Nilsson abb928f60b service_stop(): Also stop any pending restart timers
In service_stop() we call svc_del() which, as of Finit v3.1, free():s
the svc_t, so we don't want any lingering restart timers to wake up
after free() and start dereferencing the svc_t.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 16:07:22 +01:00
Joachim Nilsson 3c52118a8e svc_clean_dynamic(): Fix access after free()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-19 13:20:25 +01:00
Joachim Nilsson 5354a57313 plugin_unregister(): Stop I/O watcher before free():ing watcher
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 18:35:18 +01:00
Joachim Nilsson 92b1d882e5 do_kill(): Also skip gdbserver from being killed
To improve debug possibilities at shutdown, keep gdbserver running even
during shutdown.

Note: The gdbserver service runlevels must be sth like [123456789] for
      this to work in the first place.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 18:21:37 +01:00
Joachim Nilsson fd7a6c5020 cond.c: Normalize COND_PATH, some systems have /run not /var/run
On most modern Linux systems /run is a tmpfs that replaces /var/run.
The latter is set up as a symlink to /run by the bootmisc.so plugin.

However, Finit conditions rely on the /var/run/finit/cond prefix, which
does not exist until bootmisc.so has run, which is *after* `mount -a`
has run.  Therefore, to have working conditions before we run `mount -a`
we must normalize the path constructed by cond_path() to use either the
/run or /var/run (default) prefix.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 14:44:25 +01:00
Joachim Nilsson a61551d15f pid.c: Relocate pid_runpath() to a static inline fn
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 14:44:00 +01:00
Joachim Nilsson 7f62a69f74 New hook/mount/post, runs after mount -a but before hook/mount/all
This gives the operator a way to add a post-mount script, e.g. to peform
a 2nd stage mount or mount preparations, before the bootmisc.so plugin
and others run in hook/mount/all

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 13:34:28 +01:00
Joachim Nilsson c969bda62d bootmisc.so: Create /etc/mtab symlink if missing
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 13:34:28 +01:00
Joachim Nilsson af41fcd35e api_exit(): Must stop libuEv watcher before closing descriptor
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-18 13:34:28 +01:00
Joachim Nilsson 84e9569be6 initctl: Adjust field widths in show/status
The job:id field can now be used to display job:INET_PORT_NUMBER, e.g.
100:16161 for job 100 localhost SNMP port 16161.

The service name field has been reduced from 20 --> 16 bytes since the
full path has been reduced to display the basename.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-17 18:42:24 +01:00
Joachim Nilsson a4ece0fe3f Add log rotate, log, condition and non-SIGHUP example .conf sample
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 17:41:03 +01:00
Joachim Nilsson b2f66da1f9 Cleanup TODO, last item turned out to be bogus
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 17:06:55 +01:00
Joachim Nilsson abbc0a1d5c Fix Ctrl-C, and signals in general, on "logins" in nologin mode
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 16:25:11 +01:00
Joachim Nilsson 37e420bd35 Minor, itemize example files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 16:03:36 +01:00
Joachim Nilsson d72eb45d6e Refactor, simplify text and rename section
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 16:02:06 +01:00
Joachim Nilsson 30c593f64e Minor, reorder debug messages to not mess up progress text
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:55:57 +01:00
Joachim Nilsson f858d94d2a Reinitialize screen at shutdown and when in debug mode
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:47:14 +01:00
Joachim Nilsson 992bab2f8f Allow empty -- run/task/service descriptions => no progress
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:38:55 +01:00
Joachim Nilsson 72c9681ffb Change debug messages to use svc->cmd rather than empty svc->desc
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:15:49 +01:00
Joachim Nilsson e439b79e82 Refactor, only show process progress if -- Description is set
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:15:10 +01:00
Joachim Nilsson 36e001d636 Refactor, rindex() --> strrchr(), LEGACY as of POSIX.1-2001
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 14:13:48 +01:00
Joachim Nilsson 75aa14466f Allow disabling log rotation, log size:0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 07:50:52 +01:00
Joachim Nilsson 7f899b7a91 Clarify size:200k and count:5 global log rotation options
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 07:46:27 +01:00
Joachim Nilsson 1c177fd953 TODO before v3.1 GA release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-16 07:41:20 +01:00
Joachim Nilsson 617ec7c147 Document global log rotation setting log size:200k count:5
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 19:42:33 +01:00
Joachim Nilsson 192d3aafe7 Add support for global logfile max size and max num. rotated
# 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 size=100k count=4

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 19:42:33 +01:00
Joachim Nilsson f11ebb0046 New function, strtobytes(), allows k/M/G ISO size modifiers
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 19:42:33 +01:00
Joachim Nilsson b5e260b9e0 Minor refactor
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 18:30:41 +01:00
Joachim Nilsson 45c10edad6 Fix static build, libplug.la is now in ../plugins/, not plugins/
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 16:05:39 +01:00
Joachim Nilsson b60d8ce4b6 Fix bootstrap ordering problem, inotify watchers *after* HOOK_BASEFS_UP
An external plugin to set up /etc can use HOOK_BASEFS_UP, but the Finit
conf_monitor() must then be called *after* not before that hook, or the
inotify watchers will listen on the wrong inode.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 15:23:25 +01:00
Joachim Nilsson d35a8bbda9 Fix problem building external plugins
The file plugin.h is installed to $prefix/include and used by external
plugins.  Therefore it must not include, or depend on, features set by
the configure script in config.h

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-01-15 15:07:24 +01:00
49 changed files with 614 additions and 140 deletions
+8 -1
View File
@@ -2,13 +2,15 @@
*.o *.o
*.so *.so
*.gz *.gz
ID
GPATH GPATH
GRTAGS GRTAGS
GSYMS GSYMS
GTAGS GTAGS
# GNU configure and build system # GNU configure and build system
/autom4te.cache/* /.deps
/autom4te.cache
/aclocal.m4 /aclocal.m4
/ar-lib /ar-lib
/compile /compile
@@ -33,3 +35,8 @@ GTAGS
/.config /.config
/.stamp /.stamp
/.unpacked /.unpacked
# WeOS build system
/.autoconf
/.automake
/.built
+5
View File
@@ -1,6 +1,11 @@
Current Maintainer(s): Current Maintainer(s):
* Joachim Nilsson <troglobit@gmail.com> * Joachim Nilsson <troglobit@gmail.com>
Major Contributors:
* Tobias Waldekranz <tobias@waldekranz.com>
* Mattias Walström <mattias.walstrom@westermo.se>
* Jonas Johansson <jonas.johansson@westermo.se>
Original Author(s): Original Author(s):
* Claudio Matsuoka <cmatsuoka@gmail.com> * Claudio Matsuoka <cmatsuoka@gmail.com>
+28 -9
View File
@@ -4,10 +4,16 @@ Change Log
All relevant changes are documented in this file. All relevant changes are documented in this file.
[3.1][] - 2017-12-xx [3.1][] - 2018-01-23
-------------------- --------------------
Finit v3.1 require libuEv v2.1.0, or later, and libite v2.0.1, or later. Improvements to `netlink.so` plugin, per-service `rlimit` support,
improved integration with `watchdogd`, auto-detect TTY console. Much
improved debug, rescue and logging support. Also, many fixes to both
big and small issues, most notably in the condition handling, which no
longer is sensitive to time skips.
This version requires at least libuEv v2.1.0 and libite v2.0.1
### Changes ### Changes
@@ -24,9 +30,8 @@ Finit v3.1 require libuEv v2.1.0, or later, and libite v2.0.1, or later.
* Support for auto-detecting serial console using Linux SysFS, the new * Support for auto-detecting serial console using Linux SysFS, the new
`tty @console` eliminates the need to keep track of different console `tty @console` eliminates the need to keep track of different console
devices across embedded platforms: `/dev/ttyS0`, `/dev/ttyAMA0`, etc. devices across embedded platforms: `/dev/ttyS0`, `/dev/ttyAMA0`, etc.
* Support for the special debug option `nologin` to tty configurations, * Add TTY `nologin` option. Bypasses login and skips immediately to a
skips the login prompt and skips immediately to a root shell. Useful root shell. Useful during board bringup, in developer builds, etc.
during board bringup, in developer builds, etc. Be careful though ...
* Support for calling run/tasks on Finit internal HOOK points, issue #18 * Support for calling run/tasks on Finit internal HOOK points, issue #18
* Removed support for long-since deprecated `console DEV` setting * Removed support for long-since deprecated `console DEV` setting
* Cosmetic change to login, pressing enter at the `Press enter to ...` * Cosmetic change to login, pressing enter at the `Press enter to ...`
@@ -57,9 +62,21 @@ Finit v3.1 require libuEv v2.1.0, or later, and libite v2.0.1, or later.
redirect `stdout` and `stderr` of all applications to `/dev/null` redirect `stdout` and `stderr` of all applications to `/dev/null`
* New `pid` sub-option to services when a service does not create a PID * New `pid` sub-option to services when a service does not create a PID
file, or when the PID file has another name. Issue #95 file, or when the PID file has another name. Issue #95
* New `log` sub-option to service/run/task to selectively redirect * Greatly improved `log` sub-option to service/run/tasks, selectively
`stdout` and `stderr` using the new tool `logit` to either syslog redirect `stdout` and `stderr` using the new tool `logit` to either
or a logfile. Issue #44 syslog or a logfile. Issue #44
* Support for automatic log rotation of logfiles created by `log`
option. Use `configure --disable-logrotate` on systems with a
dedicated log rotation service. Issue #44
* Support for disabling service/run/task progress with empty ` --`
description. Note: no description separator gives a default desc.
* Create `/etc/mtab` symlink if missing on system (bootmisc plugin)
* New hook: `hook/mount/post` runs after `mount -a` but before the
`hook/mount/all`, where `bootmisc.so` runs. This provides the
possibility of running a second stage mount command before files in
`/run` and similar are created
* Skip `gdbserver` when unleashing the grim reaper at shutdown
* Distribute and install `docs/` and `contrib/` directories
### Fixes ### Fixes
@@ -94,6 +111,7 @@ Finit v3.1 require libuEv v2.1.0, or later, and libite v2.0.1, or later.
* Fix issue #81 properly, remove use of SYSV shm IPC completely. Finit * Fix issue #81 properly, remove use of SYSV shm IPC completely. Finit
now use the API socket for all communication between PID 1 and initctl now use the API socket for all communication between PID 1 and initctl
* Fix segfault on x86_64 when started with kernel cmdline `--debug` * Fix segfault on x86_64 when started with kernel cmdline `--debug`
* Normalize condition paths on systems with `/run` instead of `/var/run`
[3.0][] - 2017-10-19 [3.0][] - 2017-10-19
@@ -691,7 +709,8 @@ Major bug fix release.
* Initial release * Initial release
[UNRELEASED]: https://github.com/troglobit/finit/compare/3.0...HEAD [UNRELEASED]: https://github.com/troglobit/finit/compare/3.1...HEAD
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0 [3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4 [2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3 [2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
+1 -2
View File
@@ -1,6 +1,5 @@
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
SUBDIRS = plugins src SUBDIRS = contrib docs plugins src
bin_SCRIPT = service
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
+17 -2
View File
@@ -10,6 +10,7 @@
* [Hooks, Callbacks & Plugins](docs/plugins.md#hooks-callbacks--plugins) * [Hooks, Callbacks & Plugins](docs/plugins.md#hooks-callbacks--plugins)
* [Rebooting & Halting](#rebooting--halting) * [Rebooting & Halting](#rebooting--halting)
* [Commands & Status](#commands--status) * [Commands & Status](#commands--status)
* [Tips & Tricks with the kernel cmdline](docs/cmdline.md)
* [Building](docs/build.md#building) * [Building](docs/build.md#building)
* [Running](docs/build.md#running) * [Running](docs/build.md#running)
* [Recovery](docs/build.md#recovery) * [Recovery](docs/build.md#recovery)
@@ -28,8 +29,11 @@ was reverse engineered from the [EeePC fastinit][] ten years ago by
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 where both [Debian](contrib/debian/) and [contrib/](contrib/) section with tutorials for:
up to date [Alpine Linux](contrib/alpine/) tutorials can be found.
* [Alpine Linux](contrib/alpine/),
* [Debian GNU/Linux](contrib/debian/), and
* [Void Linux](contrib/void/)
![Alpine screenshot](images/alpine-screenshot.png) ![Alpine screenshot](images/alpine-screenshot.png)
The screenshot shows [Alpine Linux](https://www.alpinelinux.org/). The screenshot shows [Alpine Linux](https://www.alpinelinux.org/).
@@ -50,12 +54,23 @@ host default
# Runlevel to start after bootstrap, 'S', default: 2 # Runlevel to start after bootstrap, 'S', default: 2
runlevel 2 runlevel 2
# 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 size=100k count=4
# Services to be monitored and respawned as needed # Services to be monitored and respawned as needed
service [S12345] /sbin/watchdogd -L -f -- System watchdog daemon service [S12345] /sbin/watchdogd -L -f -- System watchdog daemon
service [S12345] /sbin/syslogd -n -b 3 -D -- System log daemon service [S12345] /sbin/syslogd -n -b 3 -D -- System log daemon
service [S12345] /sbin/klogd -n -- Kernel log daemon service [S12345] /sbin/klogd -n -- Kernel log daemon
service [2345] /sbin/lldpd -d -c -M1 -H0 -i -- LLDP daemon (IEEE 802.1ab) service [2345] /sbin/lldpd -d -c -M1 -H0 -i -- LLDP daemon (IEEE 802.1ab)
# 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
# log file is rotated with the above settings. The condition declares
# a dependency on a system default route (gateway) to be set. A single
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
service [2345] log:/var/log/ntpd.log <!net/route/default> /sbin/ntpd -n -l -I eth0 -- NTP daemon
# For multiple instances of the same service, add :ID somewhere between # For multiple instances of the same service, add :ID somewhere between
# the service/run/task keyword and the command. # the service/run/task keyword and the command.
service :1 [2345] /sbin/merecat -n -p 80 /var/www -- Web server service :1 [2345] /sbin/merecat -n -p 80 /var/www -- Web server
+10 -2
View File
@@ -1,10 +1,17 @@
AC_INIT(Finit, 3.1-rc2, https://github.com/troglobit/finit/issues, finit, http://troglobit.com/finit.html) AC_INIT(Finit, 3.1, https://github.com/troglobit/finit/issues, finit, http://troglobit.com/finit.html)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects]) AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip 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_HEADER([config.h]) AC_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile plugins/Makefile src/Makefile]) AC_CONFIG_FILES([Makefile
contrib/Makefile
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile contrib/debian/grub.d/Makefile
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
docs/Makefile
plugins/Makefile
src/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])
@@ -21,6 +28,7 @@ LT_INIT([shared disable-static dlopen aix-soname=both disable-fast-install])
AC_PROG_CC AC_PROG_CC
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_MKDIR_P
# Configuration. # Configuration.
AC_HEADER_STDC AC_HEADER_STDC
+2
View File
@@ -0,0 +1,2 @@
Makefile
Makefile.in
+5
View File
@@ -0,0 +1,5 @@
SUBDIRS = alpine debian void
bin_SCRIPT = service
docsdir := @docdir@/contrib
docs_DATA = README.md finit.conf procmon.sh
EXTRA_DIST = $(docs_DATA)
+5
View File
@@ -0,0 +1,5 @@
SUBDIRS = finit.d
docsdir := @docdir@/contrib/alpine
docs_DATA = README.md finit.conf alpine-release build.sh install.sh rc.local
EXTRA_DIST = $(docs_DATA)
+27
View File
@@ -0,0 +1,27 @@
SUBDIRS = available
docsdir := @docdir@/contrib/alpine/finit.d
d_LINKS = dropbear.conf getty.conf keymap.conf modules.conf klogd.conf \
syslogd.conf
install-exec-hook:
@$(MKDIR_P) $(DESTDIR)$(docsdir)
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ -L $$lnk ]; then \
echo "Skipping $$lnk exists."; \
else \
$(LN_S) $$src $$lnk; \
fi; \
done
uninstall-hook:
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ "`readlink $$lnk`" != "$$src" ]; then \
continue; \
fi; \
$(RM) $$lnk; \
done
@@ -0,0 +1,4 @@
docsdir := @docdir@/contrib/alpine/finit.d/available
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
lxdm.conf modules.conf ntpd.conf klogd.conf syslogd.conf
EXTRA_DIST = $(docs_DATA)
+4
View File
@@ -0,0 +1,4 @@
SUBDIRS = finit.d grub.d
docsdir := @docdir@/contrib/debian
docs_DATA = README.md finit.conf os-release build.sh install.sh
EXTRA_DIST = $(docs_DATA)
+27
View File
@@ -0,0 +1,27 @@
SUBDIRS = available
docsdir := @docdir@/contrib/debian/finit.d
d_LINKS = console-setup.conf getty.conf keyboard-setup.conf \
modules.conf rsyslogd.conf sshd.conf
install-exec-hook:
@$(MKDIR_P) $(DESTDIR)$(docsdir)
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ -L $$lnk ]; then \
echo "Skipping $$lnk exists."; \
else \
$(LN_S) $$src $$lnk; \
fi; \
done
uninstall-hook:
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ "`readlink $$lnk`" != "$$src" ]; then \
continue; \
fi; \
$(RM) $$lnk; \
done
@@ -0,0 +1,5 @@
docsdir := @docdir@/contrib/debian/finit.d/available
docs_DATA = acpid.conf console-setup.conf getty.conf \
keyboard-setup.conf lightdm.conf modules.conf \
ntpclient.conf rsyslogd.conf sshd.conf xdm.conf
EXTRA_DIST = $(docs_DATA)
+3
View File
@@ -0,0 +1,3 @@
docsdir := @docdir@/contrib/debian/grub.d
docs_DATA = 40_custom
EXTRA_DIST = $(docs_DATA)
+11
View File
@@ -17,6 +17,10 @@ runlevel 2
# Network bringup script # Network bringup script
network service networking start network service networking start
# 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 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
@@ -33,6 +37,13 @@ service [2345] /sbin/klogd -n -- Kernel logging server
service [2345] /sbin/syslogd -n -- Syslog server service [2345] /sbin/syslogd -n -- Syslog server
service [3] /usr/sbin/gdm -- GNOME Display Manager service [3] /usr/sbin/gdm -- GNOME Display Manager
# 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
# log file is rotated with the above settings. The condition declares
# a dependency on a system default route (gateway) to be set. A single
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
service [2345] log:/var/log/ntpd.log <!net/route/default> /sbin/ntpd -n -l -I eth0 -- NTP daemon
# Run start scripts from this directory # Run start scripts from this directory
# runparts /etc/start.d # runparts /etc/start.d
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
USAGE="Usage: $0 processName"
LOG_FILE="/tmp/memusage.csv"
ELAPSED_TIME=0
PERIOD=1 # seconds
if [ $# -ne 1 ]; then
echo $USAGE
exit 1
fi
echo "ElapsedTime,VmSize,VmRSS" > $LOG_FILE
# Monitor memory usage forever until script is killed
while :
do
SUM_VM_SIZE=0
SUM_RSS_SIZE=0
# In case the monitored process has not yet started
# keep searching until its PID is found
PROCESS_PIDS=""
while :
do
PROCESS_PIDS=`/bin/pidof $1`
if [ "$PROCESS_PIDS.X" != ".X" ]; then
break
fi
done
for PID in ${PROCESS_PIDS} ; do
VM_SIZE=`awk '/VmSize/ {print $2}' < /proc/$PID/status`
if [ "$VM_SIZE.X" = ".X" ]; then
continue
fi
#echo exprVM_ $SUM_VM_SIZE + $VM_SIZE
SUM_VM_SIZE=`expr $SUM_VM_SIZE + $VM_SIZE`
VM_RSS=`awk '/VmRSS/ {print $2}' < /proc/$PID/status`
if [ "$VM_RSS.X" = ".X" ]; then
continue
fi
SUM_RSS_SIZE=`expr $SUM_RSS_SIZE + $VM_RSS`
done
echo "$ELAPSED_TIME sec, $SUM_VM_SIZE KB, $SUM_RSS_SIZE KB"
echo "$ELAPSED_TIME,$SUM_VM_SIZE,$SUM_RSS_SIZE" >> $LOG_FILE
sleep $PERIOD
VM_SIZE=""
VM_RSS=""
# Needs to get actual elapsed time instead of doing this
ELAPSED_TIME=`expr $ELAPSED_TIME + $PERIOD`
done
View File
+4
View File
@@ -0,0 +1,4 @@
SUBDIRS = finit.d
docsdir := @docdir@/contrib/void
docs_DATA = README.md finit.conf build.sh install.sh rc.local xbps
EXTRA_DIST = $(docs_DATA)
+26
View File
@@ -0,0 +1,26 @@
SUBDIRS = available
docsdir := @docdir@/contrib/void/finit.d
d_LINKS = acpid.conf dhcpcd.conf getty.conf sshd.conf uuidd.conf
install-exec-hook:
@$(MKDIR_P) $(DESTDIR)$(docsdir)
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ -L $$lnk ]; then \
echo "Skipping $$lnk exists."; \
else \
$(LN_S) $$src $$lnk; \
fi; \
done
uninstall-hook:
@for file in $(d_LINKS); do \
lnk=$(DESTDIR)$(docsdir)/$$file; \
src=available/$$file; \
if [ "`readlink $$lnk`" != "$$src" ]; then \
continue; \
fi; \
$(RM) $$lnk; \
done
@@ -0,0 +1,5 @@
docsdir := @docdir@/contrib/void/finit.d/available
docs_DATA = acpid.conf crond.conf dhcpcd.conf dmeventd.conf getty.conf \
keymap.conf klogd.conf lxdm.conf modules.conf ntpd.conf \
sshd.conf syslogd.conf uuidd.conf
EXTRA_DIST = $(docs_DATA)
+2
View File
@@ -0,0 +1,2 @@
Makefile
Makefile.in
+4
View File
@@ -0,0 +1,4 @@
docsdir := @docdir@/docs
docs_DATA = config.md conditions.md distro.md inetd.md plugins.md \
service.md signals.md svc-machine.png cmdline.md
EXTRA_DIST = $(docs_DATA)
+38
View File
@@ -0,0 +1,38 @@
Tips & Tricks with the kernel cmdline
=====================================
This document summarizes the different boot parameters that can be
passed on the Linux kernel command line. Not just limited to Finit.
* `debug`, or `--debug`
Enable debug mode. The former syntax also enable kernel debug, and
the latter only in Finit. Debug messages are printed to the console
until a syslog daemon has been started.
* `init=/bin/sh`
Bypass system default init and tell kernel to start a shell. Note,
this shell is very limited and does not support signals and has no
job control. Recommend using, and modifying, `rescue` mode instead.
* `panic=SEC`
By default the kernel does not reboot after a kernel panic. This
setting will cause a kernel reboot after SEC seconds.
* `quiet`
Suppress kernel logging to console, except for warnings and errors.
* `rescue`
Start Finit rescue mode; no network, no `fsck` of file systems in
`/etc/fstab`, no `/etc/rc.local`, no `runparts`. The configuration
is read from `/etc/rescue.conf`, can be modified by the operator.
* `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.
* `splash`
Display Finit splash screen with progress at bootstrap and shutdown.
For more on kernel boot paramaters, see the man page `bootparam(7)`.
+35 -15
View File
@@ -2,6 +2,7 @@ Configuration
============= =============
* [Introduction](#introduction) * [Introduction](#introduction)
* [Service Wrapper Scripts](#service-wrapper-scripts)
* [Syntax](#syntax) * [Syntax](#syntax)
* [Limitations](#limitations) * [Limitations](#limitations)
* [/etc/finit.conf](#etcfinitconf) * [/etc/finit.conf](#etcfinitconf)
@@ -48,25 +49,27 @@ On `initctl reload` the following is checked for all services:
For more info on the different states of a service, see the separate For more info on the different states of a service, see the separate
document [Finit Services](service.md). document [Finit Services](service.md).
### Execute pre commands for a service
If your service requires to run additional commands that are executed before Service Wrapper Scripts
the service is actually started (something like systemds `ExecStartPre`) you -----------------------
can use a wrapper shell script which runs the additional commands before
executing the service.
The Finit service .conf file can be put into `/etc/finit.d/available` so you If your service requires to run additional commands, executed before the
can control the service using `initctl`. Just place in the service .conf file service is actually started, like the systemd `ExecStartPre`, you can
the path to the wrapper shell script, e.g. if the wrapper is located in use a wrapper shell script to start your service.
`/etc/start.d`:
The Finit service `.conf` file can be put into `/etc/finit.d/available`,
so you can control the service using `initctl`. Then use the path to
the wrapper script in the Finit `.conf` service stanza. The following
example employs a wrapper script in `/etc/start.d`.
**Example:** **Example:**
`/etc/finit.d/available/program.conf`:
* `/etc/finit.d/available/program.conf`:
```conf ```conf
service [235] <!> /etc/start.d/program -- Example Program service [235] <!> /etc/start.d/program -- Example Program
``` ```
**Example:**
`/etc/start.d/program:` * `/etc/start.d/program:`
```shell ```shell
#!/bin/sh #!/bin/sh
@@ -77,9 +80,10 @@ OPTIONS="-u $(cat /etc/username)"
exec /usr/bin/program $OPTIONS exec /usr/bin/program $OPTIONS
``` ```
*Note, that the example sets `<!>` to denote that it doesn't support SIGHUP. That **Note:**, that the example sets `<!>` to denote that it doesn't support
way Finit will stop/start such the service instead of sending SIGHUP at `SIGHUP`. That way Finit will stop/start such the service instead of
restart/reload.* sending SIGHUP at restart/reload.
Syntax Syntax
------ ------
@@ -225,6 +229,19 @@ Syntax
* `include <CONF>` * `include <CONF>`
Include another configuration file. Absolute path required. Include another configuration file. Absolute path required.
* `log size:200k count:5`
Log rotation for run/task/services using the `log` sub-option with
redirection to a log file. Global setting, applies to all services.
The size can be given as bytes, without a specifier, or in `k`, `M`,
or `G`, e.g. `size:10M`, or `size:3G`. A value of `size:0` disables
log rotation. The default is `200k`.
The count value is recommended to be between 1-5, with a default 5.
Setting count to 0 means the logfile will be truncated when the MAX
size limit is reached.
* `tty [LVLS] <DEV> [BAUD] [noclear] [nowait] [nologin] [TERM]` * `tty [LVLS] <DEV> [BAUD] [noclear] [nowait] [nologin] [TERM]`
`tty [LVLS] <CMD> <ARGS> [noclear] [nowait]` `tty [LVLS] <CMD> <ARGS> [noclear] [nowait]`
The first variant of this option uses the built-in getty on the given The first variant of this option uses the built-in getty on the given
@@ -324,6 +341,8 @@ syslog using the native `logit` tool. The full syntax is:
log:null log:null
log log
Log rotation is controlled using the global `log` setting.
**Example:** **Example:**
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
@@ -350,6 +369,7 @@ network bringup and shutdown:
- `network`, only at bootstrap - `network`, only at bootstrap
- `runparts`, only at bootstrap - `runparts`, only at bootstrap
- `include` - `include`
- `log`, global setting
- `shutdown` - `shutdown`
- `runlevel`, only at bootstrap - `runlevel`, only at bootstrap
- ... and all configuration stanzas from `/etc/finit.d` below - ... and all configuration stanzas from `/etc/finit.d` below
+3
View File
@@ -170,6 +170,9 @@ static void setup(void *arg)
makefifo("/dev/xconsole", 0640); /* sysklogd */ makefifo("/dev/xconsole", 0640); /* sysklogd */
chown("/dev/xconsole", 0, gid); 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 */ /* Void Linux has a uuidd that runs as uuid:uuid and needs /run/uuid */
uid = getuser("uuidd", NULL); uid = getuser("uuidd", NULL);
if (uid >= 0) { if (uid >= 0) {
+11 -10
View File
@@ -44,7 +44,7 @@ finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS) finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
finit_LDADD = $(lite_LIBS) $(uev_LIBS) finit_LDADD = $(lite_LIBS) $(uev_LIBS)
if STATIC if STATIC
finit_LDADD += plugins/libplug.la finit_LDADD += ../plugins/libplug.la
else else
finit_LDADD += -ldl finit_LDADD += -ldl
endif endif
@@ -69,7 +69,7 @@ install-exec-hook:
@for file in $(INIT_LNKS); do \ @for file in $(INIT_LNKS); do \
lnk=$(DESTDIR)$(sbindir)/$$file; \ lnk=$(DESTDIR)$(sbindir)/$$file; \
if [ -e $$lnk ]; then \ if [ -e $$lnk ]; then \
echo "Skipping $$lnk exists already."; \ echo "Skipping $$lnk exists."; \
else \ else \
$(LN_S) finit $$lnk; \ $(LN_S) finit $$lnk; \
fi; \ fi; \
@@ -78,11 +78,11 @@ install-exec-hook:
echo "Non-finit reboot, skipping install."; \ echo "Non-finit reboot, skipping install."; \
else \ else \
for file in $(REBOOT_LNKS); do \ for file in $(REBOOT_LNKS); do \
link=$(DESTDIR)$(sbindir)/$$file; \ lnk=$(DESTDIR)$(sbindir)/$$file; \
if [ -e $$link ]; then \ if [ -e $$lnk ]; then \
echo "$$link exists, skipping.";\ echo "Skipping $$lnk exists."; \
else \ else \
$(LN_S) reboot $$link; \ $(LN_S) reboot $$lnk; \
fi; \ fi; \
done; \ done; \
fi fi
@@ -101,10 +101,11 @@ uninstall-hook:
echo "Non-finit reboot, skipping uninstall."; \ echo "Non-finit reboot, skipping uninstall."; \
else \ else \
for file in $(REBOOT_LNKS); do \ for file in $(REBOOT_LNKS); do \
link=$(DESTDIR)$(sbindir)/$$file; \ lnk=$(DESTDIR)$(sbindir)/$$file; \
if [ "`readlink $$link`" != "reboot" ]; \ dst=`readlink $$lnk`; \
then continue; \ if [ "$$dst" != "reboot" ]; then \
continue; \
fi; \ fi; \
$(RM) $$link; \ $(RM) $$lnk; \
done; \ done; \
fi fi
+2
View File
@@ -429,6 +429,8 @@ error:
int api_exit(void) int api_exit(void)
{ {
uev_io_stop(&api_watcher);
return close(api_watcher.fd); return close(api_watcher.fd);
} }
+11 -2
View File
@@ -28,6 +28,7 @@
#include "finit.h" #include "finit.h"
#include "cond.h" #include "cond.h"
#include "pid.h"
#include "service.h" #include "service.h"
static int cond_set_gen(const char *path, unsigned int gen) static int cond_set_gen(const char *path, unsigned int gen)
@@ -205,7 +206,13 @@ static int reassert(const char *fpath, const struct stat *sb, int tflg, struct F
if (tflg != FTW_F) if (tflg != FTW_F)
return 0; return 0;
nm = (char *)fpath + sizeof(COND_PATH); nm = strstr((char *)fpath, COND_DIR);
if (!nm) {
_e("Incorrect condtion path %s, cannot reassert", fpath);
return 1;
}
nm += sizeof(COND_DIR);
_d("Reasserting %s => %s", fpath, nm); _d("Reasserting %s => %s", fpath, nm);
cond_set(nm); cond_set(nm);
@@ -224,7 +231,9 @@ void cond_reassert(const char *type)
void cond_init(void) void cond_init(void)
{ {
if (makepath(COND_PATH) && errno != EEXIST) { char path[MAX_ARG_LEN];
if (makepath(pid_runpath(COND_PATH, path, sizeof(path))) && errno != EEXIST) {
_pe("Failed creating condition base directory '%s'", COND_PATH); _pe("Failed creating condition base directory '%s'", COND_PATH);
return; return;
} }
+4 -2
View File
@@ -26,6 +26,7 @@
#include "finit.h" #include "finit.h"
#include "cond.h" #include "cond.h"
#include "pid.h"
#include "service.h" #include "service.h"
@@ -42,11 +43,12 @@ const char *condstr(enum cond_state s)
const char *cond_path(const char *name) const char *cond_path(const char *name)
{ {
char tmp[MAX_ARG_LEN];
static char file[MAX_ARG_LEN]; static char file[MAX_ARG_LEN];
snprintf(file, sizeof(file), COND_PATH "/%s", name); snprintf(tmp, sizeof(tmp), COND_PATH "/%s", name);
return file; return pid_runpath(tmp, file, sizeof(file));
} }
unsigned int cond_get_gen(const char *path) unsigned int cond_get_gen(const char *path)
+2 -1
View File
@@ -3,7 +3,8 @@
#include <paths.h> #include <paths.h>
#define COND_PATH _PATH_VARRUN "finit/cond" #define COND_DIR "finit/cond"
#define COND_PATH _PATH_VARRUN COND_DIR
#define COND_RECONF COND_PATH "/reconf" #define COND_RECONF COND_PATH "/reconf"
typedef enum cond_state { typedef enum cond_state {
+24
View File
@@ -36,11 +36,15 @@
#include "service.h" #include "service.h"
#include "tty.h" #include "tty.h"
#include "helpers.h" #include "helpers.h"
#include "util.h"
#define BOOTSTRAP (runlevel == 0) #define BOOTSTRAP (runlevel == 0)
#define MATCH_CMD(l, c, x) \ #define MATCH_CMD(l, c, x) \
(!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c))) (!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
int logfile_size_max = 200000; /* 200 kB */
int logfile_count_max = 5;
struct rlimit global_rlimit[RLIMIT_NLIMITS]; struct rlimit global_rlimit[RLIMIT_NLIMITS];
struct conf_change { struct conf_change {
@@ -383,6 +387,26 @@ static void parse_static(char *line)
return; return;
} }
if (MATCH_CMD(line, "log ", x)) {
char *tok;
static int size = 200000, count = 5;
tok = strtok(x, ":= ");
while (tok) {
if (!strncmp(tok, "size", 4))
size = strtobytes(strtok(NULL, ":= "));
else if (!strncmp(tok, "count", 5))
count = strtobytes(strtok(NULL, ":= "));
tok = strtok(NULL, ":= ");
}
if (size >= 0)
logfile_size_max = size;
if (count >= 0)
logfile_count_max = count;
}
if (MATCH_CMD(line, "shutdown ", x)) { if (MATCH_CMD(line, "shutdown ", x)) {
if (sdown) free(sdown); if (sdown) free(sdown);
sdown = strdup(strip_line(x)); sdown = strdup(strip_line(x));
+3
View File
@@ -26,6 +26,9 @@
#include "svc.h" #include "svc.h"
extern int logfile_size_max;
extern int logfile_count_max;
extern struct rlimit global_rlimit[]; extern struct rlimit global_rlimit[];
int str2rlim(char *str); int str2rlim(char *str);
+10 -7
View File
@@ -303,7 +303,7 @@ int main(int argc, char* argv[])
conf_parse_cmdline(); conf_parse_cmdline();
/* Set up canvas */ /* Set up canvas */
if (!rescue) if (!rescue && !log_is_debug())
screen_init(); screen_init();
/* /*
@@ -320,7 +320,7 @@ int main(int argc, char* argv[])
* Load plugins early, finit.conf may contain references to * Load plugins early, finit.conf may contain references to
* features implemented by plugins. * features implemented by plugins.
*/ */
plugin_init(&loop, PLUGIN_PATH); plugin_init(&loop);
/* /*
* Hello world. * Hello world.
@@ -448,6 +448,9 @@ int main(int argc, char* argv[])
if (run_interactive("mount -na", "Mounting filesystems")) if (run_interactive("mount -na", "Mounting filesystems"))
plugin_run_hooks(HOOK_MOUNT_ERROR); plugin_run_hooks(HOOK_MOUNT_ERROR);
_d("Calling extra mount hook, after mount -a ...");
plugin_run_hooks(HOOK_MOUNT_POST);
run("swapon -ea"); run("swapon -ea");
umask(0022); umask(0022);
} }
@@ -455,17 +458,17 @@ int main(int argc, char* argv[])
/* Base FS up, enable standard SysV init signals */ /* Base FS up, enable standard SysV init signals */
sig_setup(&loop); sig_setup(&loop);
if (!rescue) {
_d("Base FS up, calling hooks ...");
plugin_run_hooks(HOOK_BASEFS_UP);
}
/* /*
* Set up inotify watcher for /etc/finit.d and read all .conf * Set up inotify watcher for /etc/finit.d and read all .conf
* files to figure out how to bootstrap the system. * files to figure out how to bootstrap the system.
*/ */
conf_monitor(&loop); conf_monitor(&loop);
if (!rescue) {
_d("Base FS up, calling hooks ...");
plugin_run_hooks(HOOK_BASEFS_UP);
}
/* /*
* Initalize state machine and start all bootstrap tasks * Initalize state machine and start all bootstrap tasks
* NOTE: no network available! * NOTE: no network available!
+12
View File
@@ -252,6 +252,7 @@ int sh(char *tty)
NULL NULL
}; };
size_t len; size_t len;
struct termios term;
/* Detach from initial controlling TTY */ /* Detach from initial controlling TTY */
vhangup(); vhangup();
@@ -282,6 +283,17 @@ int sh(char *tty)
snprintf(arg0, len, "-%s", _PATH_BSHELL); snprintf(arg0, len, "-%s", _PATH_BSHELL);
args[0] = arg0; args[0] = arg0;
/* Reenable Ctrl-D and Ctrl-C, and ... */
if (!tcgetattr(STDIN_FILENO, &term)) {
term.c_lflag |= ISIG;
term.c_cc[VEOF] = CTL('D');
term.c_cc[VINTR] = CTL('C');
tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
/* ... unblock signals in general */
sig_unblock();
return execv(_PATH_BSHELL, args); return execv(_PATH_BSHELL, args);
} }
+4 -2
View File
@@ -346,8 +346,10 @@ void inetd_stop(inetd_t *inetd)
_d("Stopping %s socket watcher ...", inetd->svc->cmd); _d("Stopping %s socket watcher ...", inetd->svc->cmd);
uev_io_stop(&inetd->watcher); uev_io_stop(&inetd->watcher);
/* For dgram inetd services we block the parent SVC /*
* and halt the watcher, so don't close the socket! */ * For dgram inetd services we block the parent SVC
* and halt the watcher, so don't close the socket!
*/
if (!svc_is_busy(inetd->svc)) { if (!svc_is_busy(inetd->svc)) {
_d("Shutting down inet socket %d ...", inetd->watcher.fd); _d("Shutting down inet socket %d ...", inetd->watcher.fd);
close(inetd->watcher.fd); close(inetd->watcher.fd);
+3 -3
View File
@@ -435,7 +435,7 @@ static int show_status(char *arg)
} }
if (!verbose) if (!verbose)
printheader(NULL, "# STATUS PID RUNLEVELS SERVICE DESCRIPTION", 0); printheader(NULL, "# STATUS PID RUNLEVELS SERVICE DESCRIPTION", 0);
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) { for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
char jobid[10], args[512] = "", *lvls; char jobid[10], args[512] = "", *lvls;
@@ -445,7 +445,7 @@ static int show_status(char *arg)
// else // else
snprintf(jobid, sizeof(jobid), "%d:%d", svc->job, svc->id); snprintf(jobid, sizeof(jobid), "%d:%d", svc->job, svc->id);
printf("%-5s %7s ", jobid, svc_status(svc)); printf("%-9s %7s ", jobid, svc_status(svc));
if (svc_is_inetd(svc)) if (svc_is_inetd(svc))
printf("inetd "); printf("inetd ");
else else
@@ -466,7 +466,7 @@ static int show_status(char *arg)
else else
name++; name++;
printf("%-20.20s %-*.*s\n", name, adj, adj, svc->desc); printf("%-16.16s %-*.*s\n", name, adj, adj, svc->desc);
continue; continue;
} }
+17
View File
@@ -29,6 +29,7 @@
#include "finit.h" #include "finit.h"
#include "log.h" #include "log.h"
#include "util.h"
static int up = 0; static int up = 0;
static int debug = 0; static int debug = 0;
@@ -65,6 +66,15 @@ void log_exit(void)
sched_yield(); sched_yield();
fputs("\n", stderr); fputs("\n", stderr);
} }
/*
* Unless in debug mode at shutdown, Reinitialize screen,
* terminal may have been resized at runtime
*/
if (debug)
screen_exit();
else
screen_init();
} }
void log_open(void) void log_open(void)
@@ -102,12 +112,19 @@ void log_debug(void)
if (debug) { if (debug) {
silent = 0; silent = 0;
loglevel = LOG_DEBUG; loglevel = LOG_DEBUG;
screen_exit();
} else { } else {
silent = SILENT_MODE; silent = SILENT_MODE;
loglevel = LOG_NOTICE; loglevel = LOG_NOTICE;
screen_init();
} }
log_open(); log_open();
/* Also toggle silent mode (progress) */
log_silent();
logit(LOG_NOTICE, "Debug mode %s", debug ? "enabled" : "disabled"); logit(LOG_NOTICE, "Debug mode %s", debug ? "enabled" : "disabled");
} }
+5 -3
View File
@@ -65,7 +65,7 @@ static int logrotate(char *file, int num, off_t sz)
snprintf(nfile, len, "%s.%d.gz", file, cnt); snprintf(nfile, len, "%s.%d.gz", file, cnt);
/* May fail because ofile doesn't exist yet, ignore. */ /* May fail because ofile doesn't exist yet, ignore. */
rename(ofile, nfile); (void)rename(ofile, nfile);
} }
for (cnt = num; cnt > 0; cnt--) { for (cnt = num; cnt > 0; cnt--) {
@@ -86,8 +86,10 @@ static int logrotate(char *file, int num, off_t sz)
} }
} }
rename(file, nfile); if (rename(file, nfile))
create(file, st.st_mode, st.st_uid, st.st_gid); (void)truncate(file, 0);
else
create(file, st.st_mode, st.st_uid, st.st_gid);
} else { } else {
if (truncate(file, 0)) if (truncate(file, 0))
syslog(LOG_ERR | LOG_PERROR, "Failed truncating %s during logrotate: %s", file, strerror(errno)); syslog(LOG_ERR | LOG_PERROR, "Failed truncating %s during logrotate: %s", file, strerror(errno));
+1 -21
View File
@@ -29,6 +29,7 @@
#include <unistd.h> #include <unistd.h>
#include <lite/lite.h> #include <lite/lite.h>
#include "pid.h"
#include "svc.h" #include "svc.h"
#include "helpers.h" #include "helpers.h"
@@ -92,27 +93,6 @@ char *pid_get_name(pid_t pid, char *name, size_t len)
return pname; return pname;
} }
char *pid_runpath(char *file, char *path, size_t len)
{
static int unknown = 1;
static char *prefix = "/var/run";
if (unknown) {
if (fisdir("/run"))
prefix = "/run";
unknown = 0;
}
if (!strncmp(file, "/var/run/", 9))
file += 9;
else if (!strncmp(file, "/run/", 5))
file += 5;
snprintf(path, len, "%s/%s", prefix, file);
return path;
}
char *pid_file(svc_t *svc) char *pid_file(svc_t *svc)
{ {
char fn[MAX_ARG_LEN]; char fn[MAX_ARG_LEN];
+27 -1
View File
@@ -22,6 +22,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef FINIT_PID_H_
#define FINIT_PID_H_
#include "svc.h"
int pid_alive (pid_t pid); int pid_alive (pid_t pid);
char *pid_get_name (pid_t pid, char *name, size_t len); char *pid_get_name (pid_t pid, char *name, size_t len);
@@ -29,7 +34,28 @@ char *pid_file (svc_t *svc);
int pid_file_create (svc_t *svc); int pid_file_create (svc_t *svc);
int pid_file_parse (svc_t *svc, char *arg); int pid_file_parse (svc_t *svc, char *arg);
char *pid_runpath (char *file, char *path, size_t len); static inline char *pid_runpath(char *file, char *path, size_t len)
{
static int unknown = 1;
static char *prefix = "/var/run";
if (unknown) {
if (fisdir("/run"))
prefix = "/run";
unknown = 0;
}
if (!strncmp(file, "/var/run/", 9))
file += 9;
else if (!strncmp(file, "/run/", 5))
file += 5;
snprintf(path, len, "%s/%s", prefix, file);
return path;
}
#endif /* FINIT_PID_H_ */
/** /**
* Local Variables: * Local Variables:
+5 -2
View File
@@ -108,6 +108,9 @@ int plugin_register(plugin_t *plugin)
/* Not called, at the moment plugins cannot be unloaded. */ /* Not called, at the moment plugins cannot be unloaded. */
int plugin_unregister(plugin_t *plugin) int plugin_unregister(plugin_t *plugin)
{ {
if (is_io_plugin(plugin))
uev_io_stop(&plugin->watcher);
#ifndef ENABLE_STATIC #ifndef ENABLE_STATIC
TAILQ_REMOVE(&plugins, plugin, link); TAILQ_REMOVE(&plugins, plugin, link);
@@ -382,11 +385,11 @@ static int load_plugins(char *path)
} }
#endif /* ENABLE_STATIC */ #endif /* ENABLE_STATIC */
int plugin_init(uev_ctx_t *ctx, char *path) int plugin_init(uev_ctx_t *ctx)
{ {
int fail = 1; int fail = 1;
if (!load_plugins(path)) if (!load_plugins(PLUGIN_PATH))
fail = init_plugins(ctx); fail = init_plugins(ctx);
return fail; return fail;
+1 -5
View File
@@ -24,16 +24,11 @@
#ifndef FINIT_PLUGIN_H_ #ifndef FINIT_PLUGIN_H_
#define FINIT_PLUGIN_H_ #define FINIT_PLUGIN_H_
#include <config.h>
#include <uev/uev.h> #include <uev/uev.h>
#include <lite/queue.h> /* BSD sys/queue.h API */ #include <lite/queue.h> /* BSD sys/queue.h API */
#include "svc.h" #include "svc.h"
#ifndef PLUGIN_PATH /* Fallback for --enable-static builds */
#define PLUGIN_PATH "/dev/null"
#endif
#define PLUGIN_DEP_MAX 10 #define PLUGIN_DEP_MAX 10
/* /*
@@ -73,6 +68,7 @@
CHOOSE(HOOK_BANNER = 0, "hook/sys/banner"), \ CHOOSE(HOOK_BANNER = 0, "hook/sys/banner"), \
CHOOSE(HOOK_ROOTFS_UP, "hook/mount/root"), \ CHOOSE(HOOK_ROOTFS_UP, "hook/mount/root"), \
CHOOSE(HOOK_MOUNT_ERROR, "hook/mount/error"), \ CHOOSE(HOOK_MOUNT_ERROR, "hook/mount/error"), \
CHOOSE(HOOK_MOUNT_POST, "hook/mount/post"), \
CHOOSE(HOOK_BASEFS_UP, "hook/mount/all"), \ CHOOSE(HOOK_BASEFS_UP, "hook/mount/all"), \
CHOOSE(HOOK_NETWORK_UP, "hook/net/up"), \ CHOOSE(HOOK_NETWORK_UP, "hook/net/up"), \
CHOOSE(HOOK_SVC_UP, "hook/svc/up"), \ CHOOSE(HOOK_SVC_UP, "hook/svc/up"), \
+1 -1
View File
@@ -45,7 +45,7 @@ int plugin_exists (hook_point_t no);
void plugin_run_hook (hook_point_t no, void *arg); void plugin_run_hook (hook_point_t no, void *arg);
void plugin_run_hooks (hook_point_t no); void plugin_run_hooks (hook_point_t no);
int plugin_init (uev_ctx_t *ctx, char *path); int plugin_init (uev_ctx_t *ctx);
void plugin_exit (void); void plugin_exit (void);
#endif /* FINIT_PRIVATE_H_ */ #endif /* FINIT_PRIVATE_H_ */
+84 -38
View File
@@ -63,7 +63,8 @@ static void service_timeout_cb(uev_t *w, void *arg, int events)
svc_t *svc = arg; svc_t *svc = arg;
/* Ignore any UEV_ERROR, we're a one-shot cb so just run it. */ /* Ignore any UEV_ERROR, we're a one-shot cb so just run it. */
svc->timer_cb(svc); if (svc->timer_cb)
svc->timer_cb(svc);
} }
/** /**
@@ -137,7 +138,7 @@ static int is_norespawn(void)
*/ */
static int service_start(svc_t *svc) static int service_start(svc_t *svc)
{ {
int i, result = 0; int i, result = 0, do_progress = 1;
pid_t pid; pid_t pid;
sigset_t nmask, omask; sigset_t nmask, omask;
@@ -160,10 +161,15 @@ static int service_start(svc_t *svc)
return inetd_start(&svc->inetd); return inetd_start(&svc->inetd);
#endif #endif
if (svc_is_daemon(svc)) if (!svc->desc[0])
print_desc("Starting ", svc->desc); do_progress = 0;
else
print_desc("", svc->desc); if (do_progress) {
if (svc_is_daemon(svc))
print_desc("Starting ", svc->desc);
else
print_desc("", svc->desc);
}
/* Declare we're waiting for svc to create its pidfile */ /* Declare we're waiting for svc to create its pidfile */
svc_starting(svc); svc_starting(svc);
@@ -266,7 +272,12 @@ static int service_start(svc_t *svc)
sig_unblock(); sig_unblock();
if (svc->log.file[0] == '/') { if (svc->log.file[0] == '/') {
execlp("logit", "logit", "-f", svc->log.file, NULL); char sz[20], num[3];
snprintf(sz, sizeof(sz), "%d", logfile_size_max);
snprintf(num, sizeof(num), "%d", logfile_count_max);
execlp("logit", "logit", "-f", svc->log.file, "-n", sz, "-r", num, NULL);
_exit(0); _exit(0);
} }
@@ -318,7 +329,7 @@ static int service_start(svc_t *svc)
#endif #endif
if (svc->log.enabled && !svc->log.null) if (svc->log.enabled && !svc->log.null)
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
exit(status); _exit(status);
} else if (log_is_debug()) { } else if (log_is_debug()) {
char buf[CMD_SIZE] = ""; char buf[CMD_SIZE] = "";
@@ -352,7 +363,8 @@ static int service_start(svc_t *svc)
pid_file_create(svc); pid_file_create(svc);
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
print_result(result); if (do_progress)
print_result(result);
/* /*
* Only run hook on successful start, and *after* having printed * Only run hook on successful start, and *after* having printed
@@ -381,10 +393,10 @@ static void service_kill(svc_t *svc)
return; return;
} }
_d("%s: Sending SIGKILL to pid:%d", pid_get_name(svc->pid, NULL, 0), svc->pid);
if (runlevel != 1) if (runlevel != 1)
print_desc("Killing ", svc->desc); print_desc("Killing ", svc->desc);
_d("%s: Sending SIGKILL to pid:%d", pid_get_name(svc->pid, NULL, 0), svc->pid);
kill(svc->pid, SIGKILL); kill(svc->pid, SIGKILL);
/* Let SIGKILLs stand out, show result as [WARN] */ /* Let SIGKILLs stand out, show result as [WARN] */
@@ -408,31 +420,31 @@ static int service_stop(svc_t *svc)
#ifdef INETD_ENABLED #ifdef INETD_ENABLED
if (svc_is_inetd(svc)) { if (svc_is_inetd(svc)) {
int do_print = runlevel != 1 && !svc_is_busy(svc); int do_progress = runlevel != 1 && !svc_is_busy(svc);
if (do_print) if (do_progress)
print_desc("Stopping ", svc->desc); print_desc("Stopping ", svc->desc);
inetd_stop(&svc->inetd); inetd_stop(&svc->inetd);
if (do_print) if (do_progress)
print_result(0); print_result(0);
svc_set_state(svc, SVC_STOPPING_STATE);
return 0; return 0;
} } else
#endif #endif
service_timeout_cancel(svc);
if (svc->pid <= 1) { if (svc->pid <= 1)
_d("Bad PID %d for %s, SIGTERM", svc->pid, svc->desc);
return 1; return 1;
}
if (SVC_TYPE_SERVICE != svc->type) _d("Sending SIGTERM to pid:%d name:%s", svc->pid, pid_get_name(svc->pid, NULL, 0));
return 0; svc_set_state(svc, SVC_STOPPING_STATE);
if (runlevel != 1) if (runlevel != 1)
print_desc("Stopping ", svc->desc); print_desc("Stopping ", svc->desc);
_d("Sending SIGTERM to pid:%d name:%s", svc->pid, pid_get_name(svc->pid, NULL, 0));
res = kill(svc->pid, SIGTERM); res = kill(svc->pid, SIGTERM);
if (runlevel != 1) if (runlevel != 1)
@@ -468,21 +480,25 @@ static int service_restart(svc_t *svc)
return 1; return 1;
} }
print_desc("Restarting ", svc->desc); _d("Sending SIGHUP to PID %d", svc->pid);
if (svc->desc[0])
print_desc("Restarting ", svc->desc);
rc = kill(svc->pid, SIGHUP);
/* Declare we're waiting for svc to re-assert/touch its pidfile */ /* Declare we're waiting for svc to re-assert/touch its pidfile */
svc_starting(svc); svc_starting(svc);
_d("Sending SIGHUP to PID %d", svc->pid);
rc = kill(svc->pid, SIGHUP);
/* Service does not maintain a PID file on its own */ /* Service does not maintain a PID file on its own */
if (svc_has_pidfile(svc)) { if (svc_has_pidfile(svc)) {
sched_yield(); sched_yield();
touch(pid_file(svc)); touch(pid_file(svc));
} }
return print_result(rc); if (svc->desc[0])
print_result(rc);
return rc;
} }
/** /**
@@ -624,6 +640,15 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
while (*desc && isblank(*desc)) while (*desc && isblank(*desc))
desc++; desc++;
} else {
int pos;
/* Find "--\n" to denote empty/no description */
pos = (int)strlen(line) - 2;
if (pos > 0 && !strcmp(&line[pos], "--")) {
line[pos] = 0;
desc = &line[pos];
}
} }
cmd = strtok(line, " "); cmd = strtok(line, " ");
@@ -822,8 +847,38 @@ recreate:
return 0; return 0;
} }
/*
* This function is called when cleaning up lingering (stopped) services
* after a .conf reload, as well as when an inetd connection terminates.
*
* We need to ensure we properly stop the service before removing it,
* including stopping any pending restart or SIGKILL timers before we
* proceed to free() the svc itself.
*
* Remember to not try to stop inetd connections, they only get here
* when already stopped, if we do we end up in a recursive loop.
*/
void service_unregister(svc_t *svc) void service_unregister(svc_t *svc)
{ {
if (!svc)
return;
/*
* Only try stopping @svc if it's *not* an inetd connection.
* Prevents infinite recursion when called from service_step()
*/
if (!svc_is_inetd_conn(svc))
service_stop(svc);
if (svc_is_inetd(svc)) {
if (svc_is_busy(svc->inetd.svc)) {
svc_unblock(svc->inetd.svc);
service_step(svc->inetd.svc);
}
inetd_del(&svc->inetd);
}
svc_del(svc); svc_del(svc);
} }
@@ -877,13 +932,13 @@ static void service_retry(svc_t *svc)
if (svc->state != SVC_HALTED_STATE || if (svc->state != SVC_HALTED_STATE ||
svc->block != SVC_BLOCK_RESTARTING) { svc->block != SVC_BLOCK_RESTARTING) {
_d("%s not crashing anymore", svc->desc); _d("%s not crashing anymore", svc->cmd);
*restart_cnt = 0; *restart_cnt = 0;
return; return;
} }
if (*restart_cnt >= RESPAWN_MAX) { if (*restart_cnt >= RESPAWN_MAX) {
logit(LOG_ERR, "%s keeps crashing, not restarting", svc->desc); logit(LOG_ERR, "%s keeps crashing, not restarting", svc->cmd);
svc_crashing(svc); svc_crashing(svc);
*restart_cnt = 0; *restart_cnt = 0;
service_step(svc); service_step(svc);
@@ -892,7 +947,7 @@ static void service_retry(svc_t *svc)
(*restart_cnt)++; (*restart_cnt)++;
_d("%s crashed, trying to start it again, attempt %d", svc->desc, *restart_cnt); _d("%s crashed, trying to start it again, attempt %d", svc->cmd, *restart_cnt);
svc_unblock(svc); svc_unblock(svc);
service_step(svc); service_step(svc);
@@ -944,10 +999,6 @@ restart:
case SVC_DONE_STATE: case SVC_DONE_STATE:
#ifdef INETD_ENABLED #ifdef INETD_ENABLED
if (svc_is_inetd_conn(svc)) { if (svc_is_inetd_conn(svc)) {
if (svc_is_busy(svc->inetd.svc)) {
svc_unblock(svc->inetd.svc);
service_step(svc->inetd.svc);
}
service_unregister(svc); service_unregister(svc);
return -1; return -1;
} }
@@ -1009,7 +1060,6 @@ restart:
case SVC_RUNNING_STATE: case SVC_RUNNING_STATE:
if (!enabled) { if (!enabled) {
service_stop(svc); service_stop(svc);
svc_set_state(svc, SVC_STOPPING_STATE);
break; break;
} }
@@ -1022,7 +1072,7 @@ restart:
* Restart directly after the first crash, * Restart directly after the first crash,
* then retry after 2 sec * then retry after 2 sec
*/ */
_d("delayed restart of %s", svc->desc); _d("delayed restart of %s", svc->cmd);
service_timeout_after(svc, 1, service_retry); service_timeout_after(svc, 1, service_retry);
break; break;
} }
@@ -1043,7 +1093,6 @@ restart:
switch (cond) { switch (cond) {
case COND_OFF: case COND_OFF:
service_stop(svc); service_stop(svc);
svc_set_state(svc, SVC_STOPPING_STATE);
break; break;
case COND_FLUX: case COND_FLUX:
@@ -1060,7 +1109,6 @@ restart:
service_restart(svc); service_restart(svc);
} else { } else {
service_stop(svc); service_stop(svc);
svc_set_state(svc, SVC_STOPPING_STATE);
} }
svc_mark_clean(svc); svc_mark_clean(svc);
} }
@@ -1072,7 +1120,6 @@ restart:
if (!enabled) { if (!enabled) {
kill(svc->pid, SIGCONT); kill(svc->pid, SIGCONT);
service_stop(svc); service_stop(svc);
svc_set_state(svc, SVC_STOPPING_STATE);
break; break;
} }
@@ -1092,7 +1139,6 @@ restart:
case COND_OFF: case COND_OFF:
kill(svc->pid, SIGCONT); kill(svc->pid, SIGCONT);
service_stop(svc); service_stop(svc);
svc_set_state(svc, SVC_STOPPING_STATE);
break; break;
case COND_FLUX: case COND_FLUX:
+3 -1
View File
@@ -133,7 +133,9 @@ void do_kill(int signo)
continue; continue;
if (fgets(file, sizeof(file), fp)) { if (fgets(file, sizeof(file), fp)) {
if (file[0] != '@') if (strstr(file, "gdbserver"))
_d("Skipping %s ...", file);
else if (file[0] != '@')
kill(pid, signo); kill(pid, signo);
else else
_d("Skipping %s ...", &file[1]); _d("Skipping %s ...", &file[1]);
+2 -4
View File
@@ -74,7 +74,7 @@ svc_t *svc_new(char *cmd, int id, int type)
strlcpy(svc->cmd, cmd, sizeof(svc->cmd)); strlcpy(svc->cmd, cmd, sizeof(svc->cmd));
/* Default description, if missing */ /* Default description, if missing */
desc = rindex(cmd, '/'); desc = strrchr(cmd, '/');
if (desc) if (desc)
desc++; desc++;
else else
@@ -408,10 +408,8 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
svc_t *svc, *iter = NULL; svc_t *svc, *iter = NULL;
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
if (svc->dirty == -1 && cb) { if (svc->dirty == -1 && cb)
cb(svc); cb(svc);
svc_mark_clean(svc);
}
} }
} }
+50 -6
View File
@@ -25,6 +25,7 @@
#include <ctype.h> /* isprint() */ #include <ctype.h> /* isprint() */
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/sysinfo.h> /* sysinfo() */ #include <sys/sysinfo.h> /* sysinfo() */
#include <lite/lite.h> /* strlcat() */ #include <lite/lite.h> /* strlcat() */
@@ -45,18 +46,41 @@ char *progname(char *arg0)
return prognm; return prognm;
} }
int strtobytes(char *arg)
{
int mod = 0, bytes;
size_t pos;
if (!arg)
return -1;
pos = strspn(arg, "0123456789");
if (arg[pos] != 0) {
if (arg[pos] == 'G')
mod = 3;
else if (arg[pos] == 'M')
mod = 2;
else if (arg[pos] == 'k')
mod = 1;
else
return -1;
arg[pos] = 0;
}
bytes = atoi(arg);
while (mod--)
bytes *= 1000;
return bytes;
}
void do_sleep(unsigned int sec) void do_sleep(unsigned int sec)
{ {
while ((sec = sleep(sec))) while ((sec = sleep(sec)))
; ;
} }
/* Allowed characters in job/id/name */
static int isallowed(int ch)
{
return isprint(ch);
}
/* Seconds since boot, from sysinfo() */ /* Seconds since boot, from sysinfo() */
long jiffies(void) long jiffies(void)
{ {
@@ -108,6 +132,12 @@ char *uptime(long secs, char *buf, size_t len)
return buf; return buf;
} }
/* Allowed characters in job/id/name */
static int isallowed(int ch)
{
return isprint(ch);
}
/* Sanitize user input, make sure to NUL terminate. */ /* Sanitize user input, make sure to NUL terminate. */
char *sanitize(char *arg, size_t len) char *sanitize(char *arg, size_t len)
{ {
@@ -127,6 +157,10 @@ char *sanitize(char *arg, size_t len)
return NULL; return NULL;
} }
/*
* Called at boot, and shutdown, to (re)initialize the
* screen size for print() et al.
*/
void screen_init(void) void screen_init(void)
{ {
if (!isatty(STDOUT_FILENO)) if (!isatty(STDOUT_FILENO))
@@ -135,6 +169,16 @@ void screen_init(void)
initscr(&screen_rows, &screen_cols); initscr(&screen_rows, &screen_cols);
} }
/*
* Called when debug mode is enabled to revert back
* to old-school safe defaults.
*/
void screen_exit(void)
{
screen_rows = 24;
screen_cols = 80;
}
/** /**
* Local Variables: * Local Variables:
* indent-tabs-mode: t * indent-tabs-mode: t
+2
View File
@@ -39,6 +39,7 @@ extern char *prognm;
#include <lite/conio.h> #include <lite/conio.h>
char *progname (char *arg0); char *progname (char *arg0);
int strtobytes (char *arg);
void do_sleep (unsigned int sec); void do_sleep (unsigned int sec);
long jiffies (void); long jiffies (void);
@@ -47,6 +48,7 @@ char *uptime (long secs, char *buf, size_t len);
char *sanitize (char *arg, size_t len); char *sanitize (char *arg, size_t len);
void screen_init (void); void screen_init (void);
void screen_exit (void);
int screen_width (void); int screen_width (void);
#endif /* FINIT_UTIL_H_ */ #endif /* FINIT_UTIL_H_ */