Compare commits

..
18 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
12 changed files with 260 additions and 63 deletions
+55 -1
View File
@@ -4,6 +4,57 @@ Change Log
All relevant changes 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 [2.2][] - 2015-11-23
-------------------- --------------------
@@ -431,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.2 VERSION = 2.4
NAME = finit NAME = finit
PKG = $(NAME)-$(VERSION) PKG = $(NAME)-$(VERSION)
DEV = $(NAME)-dev DEV = $(NAME)-dev
+25 -19
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,24 +591,25 @@ not return until the given command has fully completed.
Usage: initctl [OPTIONS] <COMMAND> Usage: initctl [OPTIONS] <COMMAND>
Options: Options:
-d, --debug Debug initctl (client) -d, --debug Debug initctl (client)
-v, --verbose Verbose output -v, --verbose Verbose output
-h, --help This help text -h, --help This help text
Commands: Commands:
debug Toggle Finit (daemon) debug debug Toggle Finit (daemon) debug
emit <EV> Emit an event. Can be a predefined event: RELOAD, STOP, help This help text
START, or a custom string to match the event list in a emit <EV> Emit event; a predefined event: RELOAD, STOP, START
service stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME, or a custom string matching an event in a service
where IFNAME is the interface name, e.g. eth0 stanza, e.g: GW:UP, IFUP:IFNAME, IFDN:IFNAME. Where
reload Reload *.conf in /etc/finit.d/ and activate changes IFNAME is the interface name, e.g. eth0
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot reload Reload *.conf in /etc/finit.d/ and activate changes
status | show Show status of services runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
start <JOB|NAME> Start stopped job or service status | show Show status of services
stop <JOB|NAME> Stop/Pause running job or service start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
restart <JOB|NAME> Restart (stop/start) job or service stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
reload <JOB|NAME> Reload (SIGHUP) job or service restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
version Show Finit version 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
@@ -822,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
+14 -5
View File
@@ -77,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);
@@ -95,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)));
} }
} }
@@ -261,6 +266,10 @@ 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: /* 'init q' and 'initctl reload' */ case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
+1
View File
@@ -145,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));
} }
+3 -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;
@@ -218,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 */
+3
View File
@@ -142,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);
+53 -19
View File
@@ -136,27 +136,58 @@ 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)) {
char jobid[10], args[512] = ""; char jobid[10], args[512] = "", *lvls;
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 %-18.18s ", 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;
@@ -206,23 +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"
" -d, --debug Debug initctl (client)\n" " -d, --debug Debug initctl (client)\n"
" -v, --verbose Verbose output\n" " -v, --verbose Verbose output\n"
" -h, --help This help text\n\n" " -h, --help This help text\n\n"
"Commands:\n" "Commands:\n"
" debug Toggle Finit (daemon) 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:UP, IFUP:IFNAME, IFDN:IFNAME,\n" " or a custom string matching an event in a service\n"
" where 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/Pause 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;
} }
+21 -10
View File
@@ -353,8 +353,6 @@ int service_stop(svc_t *svc, int state)
_d("Service %s state %d, new state %d, sighup %d", svc->cmd, svc->state, state, svc->sighup); _d("Service %s state %d, new state %d, sighup %d", svc->cmd, svc->state, state, svc->sighup);
if (state == SVC_RELOAD_STATE && svc->sighup) if (state == SVC_RELOAD_STATE && svc->sighup)
goto exit; goto exit;
if (state == SVC_RESTART_STATE && svc->sighup)
return service_reload(svc);
if (runlevel != 1 && verbose) if (runlevel != 1 && verbose)
print_desc("Stopping ", svc->desc); print_desc("Stopping ", svc->desc);
@@ -401,13 +399,13 @@ static int service_stop_done(svc_t *svc)
if (svc && dyn_stop_cnt) if (svc && dyn_stop_cnt)
dyn_stop_cnt--; dyn_stop_cnt--;
_d("dyn_stop_cnt %d", dyn_stop_cnt);
if (!dyn_stop_cnt) { if (!dyn_stop_cnt) {
_d("All disabled/removed services have been stoppped, calling reconf hooks ..."); _d("All disabled/removed services have been stoppped, calling reconf hooks ...");
plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */ plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */
/* Finish off by starting/reload modified/new services */ /* Finish off by starting/reload modified/new services */
if (svc->state == SVC_RELOAD_STATE) service_start_dynamic();
service_start_dynamic();
} }
return 1; return 1;
@@ -426,10 +424,17 @@ 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) {
dyn_stop_cnt++; svc_state_t new_state = SVC_RELOAD_STATE;
_d("Marking service %s as state %d", svc->cmd, SVC_RELOAD_STATE);
service_stop(svc, 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);
} }
} }
@@ -595,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);
} }
@@ -800,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;
@@ -829,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, SVC_HALTED_STATE); 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);
} }
@@ -865,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;
+11
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);
+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 */
+3
View File
@@ -131,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);
@@ -144,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; }