Compare commits

..
43 Commits
Author SHA1 Message Date
Joachim Nilsson a822a7657c Update ChangeLog and bump version for v2.4 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-04 19:15:48 +01:00
Joachim Nilsson e46271c1a9 Revert change in v2.3 listing stopped services as "paused"
Stopped services are now (again) listed as "stopped" and halted
services, due to a runlevel change, are listed as "halted". Several
users complained that this change was just not intuitive. I agreee.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-04 19:05:35 +01:00
Joachim Nilsson 1028725079 Add support for 'initctl show dropbear:2'
By popular request, this patch adds support for querying status of a
single service.  The syntax is similar to that of stop/start/reload.

Both `initctl show ...` and `initctl status ...` is supported.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-03 20:05:25 +01:00
Joachim Nilsson ed5ee667ae [Patch 2/2]: Make sure to start/SIGHUP services when none were stopped
When no services were stopped we must ensure to start/SIGHUP any new or
SIGHUP:able services as the last pass of the `initctl reload` cycle.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-02 13:06:16 +01:00
Joachim Nilsson 4c3e053041 [Patch 1/2]: System reconfiguration causing system freeze
This patch fixes a hang when performing a system reconfiguration using
`initctl reload`, `SIGHUP` or running `(f)init q`, which caused Finit
to wait for SIGHUP:able services to stop.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-02 13:02:40 +01:00
Joachim Nilsson a5c5a5c644 Allow debug mode to override terse mode
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-01 22:36:16 +01:00
Joachim Nilsson fa3a97366c Update Debugging section, all interesting stuff is in configure now
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-01 22:30:08 +01:00
Joachim Nilsson 5b3e3da7ff Attempt to clarify how BusyBox getty works wrt. the TTY device path
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-01 22:24:21 +01:00
Joachim Nilsson 59d96f264d Reenable verbose mode at reboot, if disabled at boot
This patch reenables verbose mode at shutdown/reboot, if it was disabled
at boot.  This allows the user to see the output from the `urandom.so`
and `hwclock.so` plugins at reboot.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-30 22:31:48 +01:00
Joachim Nilsson 7027cbc439 Enforce terse mode after boot, if verbose is disabled
The urandom.so plugin uncovered that `print_desc()` does not honor the
`verbose` flag.  At runtime `print_desc()` et al should no be displaying
anyting when we finit operates in terse mode.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-30 19:45:27 +01:00
Joachim Nilsson 8218fff7e5 Update ChangeLog and bump version for v2.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-28 13:59:47 +01:00
Joachim Nilsson 263e23a0df initctl: Support for stop/start services by name:id
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 21:22:05 +01:00
Joachim Nilsson 1f88e1ff8a Refactor svc_status() used by 'initctl show'
Leverage new svc_t states in initctl status/show output.  Also, ensure
different svc_t types have correct start state.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 20:51:04 +01:00
Joachim Nilsson b4ccc8b008 Clean up bootstrap-only tasks when leaving bootstrap 'S' runlevel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 20:22:24 +01:00
Joachim Nilsson 8df2b7b6e9 service_stop_dynamic(): Skip already stopped and HALT removed services
new postponed stop handling tried to reload already stopped and removed
services.  We should of course skip already stopped services and halt
those that have been removed.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-26 19:13:39 +01:00
Joachim Nilsson 8073f7cf27 Revert semantic change in 'initctl restart' introduced in 924bf04
This patch reverts the change in behavior introduced in Finit v2.2,
commit 924bf041, where `initctl restart JOB` changed from 'stop + start'
to `SIGHUP` for services that support `SIGHUP`.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 10:14:18 +01:00
Joachim Nilsson e303e1f833 Fix column alignment in initctl show for services not in current runlevel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 09:36:56 +01:00
Joachim Nilsson 3ea4be9343 Fix NULL ptr dereference causing kernel panic
When `service_stop_done()` is called with a `NULL` argument and no
dynamic services have been stopped, this regression is triggered.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-25 09:30:53 +01:00
Joachim Nilsson d8188428ed Bump version for v2.2 release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 13:20:44 +01:00
Joachim Nilsson d9f1882204 Update ChangeLog and prepare for release of v2.2
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 00:59:04 +01:00
Joachim Nilsson 4d899851cc Upgrade libite (LITE) to v1.2.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 00:45:55 +01:00
Joachim Nilsson ad8feca3e7 Upgrade libuEv to v1.2.4
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 00:45:20 +01:00
Joachim Nilsson 7569c479b8 Improve event debugging
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 22:18:56 +01:00
Joachim Nilsson e7db6c6ac6 Update README with latest changes to initctl help
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 22:18:40 +01:00
Joachim Nilsson f12535dc19 Clarify that the GW event to listen for in service declarations is GW:UP
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 22:18:15 +01:00
Tobias Waldekranz b19ea16e9d Only trigger on events that matches the service's specification
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
2015-11-22 19:59:01 +01:00
Joachim Nilsson eb59155dad Enable mdev logging when Finit runs in debug mode
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 19:53:44 +01:00
Joachim Nilsson f38dfaf2dc Pretty printing of current runlevel in initctl show
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 15:58:32 +01:00
Joachim Nilsson 4ada42f380 Add debug flag to initctl client tool
This patch makes it possible to see debug traces when running the client
program initctl, using `--debug`.  Please note, this does not affect the
debug command to the daemon.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 15:57:56 +01:00
Joachim Nilsson 924bf041bc On reload/restart we must wait for services to stop first
This patch adds support for declaring *why* a service is being stopped
or reloaded.  This is later used when all stopped services have been
collected by the `service_monitor()` to issue start or postponed SIGHUP.

As an added benefit we can now also see why a service is not running.
If it has been paused by a user, halted when moving to another runlevel,
waiting for a condition (event), or similar.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 10:11:27 +01:00
Joachim Nilsson b1d57d6828 Set default value for svc->sighup, even if service has no event mask
The `initctl reload <JOB>` command did not work properly.  This
was due to the service not being properly initialized to default
settings when reading the Finit configuration file.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-22 10:05:57 +01:00
Joachim Nilsson 87f9b94b42 Call HOOK_SVC_RECONF only when all processes have been stopped
This patch fixes a race condition when doing an ordered RELOAD and STOP
event sequence.  For services that shall be stopped it is imperative
that we wait for them to be colleced by the `service_monitor()`, so that
we know they have really been stopped, before calling HOOK_SVC_RECONF.

The latter is a promise to external services that all services have been
indeed stopped.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-19 19:29:16 +01:00
Joachim Nilsson c8f0b97d0f tty.c: Handle EINVAL and use recommended inotify event size.
The TTY plugin might fail in read() with EINVAL if the inotify event
buffer is too small.  Fix: set the receive event buffer to the size
recommended in inotify(7).  Also add a handler for EINVAL to close and
reinitialize the inotify descriptor so we do not accidentally overrun
the CPU with any unhandled errors.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 04:33:51 +01:00
Joachim Nilsson f902505b5d Declare name for all plugins, needed for static builds.
When building a static Finit the plugins do not get a unique name
automatically from the file.  This led to only the first plugin being
loaded, since its name was 'unknown' it was registered as such and all
other plugins conflicted, since 'unknown' was already ... known and
loaded.

This patch gives all plugins a default name, __FILE__, making it
possible to use all of them when building a static Finit.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 03:44:43 +01:00
Joachim Nilsson a6b78d57c0 Clarify why we must define the name for inetd plugins.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 03:39:05 +01:00
Joachim Nilsson a33478d563 Improve urandom plugin for embedded systems w/o random seed.
For embedded systems with no initial random seed, usually stored in
/var/lib/urandom/urandom-seed on desktops, servers and laptops, we now
provide an initial seed file using a built-in PRNG.

Also, let the configure script default to *enable* the random seeding
at boot, granted the urandom plugin is enabled.  We should encourage
users to properly seed their random, for security reasons.

Moreover, the plugin did not properly regenerate the random seed on
reboot, or shutdown, this patch also rectifies that problem.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 03:31:19 +01:00
Joachim Nilsson 369fcf2100 Issue #14: Improved support for static Finit builds
- Upgrade libite (LITE) for new UNIX file parser API to improve static
  builds of Finit.
- Re-enable bootmisc plugin for static builds by adding built-in support
  for reading GID from /etc/group.
- Allow inetd support for static builds by adding built-in support for
  reading service and protocol from /etc/services and /etc/protocols.
- Do not try to install/uninstall any plugins for static builds.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 00:56:50 +01:00
Joachim Nilsson b2c5e97417 Disable bootmisc plugin entirely if configure --enable-static
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 19:01:19 +02:00
Joachim Nilsson 8725200260 Build fixes for configure --disable-inetd
service.c:
	Don't declare find_inetd_svc() if inetd is disabled.
api.c:
	Disable inetd API
initctl.c:
	Disable presentation of inetd services

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 18:59:20 +02:00
Joachim Nilsson 58980c72fa Misc. fixes to silence warnings when building a static Finit.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 18:39:46 +02:00
Joachim Nilsson bcc70ec774 Update libite and libuev to handle static builds.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 18:38:47 +02:00
Joachim Nilsson 44579cc089 README: Clarify how arguments to ./configure --with-plugins= work
This should help clarify any misunderstandings detailed in issue #13.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 15:19:01 +02:00
Joachim Nilsson da361f460d Update ChangeLog slightly, off by one fix
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-16 20:56:56 +02:00
32 changed files with 604 additions and 144 deletions
+88 -2
View File
@@ -1,7 +1,89 @@
Change Log Change Log
========== ==========
All notable changes to the project are documented in this file. All relevant changes are documented in this file.
[2.4][] - 2015-12-04
--------------------
Bug fix release.
### Changes
* Add support for status/show service by `name:id`
* Enforce terse mode after boot, if verbose mode is disabled
* Reenable verbose mode at reboot, if disabled at boot
* Update section mentioning BusyBox getty
* Update debugging documentation
* Allow debug to override terse mode
* Revert confusing change in service state introduced in [v2.3][].
As of v2.4 services are listed as "halted" and "stopped", when
they have been halted due to a runlevel changed or stopped by
the user, respectively.
### Fixes
* Fix system freeze at reconfiguration. Changed services that
all support `SIGHUP` caused a freeze due to Finit waiting for
them to stop.
* Make sure to start and/or `SIGHUP` services after reconfiguration
when there was no services to stop.
[2.3][] - 2015-11-28
--------------------
Bug fix release.
### Changes
* Add support for stop/start/restart/reload service by `name:id`
* Refactor service status listed in `initctl show`, show actual status
### Fixes
* Remove bootstrap-only tasks/services when leaving runlevel 'S'
* Fix reference counting issue with already stopped and removed services
when the user performs `initctl reload` to change system configuration
* Revert semantic change in behavior of `initctl restart`: users expect
service to be stopped/started, not reloaded with `SIGHUP` even if the
service supports it
* Fix `NULL` pointer dereference causing kernel panic when user calls
`initctl reload` after change of system configuration
* Fix column alignment in output of `initctl show` for services not in
current runlevel
[2.2][] - 2015-11-23
--------------------
Lots of fixes to handle static builds, but also fixes for dynamic event
handling and reconfiguration at runtime.
### Changes
* Upgrade to libuEv v1.2.4, to handle static builds
* Upgrade to libite (LITE) v1.2.0, to handle static builds
* Clarify how to select different plugins with the configure script
* Improve urandom plugin for embedded systems w/o random seed
* Add `--debug` flag to `initctl`
* The runlevels listed for services in `initctl show` now hightlight the
active runlevel.
* Clarify in the README and in `initctl help` that the GW event to
listen for in service declarations is `GW:UP`
### Fixes
* Build fixes for `configure --disable-inetd`
* Fixed issue #14: Improved support for static Finit builds
* Misc. fixes to silence warnings when building a static Finit
* Default to register services as `SIGHUP`'able, regression in v2.0
* Call `HOOK_SVC_RECONF` only when all processes have been stopped
* On reload/reconf we must wait for all services to stop first
* Only trigger on events that matches the service's specification,
fix by Tobias Waldekranz
[2.1][] - 2015-10-16 [2.1][] - 2015-10-16
-------------------- --------------------
@@ -20,6 +102,7 @@ All notable changes to the project are documented in this file.
* Do not allow build VERSION to be overloaded by an environment variable * Do not allow build VERSION to be overloaded by an environment variable
* Fix too small MAX arguments and too few argments in `svc_t` for * Fix too small MAX arguments and too few argments in `svc_t` for
reading currently running services with `initctl show` reading currently running services with `initctl show`
* Unblock blocked signals after forking off a child
[2.0][] - 2015-09-20 [2.0][] - 2015-09-20
@@ -399,7 +482,10 @@ Major bug fix release.
* Initial release * Initial release
[UNRELEASED]: https://github.com/troglobit/finit/compare/2.1...HEAD [UNRELEASED]: https://github.com/troglobit/finit/compare/2.4...HEAD
[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.2]: https://github.com/troglobit/finit/compare/2.1...2.2
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1 [2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0 [2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12 [1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
+1 -1
View File
@@ -26,7 +26,7 @@
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 = 2.1 VERSION = 2.4
NAME = finit NAME = finit
PKG = $(NAME)-$(VERSION) PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev DEV = $(NAME)-dev
+36 -22
View File
@@ -197,6 +197,11 @@ Syntax:
See `finit.h` for the `#define GETTY` that is called, along with the See `finit.h` for the `#define GETTY` that is called, along with the
default baud rate. default baud rate.
**Note:** BusyBox getty, used when Finit is built for embedded
systems, can take a `DEV` with *or* without `/dev/` prefix. Make
sure to call the configure script with `--enable-embedded` if this
is what you want.
* `console <DEV | /path/to/cmd [args]>` * `console <DEV | /path/to/cmd [args]>`
Some embedded systems have a dedicated serial console/service port. Some embedded systems have a dedicated serial console/service port.
This command tells finit to not start getty directly, since there may This command tells finit to not start getty directly, since there may
@@ -586,22 +591,25 @@ not return until the given command has fully completed.
Usage: initctl [OPTIONS] <COMMAND> Usage: initctl [OPTIONS] <COMMAND>
Options: Options:
-v, --verbose Verbose output -d, --debug Debug initctl (client)
-h, --help This help text -v, --verbose Verbose output
-h, --help This help text
Commands: Commands:
debug Toggle init daemon debug debug Toggle Finit (daemon) debug
emit <EV> Emit an event: RELOAD, STOP, START, GW help This help text
IFUP:IFNAME, IFDN:IFNAME emit <EV> Emit event; a predefined event: RELOAD, STOP, START
IFNAME is the interface name, e.g. eth0 or a custom string matching an event in a service
reload Reload *.conf in /etc/finit.d/, like SIGHUP stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME. Where
runlevel <0-9> Change runlevel: 0 (halt), 6 (reboot) IFNAME is the interface name, e.g. eth0
start <JOB#> Start a stopped service reload Reload *.conf in /etc/finit.d/ and activate changes
stop <JOB#> Stop a running service runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
restart <JOB#> Restart (stop/start) a running service status | show Show status of services
reload <JOB#> Reload (SIGHUP) a running service start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
status | show List status of all services known to Finit stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
version Show Finit version restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name
version Show Finit version
``` ```
The `emit <EV>` command can be used to send events to Finit. Built-in The `emit <EV>` command can be used to send events to Finit. Built-in
@@ -610,6 +618,11 @@ their command counterparts. The `reload` command reloads all `*.conf`
files in `/etc/finit.d/` *and* activates the changes, with `emit RELOAD` files in `/etc/finit.d/` *and* activates the changes, with `emit RELOAD`
only the `*.conf` files are reloaded. only the `*.conf` files are reloaded.
**Note:** The `emit STOP` event is more like "prepare" than "stop".
Depending on how the service is declared, `<!>` or not, the service
may be stopped, or skipped to be be sent `SIGHUP` later when `emit
START` is issued.
To achieve the same result as `initctl reload` emit all three events: To achieve the same result as `initctl reload` emit all three events:
```shell ```shell
@@ -643,10 +656,10 @@ started.
The `emit <EV>` command can also be used to emit custom events. In The `emit <EV>` command can also be used to emit custom events. In
fact, the event is a simple string. Declare a list of events in a fact, the event is a simple string. Declare a list of events in a
service stanza: `service … <GW,IFUP:eth0>` to reload (`SIGHUP`) a service stanza: `service … <GW:UP,IFUP:eth0>` to reload (`SIGHUP`) a
service when recieving the `"GW"` or `"IFUP:eth0"` strings. If a service when recieving the `"GW:UP"` or `"IFUP:eth0"` strings. If a
service cannot handle reload and must be stopped-started, simply add an service cannot handle reload and must be stopped-started, simply add an
exclamation mark first: `service … <!GW,IFUP:eth0>`. exclamation mark first: `service … <!GW:UP,IFUP:eth0>`.
The `<!>` notation to a service stanza can be used empty, then it will The `<!>` notation to a service stanza can be used empty, then it will
apply to `reload` and `runlevel` commands. I.e., when a service's apply to `reload` and `runlevel` commands. I.e., when a service's
@@ -706,7 +719,8 @@ switches to configure:
* `--with-plugins=`: List of stock finit plugins to build and install. * `--with-plugins=`: List of stock finit plugins to build and install.
The build system adds `.o` or `.so` extension to the listed plugins The build system adds `.o` or `.so` extension to the listed plugins
depending on the `--enable-static` switch. depending on the `--enable-static` switch. Hence, list the plugins
*without* their extension.
* `--enable-embedded`: Target finit for BusyBox getty and mdev instead * `--enable-embedded`: Target finit for BusyBox getty and mdev instead
of a standard Linux distribution with GNU tools and udev. of a standard Linux distribution with GNU tools and udev.
@@ -754,7 +768,7 @@ First, unpack the archive:
Then configure, build and install: Then configure, build and install:
```shell ```shell
$ ./configure --with-plugins="initctl.so hwclock.so" $ ./configure --with-plugins="initctl hwclock"
$ make $ make
CC finit.o CC finit.o
CC conf.o CC conf.o
@@ -814,9 +828,9 @@ give the kernel the following extra command line:
Debugging Debugging
--------- ---------
Add `finit_debug`, or `--debug`, to the kernel command line to Add `finit_debug`, or `--debug`, to the kernel command line to enable
enable trace messages. A console getty is always started, see the file debug messages. See the output from `configure --help` for more on
`finit.h` for more useful compile-time tweaks: how to assist debugging.
```shell ```shell
init=/sbin/finit --debug init=/sbin/finit --debug
+27 -8
View File
@@ -30,6 +30,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include "config.h"
#include "finit.h" #include "finit.h"
#include "conf.h" #include "conf.h"
#include "helpers.h" #include "helpers.h"
@@ -76,10 +77,10 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
token = strtok_r(input, " ", &pos); token = strtok_r(input, " ", &pos);
while (token) { while (token) {
svc_t *svc; svc_t *svc;
char *ptr = strchr(token, ':');
if (isdigit(token[0])) { if (isdigit(token[0])) {
int job = atonum(token); int job = atonum(token);
char *ptr = strchr(token, ':');
if (!ptr) { if (!ptr) {
svc = svc_job_iterator(1, job); svc = svc_job_iterator(1, job);
@@ -94,10 +95,15 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
} }
} else { } else {
svc = svc_named_iterator(1, token); if (!ptr) {
while (svc) { svc = svc_named_iterator(1, token);
result += action(svc); while (svc) {
svc = svc_named_iterator(0, token); result += action(svc);
svc = svc_named_iterator(0, token);
}
} else {
*ptr++ = 0;
result += action(svc_find_by_nameid(token, atonum(ptr)));
} }
} }
@@ -107,11 +113,17 @@ static int call(int (*action)(svc_t *), char *buf, size_t len)
return result; return result;
} }
static int service_pause(svc_t *svc)
{
return service_stop(svc, SVC_PAUSED_STATE);
}
static int do_start (char *buf, size_t len) { return call(service_start, buf, len); } static int do_start (char *buf, size_t len) { return call(service_start, buf, len); }
static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); } static int do_pause (char *buf, size_t len) { return call(service_pause, buf, len); }
static int do_reload (char *buf, size_t len) { return call(service_reload, buf, len); } static int do_reload (char *buf, size_t len) { return call(service_reload, buf, len); }
static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); } static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); }
#ifndef INETD_DISABLED
static int do_query_inetd(char *buf, size_t len) static int do_query_inetd(char *buf, size_t len)
{ {
int id = 1; int id = 1;
@@ -135,6 +147,7 @@ static int do_query_inetd(char *buf, size_t len)
return inetd_filter_str(&svc->inetd, buf, len); return inetd_filter_str(&svc->inetd, buf, len);
} }
#endif /* !INETD_DISABLED */
typedef struct { typedef struct {
char *event; char *event;
@@ -253,9 +266,13 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events))
case INIT_CMD_DEBUG: case INIT_CMD_DEBUG:
debug = !debug; debug = !debug;
if (debug)
verbose = 1;
else
verbose = quiet ? 0 : VERBOSE_MODE;
break; break;
case INIT_CMD_RELOAD: case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
service_reload_dynamic(); service_reload_dynamic();
break; break;
@@ -264,7 +281,7 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events))
break; break;
case INIT_CMD_STOP_SVC: case INIT_CMD_STOP_SVC:
result = do_stop(rq.data, sizeof(rq.data)); result = do_pause(rq.data, sizeof(rq.data));
break; break;
case INIT_CMD_RELOAD_SVC: case INIT_CMD_RELOAD_SVC:
@@ -275,9 +292,11 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events))
result = do_restart(rq.data, sizeof(rq.data)); result = do_restart(rq.data, sizeof(rq.data));
break; break;
#ifndef INETD_DISABLED
case INIT_CMD_QUERY_INETD: case INIT_CMD_QUERY_INETD:
result = do_query_inetd(rq.data, sizeof(rq.data)); result = do_query_inetd(rq.data, sizeof(rq.data));
break; break;
#endif
case INIT_CMD_EMIT: case INIT_CMD_EMIT:
result = do_handle_emit(rq.data, sizeof(rq.data)); result = do_handle_emit(rq.data, sizeof(rq.data));
+9 -5
View File
@@ -116,18 +116,21 @@ int conf_parse_runlevels(char *runlevels)
void conf_parse_events(svc_t *svc, char *events) void conf_parse_events(svc_t *svc, char *events)
{ {
size_t i = 0; size_t i = 0;
char *ptr = events; char *ptr;
if (!events)
return;
if (!svc) { if (!svc) {
_e("Invalid service pointer"); _e("Invalid service pointer");
return; return;
} }
/* First character must be '!' if SIGHUP is not supported. */ /* By default we assume UNIX daemons support SIGHUP */
svc->sighup = 1; svc->sighup = 1;
if (!events)
return;
/* First character must be '!' if SIGHUP is not supported. */
ptr = events;
if (ptr[i] == '!') { if (ptr[i] == '!') {
svc->sighup = 0; svc->sighup = 0;
ptr++; ptr++;
@@ -142,6 +145,7 @@ void conf_parse_events(svc_t *svc, char *events)
return; return;
} }
svc->state = SVC_CONDHALT_STATE;
strlcpy(svc->events, ptr, sizeof(svc->events)); strlcpy(svc->events, ptr, sizeof(svc->events));
} }
Vendored
+4 -3
View File
@@ -22,6 +22,7 @@ defaults()
plugindir=${plugindir:="$libdir/$pdir"} plugindir=${plugindir:="$libdir/$pdir"}
# The initctl FIFO, should probably be in /run, not /dev # The initctl FIFO, should probably be in /run, not /dev
fifo=${fifo:="/dev/initctl"} fifo=${fifo:="/dev/initctl"}
random=${random:="/var/lib/urandom/random-seed"}
conf="finit.conf" conf="finit.conf"
config=${config:="$sysconfdir/$conf"} config=${config:="$sysconfdir/$conf"}
confdir=${confdir:="finit.d"} confdir=${confdir:="finit.d"}
@@ -149,9 +150,9 @@ usage()
echo " --with-fifo=FIFO FIFO for initctl plugin, default '$fifo'" echo " --with-fifo=FIFO FIFO for initctl plugin, default '$fifo'"
echo " --with-config=CONFIG Finit CONFIG file, default '\$sysconfdir/$conf'" echo " --with-config=CONFIG Finit CONFIG file, default '\$sysconfdir/$conf'"
echo " --with-heading=GREET Display GREET instead of Finit version at boot" echo " --with-heading=GREET Display GREET instead of Finit version at boot"
echo " --with-randomseed=SEED Seed /dev/urandom from file SEED. On Debian/Ubuntu" echo " --with-randomseed=SEED Seed /dev/urandom at boot from SEED. Usually found in"
echo " systems, set this to /var/lib/urandom/random-seed" echo " standard Linux systems at $random"
echo " Default: none" echo " which is also the default. Requires urandom plugin!"
echo " --with-plugins=\"a b c\" Build plugins 'a', 'b' and 'c', either as dynamic .so" echo " --with-plugins=\"a b c\" Build plugins 'a', 'b' and 'c', either as dynamic .so"
echo " files, or as built-in if --enable-static is given," echo " files, or as built-in if --enable-static is given,"
echo " defaults to all plugins. Exclude extension!" echo " defaults to all plugins. Exclude extension!"
+16 -10
View File
@@ -140,9 +140,14 @@ int event_cache_if(char *ifname)
return entry->updown; return entry->updown;
} }
static int validate_events(char *events) static int has_events(char *events)
{ {
return !events || !events[0]; return events && events[0];
}
static int matches_event(char *events, char *event)
{
return strcasestr(events, event) ? 1 : 0;
} }
int event_service_cond(char *events) int event_service_cond(char *events)
@@ -152,7 +157,7 @@ int event_service_cond(char *events)
char temp[MAX_ARG_LEN]; char temp[MAX_ARG_LEN];
/* No required events, condition satisfied */ /* No required events, condition satisfied */
if (validate_events(events)) if (!has_events(events))
return cond; return cond;
strlcpy(temp, events, sizeof(temp)); strlcpy(temp, events, sizeof(temp));
@@ -201,14 +206,16 @@ void event_dispatch(char *msg)
/* Iterate over svc_t and call service_restart() for event matches */ /* Iterate over svc_t and call service_restart() for event matches */
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
if (svc->type != SVC_TYPE_SERVICE || validate_events(svc->events)) if (svc->type != SVC_TYPE_SERVICE ||
!service_enabled(svc, 1, NULL) ||
!has_events(svc->events) ||
!matches_event(svc->events, msg)) {
_d("No match for %s in service %s", msg, svc->cmd);
continue; continue;
}
if (change == 1) { if (change == 1) {
if (!service_enabled(svc, 1, NULL)) _d("%s matches <%s> %s (re)starting ...", msg, svc->events, svc->cmd);
continue;
_d("Got event %s, (re)starting %s ...", svc->events, svc->cmd);
if (!svc->pid) { if (!svc->pid) {
service_start(svc); service_start(svc);
continue; continue;
@@ -220,12 +227,11 @@ void event_dispatch(char *msg)
service_restart(svc); service_restart(svc);
} else { /* change == -1 */ } else { /* change == -1 */
if (svc->pid && !event_service_cond(svc->events)) if (svc->pid && !event_service_cond(svc->events))
service_stop(svc); service_stop(svc, SVC_CONDHALT_STATE);
} }
} }
} }
/** /**
* Local Variables: * Local Variables:
* version-control: t * version-control: t
+7 -3
View File
@@ -43,9 +43,9 @@
int debug = 0; int debug = 0;
int quiet = KERNEL_QUIET; /* Delayed disable of verbose mode. */ int quiet = KERNEL_QUIET; /* Delayed disable of verbose mode. */
int verbose = VERBOSE_MODE; int verbose = VERBOSE_MODE;
int runlevel = 0; /* Bootstrap */ int runlevel = 0; /* Bootstrap 'S' */
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */ int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
int prevlevel = 0; /* HALT */ int prevlevel = -1;
char *sdown = NULL; char *sdown = NULL;
char *network = NULL; char *network = NULL;
char *username = NULL; char *username = NULL;
@@ -119,6 +119,10 @@ int main(int argc, char* argv[])
/* /*
* Populate /dev and prepare for runtime events from kernel. * Populate /dev and prepare for runtime events from kernel.
*/ */
#ifdef EMBEDDED_SYSTEM
if (debug)
touch("/dev/mdev.log");
#endif
run_interactive(SETUP_DEVFS, "Populating device tree"); run_interactive(SETUP_DEVFS, "Populating device tree");
/* /*
@@ -214,7 +218,7 @@ int main(int argc, char* argv[])
tty_runlevel(runlevel); tty_runlevel(runlevel);
/* Disable verbose mode, if selected */ /* Disable verbose mode, if selected */
if (quiet) if (quiet && !debug)
verbose = 0; verbose = 0;
/* Start new initctl API responder */ /* Start new initctl API responder */
+23 -4
View File
@@ -84,17 +84,27 @@ int runlevel_get(void)
*/ */
char *runlevel_string(int levels) char *runlevel_string(int levels)
{ {
int i, pos = 1;; int i, pos = 1;
static char lvl[10] = "[]"; static char lvl[20];
memset(lvl, 0, sizeof(lvl));
lvl[0] = '[';
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if (ISSET(levels, i)) { if (ISSET(levels, i)) {
if (runlevel == i)
pos = strlcat(lvl, "\e[1m", sizeof(lvl));
if (i == 0) if (i == 0)
lvl[pos++] = 'S'; lvl[pos++] = 'S';
else else
lvl[pos++] = '0' + i; lvl[pos++] = '0' + i;
if (runlevel == i)
pos = strlcat(lvl, "\e[0m", sizeof(lvl));
} }
} }
lvl[pos++] = ']'; lvl[pos++] = ']';
lvl[pos] = 0; lvl[pos] = 0;
@@ -132,6 +142,9 @@ void print(int action, const char *fmt, ...)
const char pending[] = " \e[1m[ \\/ ]\e[0m\n"; const char pending[] = " \e[1m[ \\/ ]\e[0m\n";
const char dots[] = " ....................................................................."; const char dots[] = " .....................................................................";
if (!verbose)
return;
if (fmt) { if (fmt) {
va_start(ap, fmt); va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap); len = vsnprintf(buf, sizeof(buf), fmt, ap);
@@ -174,27 +187,33 @@ int print_result(int fail)
return fail; return fail;
} }
#ifndef ENABLE_STATIC
int getuser(char *username) int getuser(char *username)
{ {
#ifdef ENABLE_STATIC
return fgetint("/etc/passwd", "x:\n", username);
#else
struct passwd *usr; struct passwd *usr;
if (!username || (usr = getpwnam(username)) == NULL) if (!username || (usr = getpwnam(username)) == NULL)
return -1; return -1;
return usr->pw_uid; return usr->pw_uid;
#endif
} }
int getgroup(char *group) int getgroup(char *group)
{ {
#ifdef ENABLE_STATIC
return fgetint("/etc/group", "x:\n", group);
#else
struct group *grp; struct group *grp;
if ((grp = getgrnam(group)) == NULL) if ((grp = getgrnam(group)) == NULL)
return -1; return -1;
return grp->gr_gid; return grp->gr_gid;
}
#endif #endif
}
/* Signal safe sleep ... we get a lot of SIGCHLD at reboot */ /* Signal safe sleep ... we get a lot of SIGCHLD at reboot */
void do_sleep(unsigned int sec) void do_sleep(unsigned int sec)
+29 -2
View File
@@ -212,12 +212,27 @@ void inetd_stop(inetd_t *inetd)
/* Stop any running service, not allowed anymore. */ /* Stop any running service, not allowed anymore. */
if (svc->pid) if (svc->pid)
service_stop(svc); service_stop(svc, SVC_WAITING_STATE);
} }
static int getent(char *service, char *proto, struct servent **sv, struct protoent **pv) static int getent(char *service, char *proto, struct servent **sv, struct protoent **pv)
{ {
#ifdef ENABLE_STATIC
int service_num;
static struct servent lfs;
service_num = fgetint("/etc/services", " \n\t", service);
if (service_num > 0) {
lfs.s_name = service;
lfs.s_port = htons(service_num);
lfs.s_proto = NULL;
if (!strcmp("tcp", proto) || !strcmp("udp", proto))
lfs.s_proto = proto;
*sv = &lfs;
}
#else
*sv = getservbyname(service, proto); *sv = getservbyname(service, proto);
#endif
if (!*sv) { if (!*sv) {
const char *errstr; const char *errstr;
static struct servent s; static struct servent s;
@@ -238,8 +253,20 @@ static int getent(char *service, char *proto, struct servent **sv, struct protoe
*sv = &s; *sv = &s;
} }
if (pv) { if (pv && (*sv)->s_proto) {
#ifdef ENABLE_STATIC
int proto_num;
static struct protoent lfp;
proto_num = fgetint("/etc/protocols", " \n\t", (*sv)->s_proto);
if (proto_num > 0) {
lfp.p_name = proto;
lfp.p_proto = proto_num;
}
*pv = &lfp;
#else
*pv = getprotobyname((*sv)->s_proto); *pv = getprotobyname((*sv)->s_proto);
#endif
if (!*pv) { if (!*pv) {
_e("Cannot find proto %s, skipping.", (*sv)->s_proto); _e("Cannot find proto %s, skipping.", (*sv)->s_proto);
return errno = EINVAL; return errno = EINVAL;
+70 -27
View File
@@ -136,39 +136,70 @@ static int show_version(char *UNUSED(arg))
/* In verbose mode we skip the header and each service description. /* In verbose mode we skip the header and each service description.
* This in favor of having all info on one line so a machine can more * This in favor of having all info on one line so a machine can more
* easily parse it. */ * easily parse it. */
static int show_status(char *UNUSED(arg)) static int show_status(char *arg)
{ {
svc_t *svc; svc_t *svc;
/* Fetch UTMP runlevel, needed for svc_status() call below */ /* Fetch UTMP runlevel, needed for svc_status() call below */
runlevel = runlevel_get(); runlevel = runlevel_get();
if (arg && arg[0]) {
int id = 1;
char *ptr, *next;
ptr = strchr(arg, ':');
if (ptr) {
*ptr++ = 0;
next = strchr(ptr, ' ');
if (next)
*next = 0;
id = atonum(ptr);
}
if (isdigit(arg[0]))
svc = svc_find_by_jobid(atonum(arg), id);
else
svc = svc_find_by_nameid(arg, id);
if (!svc)
return 1;
printf("%s\n", svc_status(svc));
return 0;
}
if (!verbose) { if (!verbose) {
printf("# Status PID Runlevels Service Description\n"); printf("# Status PID Runlevels Service Description\n");
printf("====================================================================================\n"); printf("====================================================================================\n");
} }
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
int inetd = svc_is_inetd(svc); char jobid[10], args[512] = "", *lvls;
char jobid[10], args[512] = "";
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_QUERY_INETD,
};
if (svc_is_unique(svc)) if (svc_is_unique(svc))
snprintf(jobid, sizeof(jobid), "%d", svc->job); snprintf(jobid, sizeof(jobid), "%d", svc->job);
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 %-6d %-9s ", jobid, svc_status(svc), svc->pid, runlevel_string(svc->runlevels)); printf("%-5s %7s %-6d ", jobid, svc_status(svc), svc->pid);
lvls = runlevel_string(svc->runlevels);
if (strchr(lvls, '\e'))
printf("%-18.18s ", lvls);
else
printf("%-10.10s ", lvls);
if (!verbose) { if (!verbose) {
printf("%-20s %s\n", svc->cmd, svc->desc); printf("%-20s %s\n", svc->cmd, svc->desc);
continue; continue;
} }
if (inetd) { #ifndef INETD_DISABLED
if (svc_is_inetd(svc)) {
char *info; char *info;
struct init_request rq = {
.magic = INIT_MAGIC,
.cmd = INIT_CMD_QUERY_INETD,
};
snprintf(rq.data, sizeof(rq.data), "%s", jobid); snprintf(rq.data, sizeof(rq.data), "%s", jobid);
if (do_send(&rq, sizeof(rq))) { if (do_send(&rq, sizeof(rq))) {
@@ -184,7 +215,10 @@ static int show_status(char *UNUSED(arg))
} }
printf("%s %s\n", svc->cmd, info); printf("%s %s\n", svc->cmd, info);
} else { }
else
#endif /* !INETD_DISABLED */
{
int i; int i;
for (i = 1; i < MAX_NUM_SVC_ARGS; i++) { for (i = 1; i < MAX_NUM_SVC_ARGS; i++) {
@@ -203,22 +237,26 @@ static int usage(int rc)
{ {
fprintf(stderr, "Usage: %s [OPTIONS] <COMMAND>\n\n" fprintf(stderr, "Usage: %s [OPTIONS] <COMMAND>\n\n"
"Options:\n" "Options:\n"
" -v, --verbose Verbose output\n" " -d, --debug Debug initctl (client)\n"
" -h, --help This help text\n\n" " -v, --verbose Verbose output\n"
" -h, --help This help text\n\n"
"Commands:\n" "Commands:\n"
" debug Toggle Finit debug\n" " debug Toggle Finit (daemon) debug\n"
" emit <EV> Emit an event. Can be a predefined event: RELOAD, STOP,\n" " help This help text\n"
" START, or a custom string to match the event list in a\n" " emit <EV> Emit event; a predefined event: RELOAD, STOP, START\n"
" service stanza, e.g: GW, IFUP:IFNAME, IFDN:IFNAME, where\n" " or a custom string matching an event in a service\n"
" IFNAME is the interface name, e.g. eth0\n" " stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME. Where\n"
" reload Reload *.conf in /etc/finit.d/ and activate changes\n" " IFNAME is the interface name, e.g. eth0\n"
" runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n" " reload Reload *.conf in /etc/finit.d/ and activate changes\n"
" status | show Show status of services\n" " runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n"
" start <JOB|NAME> Start stopped job or service\n" " status | show Show status of services\n"
" stop <JOB|NAME> Stop running job or service\n" " start <JOB|NAME>[:ID] Start service by job# or name, with optional ID\n"
" restart <JOB|NAME> Restart (stop/start) job or service\n" " stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name\n"
" reload <JOB|NAME> Reload (SIGHUP) job or service\n" " restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name\n"
" version Show Finit version\n\n", __progname); " reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name\n"
" status <JOB|NAME>[:ID] Show status of a service by job# or name\n"
" show <JOB|NAME>[:ID] Alias to 'status <JOB|NAME>[:ID]'\n"
" version Show Finit version\n\n", __progname);
return rc; return rc;
} }
@@ -241,17 +279,22 @@ int main(int argc, char *argv[])
}; };
struct option long_options[] = { struct option long_options[] = {
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"debug", 0, NULL, 'd'},
{"verbose", 0, NULL, 'v'}, {"verbose", 0, NULL, 'v'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
verbose = 0; verbose = 0;
while ((c = getopt_long(argc, argv, "h?v", long_options, NULL)) != EOF) { while ((c = getopt_long(argc, argv, "dh?v", long_options, NULL)) != EOF) {
switch(c) { switch(c) {
case 'h': case 'h':
case '?': case '?':
return usage(0); return usage(0);
case 'd':
debug = 1;
break;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
+1 -1
Submodule libite updated: bd9a618ea3...12ed342d55
+1 -1
Submodule libuev updated: a8d8705c34...cf5e729dd3
+5
View File
@@ -317,11 +317,16 @@ int plugin_load_all(uev_ctx_t *ctx, char *path)
closedir(dp); closedir(dp);
#else #else
_d("Finit built statically, not loading plugins from %s ...", path); _d("Finit built statically, not loading plugins from %s ...", path);
if (verbose)
print_desc("Initializing plugins", NULL);
#endif /* ENABLE_STATIC */ #endif /* ENABLE_STATIC */
/* Always initialize plugins */ /* Always initialize plugins */
init_plugins(ctx); init_plugins(ctx);
#ifndef ENABLE_STATIC
exit: exit:
#endif
if (verbose) if (verbose)
print_result(fail); print_result(fail);
+12
View File
@@ -14,7 +14,12 @@ endif
include ../common.mk include ../common.mk
ifneq ($(STATIC), 1)
all: $(PLUGINS) all: $(PLUGINS)
else
all:
@true
endif
clean: clean:
-@$(RM) $(PLUGINS) -@$(RM) $(PLUGINS)
@@ -22,6 +27,7 @@ clean:
distclean: distclean:
-@$(RM) *.o *.so $(JUNK) $(DEPS) -@$(RM) *.o *.so $(JUNK) $(DEPS)
ifneq ($(STATIC), 1)
install: all install: all
@install -d $(DESTDIR)$(plugindir) @install -d $(DESTDIR)$(plugindir)
@for plugin in $(PLUGINS); do \ @for plugin in $(PLUGINS); do \
@@ -35,6 +41,12 @@ uninstall:
rm $(DESTDIR)$(plugindir)/$$plugin 2>/dev/null; \ rm $(DESTDIR)$(plugindir)/$$plugin 2>/dev/null; \
done done
-@rmdir $(DESTDIR)$(plugindir) 2>/dev/null -@rmdir $(DESTDIR)$(plugindir) 2>/dev/null
else
install:
@true
uninstall:
@true
endif
ifneq ($(MAKECMDGOALS),distclean) ifneq ($(MAKECMDGOALS),distclean)
-include $(DEPS) -include $(DEPS)
+1
View File
@@ -39,6 +39,7 @@ static void restore(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_BASEFS_UP] = { .hook[HOOK_BASEFS_UP] = {
.cb = restore .cb = restore
}, },
+3 -5
View File
@@ -24,15 +24,12 @@
#include <string.h> #include <string.h>
#include <utmp.h> #include <utmp.h>
#include "../config.h"
#include "../finit.h" #include "../finit.h"
#include "../helpers.h" #include "../helpers.h"
#include "../plugin.h" #include "../plugin.h"
#include "libite/lite.h" #include "libite/lite.h"
#ifdef ENABLE_STATIC
#error This plugin uses getuser(), which relies on dynamically linked GLIBC. Cannot be built statically!
#endif
/* /*
* Setup standard FHS 2.3 structure in /var, and * Setup standard FHS 2.3 structure in /var, and
* write runlevel to UTMP, needed by, e.g., printerdrake. * write runlevel to UTMP, needed by, e.g., printerdrake.
@@ -49,6 +46,7 @@ static void setup(void *UNUSED(arg))
makedir("/var/lib", 0755); makedir("/var/lib", 0755);
makedir("/var/lib/misc", 0755); makedir("/var/lib/misc", 0755);
makedir("/var/lib/alarm", 0755); makedir("/var/lib/alarm", 0755);
makedir("/var/lib/urandom",0755);
makedir("/var/lock", 0755); makedir("/var/lock", 0755);
makedir("/var/log", 0755); makedir("/var/log", 0755);
makedir("/var/mail", 0755); makedir("/var/mail", 0755);
@@ -89,7 +87,7 @@ static void setup(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = "bootmisc", .name = __FILE__,
.hook[HOOK_BASEFS_UP] = { .hook[HOOK_BASEFS_UP] = {
.cb = setup .cb = setup
}, },
+1
View File
@@ -42,6 +42,7 @@ static void setup(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_NETWORK_UP] = { .hook[HOOK_NETWORK_UP] = {
.cb = setup .cb = setup
}, },
+1
View File
@@ -41,6 +41,7 @@ static void restore(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_BASEFS_UP] = { .hook[HOOK_BASEFS_UP] = {
.cb = restore .cb = restore
}, },
+1
View File
@@ -42,6 +42,7 @@
static void parse(void *arg, int fd, int events); static void parse(void *arg, int fd, int events);
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.io = { .io = {
.cb = parse, .cb = parse,
.flags = PLUGIN_IO_READ, .flags = PLUGIN_IO_READ,
+1
View File
@@ -180,6 +180,7 @@ static void nl_callback(void *UNUSED(arg), int sd, int UNUSED(events))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.io = { .io = {
.cb = nl_callback, .cb = nl_callback,
.flags = PLUGIN_IO_READ, .flags = PLUGIN_IO_READ,
+1
View File
@@ -66,6 +66,7 @@ static void setup(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_BASEFS_UP] = { .hook[HOOK_BASEFS_UP] = {
.cb = setup .cb = setup
}, },
+1 -1
View File
@@ -62,7 +62,7 @@ static int rfc868(int type)
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = "time", .name = "time", /* Must match the inetd /etc/services entry */
.inetd = { .inetd = {
.cmd = rfc868 .cmd = rfc868
} }
+9 -2
View File
@@ -37,6 +37,7 @@
static void watcher(void *arg, int fd, int events); static void watcher(void *arg, int fd, int events);
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.io = { .io = {
.cb = watcher, .cb = watcher,
.flags = PLUGIN_IO_READ, .flags = PLUGIN_IO_READ,
@@ -45,7 +46,10 @@ static plugin_t plugin = {
static void setup(void) static void setup(void)
{ {
plugin.io.fd = inotify_init1(IN_NONBLOCK); if (plugin.io.fd)
close(plugin.io.fd);
plugin.io.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0) if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0)
_e("Failed starting TTY watcher: %s", strerror(errno)); _e("Failed starting TTY watcher: %s", strerror(errno));
} }
@@ -59,9 +63,12 @@ static void watcher(void *UNUSED(arg), int fd, int UNUSED(events))
while ((len = read(fd, buf, sizeof(buf)))) { while ((len = read(fd, buf, sizeof(buf)))) {
if (-1 == len) { if (-1 == len) {
if (errno == EINVAL)
setup();
if (errno == EINTR) if (errno == EINTR)
continue; continue;
break;
break; /* Likely EAGAIN */
} }
snprintf(name, sizeof(name), "/dev/%s", notified->name); snprintf(name, sizeof(name), "/dev/%s", notified->name);
+42 -8
View File
@@ -22,29 +22,63 @@
*/ */
#include <unistd.h> #include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> /* gettimeofday() */
#include <sys/types.h>
#include "../config.h"
#include "../finit.h" #include "../finit.h"
#include "libite/lite.h"
#include "../helpers.h" #include "../helpers.h"
#include "../plugin.h" #include "../plugin.h"
#include "libite/lite.h"
static void setup(void *UNUSED(arg)) static void setup(void *UNUSED(arg))
{ {
#ifdef RANDOMSEED #ifdef RANDOMSEED
copyfile(RANDOMSEED, "/dev/urandom", 0, 0); if (!fexist(RANDOMSEED)) {
unlink(RANDOMSEED); int ret = 1;
FILE *fp;
print_desc("Bootstrapping random seed", NULL);
umask(077);
fp = fopen(RANDOMSEED, "w");
if (fp) {
int iter = 128;
struct timeval tv;
gettimeofday(&tv, NULL);
srandom(tv.tv_sec % 3600);
while (iter--) {
uint32_t i, prng = random();
for (i = 0; i < sizeof(prng); i++)
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
}
ret = fclose(fp);
}
print_result(ret);
umask(0);
}
print_desc("Initializing random number generator", NULL);
print_result(512 != copyfile(RANDOMSEED, "/dev/urandom", 0, 0));
#endif
}
static void save(void *UNUSED(arg))
{
#ifdef RANDOMSEED
umask(077); umask(077);
copyfile("/dev/urandom", RANDOMSEED, 4096, 0); print_desc("Saving random seed", NULL);
print_result(512 != copyfile("/dev/urandom", RANDOMSEED, 512, 0));
umask(0); umask(0);
#endif #endif
} }
static plugin_t plugin = { static plugin_t plugin = {
.hook[HOOK_BASEFS_UP] = { .name = __FILE__,
.cb = setup .hook[HOOK_BASEFS_UP] = { .cb = setup },
}, .hook[HOOK_SHUTDOWN] = { .cb = save },
.depends = { "bootmisc", } .depends = { "bootmisc", }
}; };
+1
View File
@@ -54,6 +54,7 @@ static void setup(void *UNUSED(arg))
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = __FILE__,
.hook[HOOK_NETWORK_UP] = { .hook[HOOK_NETWORK_UP] = {
.cb = setup .cb = setup
}, },
+113 -31
View File
@@ -41,11 +41,14 @@
#define RESPAWN_MAX 10 /* Prevent endless respawn of faulty services. */ #define RESPAWN_MAX 10 /* Prevent endless respawn of faulty services. */
static int dyn_stop_cnt = 0;
static int is_norespawn (void); static int is_norespawn (void);
static void restart_lost_procs (void); static void restart_lost_procs (void);
static void svc_dance (svc_t *svc); static void svc_dance (svc_t *svc);
#ifndef INETD_DISABLED
static svc_t *find_inetd_svc (char *path, char *service, char *proto); static svc_t *find_inetd_svc (char *path, char *service, char *proto);
#endif
/** /**
* service_bootstrap - Start bootstrap services and tasks * service_bootstrap - Start bootstrap services and tasks
@@ -87,6 +90,8 @@ void service_bootstrap(void)
*/ */
svc_cmd_t service_enabled(svc_t *svc, int event, void *arg) svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
{ {
svc_cmd_t cmd = SVC_START; /* Default to start, since listed in finit.conf */
if (!svc) { if (!svc) {
errno = EINVAL; errno = EINVAL;
return SVC_STOP; return SVC_STOP;
@@ -98,9 +103,15 @@ svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
/* /*
* Event conditions for services are ignored during bootstrap. * Event conditions for services are ignored during bootstrap.
*/ */
_d("Checking %s runlevel %d and events %s", svc->cmd, runlevel, svc->events);
if (runlevel && !event_service_cond(svc->events)) if (runlevel && !event_service_cond(svc->events))
return SVC_STOP; return SVC_STOP;
if (svc->state == SVC_RELOAD_STATE)
cmd = SVC_RELOAD;
if (svc->state == SVC_PAUSED_STATE)
cmd = SVC_STOP;
/* Is there a service plugin registered? */ /* Is there a service plugin registered? */
if (svc->cb) { if (svc->cb) {
int status; int status;
@@ -122,8 +133,10 @@ svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
} }
/* Callback normally exits here. */ /* Callback normally exits here. */
if (WIFEXITED(status)) if (WIFEXITED(status)) {
return WEXITSTATUS(status); svc_cmd_t tmp = WEXITSTATUS(status);
return tmp == SVC_START ? cmd : tmp;
}
/* Check for SEGFAULT or other error ... */ /* Check for SEGFAULT or other error ... */
if (WIFSIGNALED(status) && WCOREDUMP(status)) if (WIFSIGNALED(status) && WCOREDUMP(status))
@@ -134,8 +147,13 @@ svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
return SVC_STOP; return SVC_STOP;
} }
/* No service plugin, default to start, since listed in finit.conf */ _d("%s => %s", svc->cmd, (cmd == SVC_START
return SVC_START; ? "SVC_START"
: (cmd == SVC_RELOAD
? "SVC_RELOAD"
: "SVC_STOP")));
return cmd;
} }
/* Remember: service_enabled() must be called before calling service_start() */ /* Remember: service_enabled() must be called before calling service_start() */
@@ -294,6 +312,7 @@ int service_start(svc_t *svc)
exit(status); exit(status);
} }
svc->pid = pid; svc->pid = pid;
svc->state = SVC_RUNNING_STATE;
if (svc_is_inetd(svc)) { if (svc_is_inetd(svc)) {
if (svc->inetd.type == SOCK_STREAM) if (svc->inetd.type == SOCK_STREAM)
@@ -315,9 +334,9 @@ int service_start(svc_t *svc)
return 0; return 0;
} }
int service_stop(svc_t *svc) int service_stop(svc_t *svc, int state)
{ {
int res = 1; int res = 0;
if (!svc) if (!svc)
return 1; return 1;
@@ -331,6 +350,10 @@ int service_stop(svc_t *svc)
if (SVC_TYPE_SERVICE != svc->type) if (SVC_TYPE_SERVICE != svc->type)
return 0; return 0;
_d("Service %s state %d, new state %d, sighup %d", svc->cmd, svc->state, state, svc->sighup);
if (state == SVC_RELOAD_STATE && svc->sighup)
goto exit;
if (runlevel != 1 && verbose) if (runlevel != 1 && verbose)
print_desc("Stopping ", svc->desc); print_desc("Stopping ", svc->desc);
@@ -340,7 +363,8 @@ int service_stop(svc_t *svc)
if (runlevel != 1 && verbose) if (runlevel != 1 && verbose)
print_result(res); print_result(res);
exit: exit:
svc->pid = 0; if (!res)
svc->state = state;
svc->restart_counter = 0; svc->restart_counter = 0;
return res; return res;
@@ -363,8 +387,36 @@ void service_start_dynamic(void)
svc_clean_dynamic(service_unregister); svc_clean_dynamic(service_unregister);
} }
/*
* Unless there are services we must collect first (wait for
* them to stop), we can call HOOK_SVC_RECONF here.
*/
static int service_stop_done(svc_t *svc)
{
if (svc && !svc_is_changed(svc))
return 0;
if (svc && dyn_stop_cnt)
dyn_stop_cnt--;
_d("dyn_stop_cnt %d", dyn_stop_cnt);
if (!dyn_stop_cnt) {
_d("All disabled/removed services have been stoppped, calling reconf hooks ...");
plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */
/* Finish off by starting/reload modified/new services */
service_start_dynamic();
}
return 1;
}
/** /**
* service_stop_dynamic - Stop disabled/removed dynamic services * service_stop_dynamic - Stop disabled/removed dynamic services
*
* We call it "stop", but in reality it could be "skip" as well, if the
* service supports SIGHUP. This function is just one step on the road
* to reload all modified services.
*/ */
void service_stop_dynamic(void) void service_stop_dynamic(void)
{ {
@@ -372,31 +424,48 @@ void service_stop_dynamic(void)
_d("Stopping disabled/removed services ..."); _d("Stopping disabled/removed services ...");
for (svc = svc_dynamic_iterator(1); svc; svc = svc_dynamic_iterator(0)) { for (svc = svc_dynamic_iterator(1); svc; svc = svc_dynamic_iterator(0)) {
if (svc_is_changed(svc)) if (svc_is_changed(svc) && svc->pid) {
service_stop(svc); svc_state_t new_state = SVC_RELOAD_STATE;
if (svc_is_removed(svc))
new_state = SVC_HALTED_STATE;
if (!svc_has_sighup(svc))
dyn_stop_cnt++;
_d("Marking service %s as state %d", svc->cmd, new_state);
service_stop(svc, new_state);
}
} }
_d("All disabled/removed services have been stoppped, calling reconf hooks ..."); /* Check if we need to collect any services before calling user HOOK */
plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */ service_stop_done(NULL);
} }
/* stop + start /**
* service_restart - Restart or SIGHUP a process
* *
* XXX: This should be refactored into a background job AND marked such * Unfortunately we cannot call service_start() here because we must
* so that the service monitor doesn't attempt to restart it! * wait for the svc to actually be collected by the service_monitor()
* first. Currently this means that an initctl user will not get
* correct feedback when restarting a service. (Prompt may return
* before we've actually started upp the service again.)
*
* XXX: This should be refactored to let initctl check the sighup
* flag and then to stop+start or reload.
*/ */
int service_restart(svc_t *svc) int service_restart(svc_t *svc)
{ {
int result = 0;
if (!svc) if (!svc)
return 1; return 1;
result += service_stop(svc); /* Ignore if finit is SIGSTOP'ed */
sleep(1); if (is_norespawn())
result += service_start(svc); return 0;
return result; svc->restart_counter = 0;
return service_stop(svc, SVC_RESTART_STATE);
} }
/** /**
@@ -415,16 +484,15 @@ int service_reload(svc_t *svc)
if (is_norespawn()) if (is_norespawn())
return 0; return 0;
if (!svc) { if (!svc)
_e("Failed, no svc pointer.");
return 1; return 1;
}
if (svc->pid <= 1) { if (svc->pid <= 1) {
_d("Bad PID %d for %s, SIGHUP", svc->pid, svc->cmd); _d("Bad PID %d for %s, SIGHUP", svc->pid, svc->cmd);
svc->pid = 0; svc->pid = 0;
return 1; return 1;
} }
svc->state = SVC_RUNNING_STATE;
_d("Sending SIGHUP to PID %d", svc->pid); _d("Sending SIGHUP to PID %d", svc->pid);
return kill(svc->pid, SIGHUP); return kill(svc->pid, SIGHUP);
@@ -445,8 +513,12 @@ void service_reload_dynamic(void)
/* Then stop any disabled/removed services and non-reloadable */ /* Then stop any disabled/removed services and non-reloadable */
service_stop_dynamic(); service_stop_dynamic();
/* Finish off by starting/reload modified/new services */ /*
service_start_dynamic(); * Finish off by starting/reloading modified/new services.
* Postponed to service_stop_done() to make sure all services
* are guaranteed to have been stopped before being started
* again.
*/
} }
/** /**
@@ -483,12 +555,12 @@ void service_runlevel(int newlevel)
inetd_stop(&svc->inetd); inetd_stop(&svc->inetd);
else else
#endif #endif
service_stop(svc); service_stop(svc, SVC_HALTED_STATE);
} }
/* ... or disabled/removed services from /etc/finit.d/ */ /* ... or disabled/removed services from /etc/finit.d/ */
if (svc_is_dynamic(svc) && svc_is_changed(svc)) if (svc_is_dynamic(svc) && svc_is_changed(svc))
service_stop(svc); service_stop(svc, SVC_HALTED_STATE);
} }
/* Prev runlevel services stopped, call hooks before starting new runlevel ... */ /* Prev runlevel services stopped, call hooks before starting new runlevel ... */
@@ -528,7 +600,8 @@ void service_runlevel(int newlevel)
else else
erase("/etc/nologin"); erase("/etc/nologin");
if (0 != prevlevel) /* No TTYs run at bootstrap, they have a delayed start. */
if (prevlevel > 0)
tty_runlevel(runlevel); tty_runlevel(runlevel);
} }
@@ -733,6 +806,7 @@ int service_register(int type, char *line, time_t mtime, char *username)
if (svc_is_inetd(svc)) { if (svc_is_inetd(svc)) {
char *iface, *name = service; char *iface, *name = service;
svc->state = SVC_WAITING_STATE;
if (svc->inetd.cmd && plugin) if (svc->inetd.cmd && plugin)
name = plugin->name; name = plugin->name;
@@ -762,7 +836,8 @@ int service_register(int type, char *line, time_t mtime, char *username)
void service_unregister(svc_t *svc) void service_unregister(svc_t *svc)
{ {
service_stop(svc); if (svc->state != SVC_HALTED_STATE)
_e("Failed stopping %s, removing anyway from list of monitored services.", svc->cmd);
svc_del(svc); svc_del(svc);
} }
@@ -798,6 +873,9 @@ void service_monitor(pid_t lost)
if (lost != svc->pid) if (lost != svc->pid)
continue; continue;
if (!prevlevel && svc_clean_bootstrap(svc))
continue;
if (SVC_TYPE_SERVICE != svc->type) { if (SVC_TYPE_SERVICE != svc->type) {
svc->pid = 0; svc->pid = 0;
continue; continue;
@@ -808,6 +886,10 @@ void service_monitor(pid_t lost)
/* No longer running, update books. */ /* No longer running, update books. */
svc->pid = 0; svc->pid = 0;
/* Check if we're still collecting stopped dynamic services */
if (service_stop_done(svc))
break;
if (sig_stopped()) { if (sig_stopped()) {
_e("Stopped, not respawning killed processes."); _e("Stopped, not respawning killed processes.");
break; break;
@@ -861,7 +943,7 @@ static void svc_dance(svc_t *svc)
if (svc->pid) { if (svc->pid) {
if (SVC_STOP == cmd) if (SVC_STOP == cmd)
service_stop(svc); service_stop(svc, SVC_HALTED_STATE);
else if (SVC_RELOAD == cmd) else if (SVC_RELOAD == cmd)
service_reload(svc); service_reload(svc);
} else { } else {
+1 -1
View File
@@ -33,7 +33,7 @@ void service_unregister (svc_t *svc);
svc_cmd_t service_enabled (svc_t *svc, int event, void *arg); svc_cmd_t service_enabled (svc_t *svc, int event, void *arg);
int service_start (svc_t *svc); int service_start (svc_t *svc);
int service_stop (svc_t *svc); int service_stop (svc_t *svc, int state);
void service_start_dynamic (void); void service_start_dynamic (void);
void service_stop_dynamic (void); void service_stop_dynamic (void);
int service_restart (svc_t *svc); int service_restart (svc_t *svc);
+12
View File
@@ -38,12 +38,14 @@
* It activates the kbrequest action. * It activates the kbrequest action.
*/ */
#include <sched.h>
#include <string.h> /* strerror() */ #include <string.h> /* strerror() */
#include <sys/reboot.h> #include <sys/reboot.h>
#include <sys/wait.h> #include <sys/wait.h>
#include "finit.h" #include "finit.h"
#include "conf.h" #include "conf.h"
#include "config.h"
#include "helpers.h" #include "helpers.h"
#include "plugin.h" #include "plugin.h"
#include "private.h" #include "private.h"
@@ -64,6 +66,15 @@ void do_shutdown(int sig)
if (sdown) if (sdown)
run_interactive(sdown, "Calling shutdown hook: %s", sdown); run_interactive(sdown, "Calling shutdown hook: %s", sdown);
/* If we enabled terse mode at boot, restore to previous setting at shutdown */
if (quiet) {
verbose = VERBOSE_MODE;
if (verbose) {
sched_yield();
fputs("\n", stderr);
}
}
/* Call all shutdown hooks before rebooting... */ /* Call all shutdown hooks before rebooting... */
plugin_run_hooks(HOOK_SHUTDOWN); plugin_run_hooks(HOOK_SHUTDOWN);
@@ -96,6 +107,7 @@ void do_shutdown(int sig)
*/ */
static void sighup_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) static void sighup_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
/* INIT_CMD_RELOAD: 'init q', 'initctl reload', and SIGHUP */
service_reload_dynamic(); service_reload_dynamic();
} }
+70 -5
View File
@@ -310,6 +310,33 @@ svc_t *svc_find_by_jobid(int job, int id)
return NULL; return NULL;
} }
/**
* svc_find_by_nameid - Find an service object by its basename:ID
* @name: Process name to match
* @id: Instance id
*
* Returns:
* A pointer to an &svc_t object, or %NULL if not found.
*/
svc_t *svc_find_by_nameid(char *name, int id)
{
char *ptr;
svc_t *svc;
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
ptr = strrchr(svc->cmd, '/');
if (ptr)
ptr++;
else
ptr = svc->cmd;
if (svc->id == id && !strcmp(name, ptr))
return svc;
}
return NULL;
}
/** /**
* svc_mark_dynamic - Mark dynamically loaded services for deletion. * svc_mark_dynamic - Mark dynamically loaded services for deletion.
* *
@@ -359,18 +386,56 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
} }
} }
/**
* svc_clean_bootstrap - Remove bootstrap-only services after boot
* @svc: Pointer to &svc_t object
*
* Returns:
* %TRUE(1) if object was bootstrap-only, otherwise %FALSE(0)
*/
int svc_clean_bootstrap(svc_t *svc)
{
if (!ISOTHER(svc->runlevels, 0)) {
svc->pid = 0;
svc_del(svc);
return 1;
}
return 0;
}
char *svc_status(svc_t *svc) char *svc_status(svc_t *svc)
{ {
if (svc->pid)
return "running";
if (!svc_in_runlevel(svc, runlevel)) if (!svc_in_runlevel(svc, runlevel))
return "halted"; return "halted";
if (svc_is_inetd(svc)) switch (svc->state) {
case SVC_WAITING_STATE:
return "waiting"; return "waiting";
return "stopped"; case SVC_PAUSED_STATE:
return "stopped";
case SVC_CONDHALT_STATE:
return "nocond";
case SVC_RESTART_STATE:
return "restart";
case SVC_RELOAD_STATE:
return "reload";
case SVC_RUNNING_STATE:
if (svc->pid)
return "running";
/* Fall through */
case SVC_HALTED_STATE:
default:
break;
}
return "halted";
} }
/* Same base service, return unique ID */ /* Same base service, return unique ID */
+15 -1
View File
@@ -40,12 +40,22 @@ typedef enum {
typedef enum { typedef enum {
SVC_TYPE_FREE = 0, /* Free to allocate */ SVC_TYPE_FREE = 0, /* Free to allocate */
SVC_TYPE_SERVICE , /* Monitored, will be respawned */ SVC_TYPE_SERVICE, /* Monitored, will be respawned */
SVC_TYPE_TASK, /* One-shot, runs in parallell */ SVC_TYPE_TASK, /* One-shot, runs in parallell */
SVC_TYPE_RUN, /* Like task, but wait for completion */ SVC_TYPE_RUN, /* Like task, but wait for completion */
SVC_TYPE_INETD /* Classic inetd service */ SVC_TYPE_INETD /* Classic inetd service */
} svc_type_t; } svc_type_t;
typedef enum {
SVC_HALTED_STATE = 0, /* Not allowed in runlevel, or not enabled. */
SVC_WAITING_STATE, /* Waiting for connection (inetd service) */
SVC_PAUSED_STATE, /* Stopped/Paused by user started on reload */
SVC_CONDHALT_STATE, /* Not allowed to run atm. event/state lost */
SVC_RESTART_STATE, /* Restarting service waiting to be stopped */
SVC_RELOAD_STATE, /* Reloading services, after .conf changed */
SVC_RUNNING_STATE, /* Currently running service, see svc->pid */
} svc_state_t;
#define FINIT_SHM_ID 0x494E4954 /* "INIT", see ascii(7) */ #define FINIT_SHM_ID 0x494E4954 /* "INIT", see ascii(7) */
#define MAX_ARG_LEN 64 #define MAX_ARG_LEN 64
#define MAX_STR_LEN 64 #define MAX_STR_LEN 64
@@ -63,6 +73,7 @@ typedef struct svc {
/* Service details */ /* Service details */
pid_t pid; pid_t pid;
svc_state_t state; /* Paused, Reloading, Restart, Running, ... */
svc_type_t type; svc_type_t type;
time_t mtime; /* Modification time for .conf from /etc/finit.d/ */ time_t mtime; /* Modification time for .conf from /etc/finit.d/ */
int dirty; /* Set if old mtime != new mtime => reloaded, int dirty; /* Set if old mtime != new mtime => reloaded,
@@ -120,6 +131,7 @@ int svc_del (svc_t *svc);
svc_t *svc_find (char *cmd, int id); svc_t *svc_find (char *cmd, int id);
svc_t *svc_find_by_pid (pid_t pid); svc_t *svc_find_by_pid (pid_t pid);
svc_t *svc_find_by_jobid (int job, int id); svc_t *svc_find_by_jobid (int job, int id);
svc_t *svc_find_by_nameid (char *name, int id);
svc_t *svc_iterator (int first); svc_t *svc_iterator (int first);
svc_t *svc_inetd_iterator (int first); svc_t *svc_inetd_iterator (int first);
@@ -133,12 +145,14 @@ void svc_foreach_dynamic (void (*cb)(svc_t *));
void svc_mark_dynamic (void); void svc_mark_dynamic (void);
void svc_check_dirty (svc_t *svc, time_t mtime); void svc_check_dirty (svc_t *svc, time_t mtime);
void svc_clean_dynamic (void (*cb)(svc_t *)); void svc_clean_dynamic (void (*cb)(svc_t *));
int svc_clean_bootstrap (svc_t *svc);
char *svc_status (svc_t *svc); char *svc_status (svc_t *svc);
int svc_next_id (char *cmd); int svc_next_id (char *cmd);
int svc_is_unique (svc_t *svc); int svc_is_unique (svc_t *svc);
static inline int svc_in_runlevel(svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); } static inline int svc_in_runlevel(svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
static inline int svc_has_sighup(svc_t *svc) { return svc && 0 != svc->sighup; }
static inline int svc_is_dynamic(svc_t *svc) { return svc && 0 != svc->mtime; } static inline int svc_is_dynamic(svc_t *svc) { return svc && 0 != svc->mtime; }
static inline int svc_is_removed(svc_t *svc) { return svc && -1 == svc->dirty; } static inline int svc_is_removed(svc_t *svc) { return svc && -1 == svc->dirty; }
+2 -1
View File
@@ -25,9 +25,10 @@
#ifndef FINIT_TTY_H_ #ifndef FINIT_TTY_H_
#define FINIT_TTY_H_ #define FINIT_TTY_H_
#include <limits.h>
#include "queue.h" /* BSD sys/queue.h API */ #include "queue.h" /* BSD sys/queue.h API */
#define EVENT_SIZE ((sizeof(struct inotify_event) + 20)) #define EVENT_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1))
typedef struct { typedef struct {
char *name; char *name;