mirror of
https://github.com/troglobit/finit.git
synced 2026-10-14 10:19:36 +00:00
dbus: mirror legacy runlevel edge cases in Manager1.SetRunlevel
The bus method called sm_runlevel() unconditionally. In runlevel 0 and 6 that aborts an in-flight shutdown, which INIT_CMD_RUNLVL refuses with a warning, and during bootstrap it switches immediately where the legacy path defers via cfglevel to the end of runlevel S. Port both. A bad runlevel argument still returns InvalidArgs, where the legacy protocol acks silently: a typed interface rejects garbage. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
4 files changed
+29
-23
No files matched your search
@@ -233,6 +233,7 @@ static void bypass_shutdown(void *unused)
|
||||
do_shutdown(halt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle switch_root API command.
|
||||
* Parses data: "newroot\0newinit\0"
|
||||
@@ -370,8 +371,8 @@ static void api_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
static svc_t *iter = NULL;
|
||||
struct init_request rq;
|
||||
int sd, lvl;
|
||||
svc_t *svc;
|
||||
int sd;
|
||||
|
||||
(void)arg;
|
||||
|
||||
@@ -446,14 +447,6 @@ static void api_cb(uev_t *w, void *arg, int events)
|
||||
|
||||
switch (rq.cmd) {
|
||||
case INIT_CMD_RUNLVL:
|
||||
/* Allow changing cfglevel in runlevel S */
|
||||
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||
if (runlevel != INIT_LEVEL) {
|
||||
warnx("Cannot abort runlevel 6/0.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rq.runlevel) {
|
||||
case 's':
|
||||
case 'S':
|
||||
@@ -462,17 +455,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
||||
|
||||
case '0'...'9':
|
||||
dbg("Setting new runlevel %c", rq.runlevel);
|
||||
lvl = rq.runlevel - '0';
|
||||
if (lvl == 0)
|
||||
halt = SHUT_OFF;
|
||||
if (lvl == 6)
|
||||
halt = SHUT_REBOOT;
|
||||
|
||||
/* User requested change in next runlevel */
|
||||
if (runlevel == INIT_LEVEL)
|
||||
cfglevel = lvl;
|
||||
else
|
||||
sm_runlevel(lvl);
|
||||
sm_request_runlevel(rq.runlevel - '0');
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+1
-3
@@ -454,9 +454,7 @@ static int manager_set_runlevel(link_call_t *call, void *userdata)
|
||||
"org.freedesktop.DBus.Error.InvalidArgs",
|
||||
"runlevel must be 0-9 (excluding internal levels)");
|
||||
|
||||
if (lvl == 0) halt = SHUT_OFF;
|
||||
if (lvl == 6) halt = SHUT_REBOOT;
|
||||
sm_runlevel((int)lvl);
|
||||
sm_request_runlevel((int)lvl);
|
||||
|
||||
(void)link_call_reply(call);
|
||||
return 0;
|
||||
|
||||
@@ -94,6 +94,30 @@ static void shutdown_wdt_cb(uev_t *w, void *arg, int events)
|
||||
do_shutdown(halt);
|
||||
}
|
||||
|
||||
/*
|
||||
* User-requested runlevel change, shared by the legacy API and the
|
||||
* D-Bus SetRunlevel method. Refused in runlevel 0/6, deferred via
|
||||
* cfglevel during bootstrap.
|
||||
*/
|
||||
void sm_request_runlevel(int lvl)
|
||||
{
|
||||
if (IS_RESERVED_RUNLEVEL(runlevel) && runlevel != INIT_LEVEL) {
|
||||
warnx("Cannot abort runlevel 6/0.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lvl == 0)
|
||||
halt = SHUT_OFF;
|
||||
if (lvl == 6)
|
||||
halt = SHUT_REBOOT;
|
||||
|
||||
/* Runlevel S: user requested change in next runlevel */
|
||||
if (runlevel == INIT_LEVEL)
|
||||
cfglevel = lvl;
|
||||
else
|
||||
sm_runlevel(lvl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Console input callback - handles Ctrl-C during bootstrap wait
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user