mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 05:22:48 +07:00
Fix #352: separate runlevel S from runlevel 0
Due to an old design decision runlevel S was encoded internally as '0', meaning it was the same as halt/poweroff. If you want to run scripts at system shutdown this was less then ideal since it meant your scripts also ran at bootstrap. This change is quite invasive. It introduces INIT_LEVEL (10) as the value for runlevel S, meaning all code that parses and/or evaluates anything for runlevel 0/S was affected and had to be reworked. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -244,7 +244,7 @@ networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
|||||||
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
||||||
given on the kernel cmdline, in which case runlevel 1 is started.
|
given on the kernel cmdline, in which case runlevel 1 is started.
|
||||||
|
|
||||||
All services in runlevel S(0) are started first, followed by the desired
|
All services in runlevel S) are started first, followed by the desired
|
||||||
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
||||||
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
||||||
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
||||||
@@ -585,24 +585,24 @@ scripting and documentation:
|
|||||||
|
|
||||||
```
|
```
|
||||||
alpine:~# initctl -p
|
alpine:~# initctl -p
|
||||||
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
||||||
======================================================================
|
======================================================================
|
||||||
1506 acpid running [--2345----] ACPI daemon
|
1506 acpid running [---2345----] ACPI daemon
|
||||||
1509 crond running [--2345----] Cron daemon
|
1509 crond running [---2345----] Cron daemon
|
||||||
1489 dropbear running [--2345----] Dropbear SSH daemon
|
1489 dropbear running [---2345----] Dropbear SSH daemon
|
||||||
1511 klogd running [S12345----] Kernel log daemon
|
1511 klogd running [S-12345----] Kernel log daemon
|
||||||
1512 ntpd running [--2345----] NTP daemon
|
1512 ntpd running [---2345----] NTP daemon
|
||||||
1473 syslogd running [S12345----] Syslog daemon
|
1473 syslogd running [S-12345----] Syslog daemon
|
||||||
|
|
||||||
alpine:~# initctl -pv
|
alpine:~# initctl -pv
|
||||||
PID IDENT STATUS RUNLEVELS COMMAND
|
PID IDENT STATUS RUNLEVELS COMMAND
|
||||||
======================================================================
|
======================================================================
|
||||||
1506 acpid running [--2345----] acpid -f
|
1506 acpid running [---2345----] acpid -f
|
||||||
1509 crond running [--2345----] crond -f -S $CRON_OPTS
|
1509 crond running [---2345----] crond -f -S $CRON_OPTS
|
||||||
1489 dropbear running [--2345----] dropbear -R -F $DROPBEAR_OPTS
|
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
|
||||||
1511 klogd running [S12345----] klogd -n $KLOGD_OPTS
|
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
|
||||||
1512 ntpd running [--2345----] ntpd -n $NTPD_OPTS
|
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
|
||||||
1473 syslogd running [S12345----] syslogd -n
|
1473 syslogd running [S-12345----] syslogd -n
|
||||||
```
|
```
|
||||||
|
|
||||||
The environment variables to each of the services above are read from,
|
The environment variables to each of the services above are read from,
|
||||||
@@ -627,7 +627,7 @@ Condition(s):
|
|||||||
User : root
|
User : root
|
||||||
Group : root
|
Group : root
|
||||||
Uptime : 2 hour 46 min 56 sec
|
Uptime : 2 hour 46 min 56 sec
|
||||||
Runlevels : [--2345----]
|
Runlevels : [---2345----]
|
||||||
Memory : 1.2M
|
Memory : 1.2M
|
||||||
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
||||||
|- 1485 dropbear -R -F
|
|- 1485 dropbear -R -F
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
case INIT_CMD_SUSPEND:
|
case INIT_CMD_SUSPEND:
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
warnx("Unsupported command in runlevel S and 6.");
|
warnx("Unsupported command in runlevel S and 6.");
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -48,7 +48,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define BOOTSTRAP (runlevel == 0)
|
#define BOOTSTRAP (runlevel == INIT_LEVEL)
|
||||||
|
|
||||||
int logfile_size_max = 200000; /* 200 kB */
|
int logfile_size_max = 200000; /* 200 kB */
|
||||||
int logfile_count_max = 5;
|
int logfile_count_max = 5;
|
||||||
@@ -475,7 +475,7 @@ static void kmod_load(char *mod)
|
|||||||
char module[64] = { 0 };
|
char module[64] = { 0 };
|
||||||
char cmd[CMD_SIZE];
|
char cmd[CMD_SIZE];
|
||||||
|
|
||||||
if (runlevel != 0)
|
if (runlevel != INIT_LEVEL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Strip args for progress below and kmod_exists() */
|
/* Strip args for progress below and kmod_exists() */
|
||||||
@@ -508,15 +508,16 @@ int conf_parse_runlevels(char *runlevels)
|
|||||||
break;
|
break;
|
||||||
if ('!' == lvl) {
|
if ('!' == lvl) {
|
||||||
not = 1;
|
not = 1;
|
||||||
bitmask = 0x3FE;
|
bitmask = 0x7FE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('s' == lvl || 'S' == lvl)
|
if ('s' == lvl || 'S' == lvl)
|
||||||
lvl = '0';
|
level = INIT_LEVEL;
|
||||||
|
else
|
||||||
|
level = lvl - '0';
|
||||||
|
|
||||||
level = lvl - '0';
|
if (level > INIT_LEVEL || level < 0)
|
||||||
if (level > 9 || level < 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (not)
|
if (not)
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@
|
|||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
|
|
||||||
int runlevel = 0; /* Bootstrap 'S' */
|
int runlevel = INIT_LEVEL; /* Bootstrap 'S' */
|
||||||
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
|
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
|
||||||
int cmdlevel = 0; /* runlevel override from cmdline */
|
int cmdlevel = 0; /* runlevel override from cmdline */
|
||||||
int prevlevel = -1;
|
int prevlevel = -1;
|
||||||
|
|||||||
+2
-1
@@ -63,10 +63,11 @@
|
|||||||
#define LINE_SIZE 1024
|
#define LINE_SIZE 1024
|
||||||
#define BUF_SIZE 4096
|
#define BUF_SIZE 4096
|
||||||
|
|
||||||
/* We extend the INIT_CMD_ range for the new initctl tool. */
|
|
||||||
#define INIT_SOCKET _PATH_VARRUN "finit/socket"
|
#define INIT_SOCKET _PATH_VARRUN "finit/socket"
|
||||||
#define INIT_MAGIC 0x03091969
|
#define INIT_MAGIC 0x03091969
|
||||||
|
#define INIT_LEVEL 10
|
||||||
|
|
||||||
|
/* We extend the INIT_CMD_ range for the new initctl tool. */
|
||||||
#define INIT_CMD_START 0
|
#define INIT_CMD_START 0
|
||||||
#define INIT_CMD_RUNLVL 1
|
#define INIT_CMD_RUNLVL 1
|
||||||
#define INIT_CMD_POWERFAIL 2
|
#define INIT_CMD_POWERFAIL 2
|
||||||
|
|||||||
+24
-10
@@ -761,17 +761,18 @@ static int plugins_list(char *arg)
|
|||||||
char *runlevel_string(int currlevel, int levels)
|
char *runlevel_string(int currlevel, int levels)
|
||||||
{
|
{
|
||||||
static char lvl[21];
|
static char lvl[21];
|
||||||
int i, pos = 1;
|
int i = INIT_LEVEL;
|
||||||
|
int pos = 1;
|
||||||
|
|
||||||
memset(lvl, 0, sizeof(lvl));
|
memset(lvl, 0, sizeof(lvl));
|
||||||
lvl[0] = '[';
|
lvl[0] = '[';
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
do {
|
||||||
if (ISSET(levels, i)) {
|
if (ISSET(levels, i)) {
|
||||||
if (!plain && currlevel == i)
|
if (!plain && currlevel == i)
|
||||||
pos = strlcat(lvl, "\e[1m", sizeof(lvl));
|
pos = strlcat(lvl, "\e[1m", sizeof(lvl));
|
||||||
|
|
||||||
if (i == 0)
|
if (i == INIT_LEVEL)
|
||||||
lvl[pos++] = 'S';
|
lvl[pos++] = 'S';
|
||||||
else
|
else
|
||||||
lvl[pos++] = '0' + i;
|
lvl[pos++] = '0' + i;
|
||||||
@@ -781,7 +782,14 @@ char *runlevel_string(int currlevel, int levels)
|
|||||||
} else {
|
} else {
|
||||||
lvl[pos++] = '-';
|
lvl[pos++] = '-';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* XXX: ugly hack to get order right: S0123456789 */
|
||||||
|
if (i == INIT_LEVEL)
|
||||||
|
i = 0;
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
} while (i < INIT_LEVEL);
|
||||||
|
|
||||||
|
|
||||||
lvl[pos++] = ']';
|
lvl[pos++] = ']';
|
||||||
lvl[pos] = 0;
|
lvl[pos] = 0;
|
||||||
@@ -792,18 +800,24 @@ char *runlevel_string(int currlevel, int levels)
|
|||||||
char *runlevel_arr(int levels)
|
char *runlevel_arr(int levels)
|
||||||
{
|
{
|
||||||
static char lvl[42];
|
static char lvl[42];
|
||||||
|
int i = INIT_LEVEL;
|
||||||
int p = 2, s = 0;
|
int p = 2, s = 0;
|
||||||
|
|
||||||
strlcpy(lvl, "[ ", sizeof(lvl));
|
strlcpy(lvl, "[ ", sizeof(lvl));
|
||||||
for (int i = 0; i < 10; i++) {
|
do {
|
||||||
if (ISSET(levels, i)) {
|
if (ISSET(levels, i)) {
|
||||||
if (i == 0)
|
if (i == INIT_LEVEL)
|
||||||
p += snprintf(&lvl[p], sizeof(lvl) - p, "\"S\"");
|
p += snprintf(&lvl[p], sizeof(lvl) - p, "\"S\"");
|
||||||
else
|
else
|
||||||
p += snprintf(&lvl[p], sizeof(lvl) - p, "%s%c", s ? ", " : "", '0' + i);
|
p += snprintf(&lvl[p], sizeof(lvl) - p, "%s%c", s ? ", " : "", '0' + i);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
}
|
/* XXX: ugly hack to get order right: S0123456789 */
|
||||||
|
if (i == INIT_LEVEL)
|
||||||
|
i = 0;
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
} while (i < INIT_LEVEL);
|
||||||
strlcat(lvl, " ]", sizeof(lvl));
|
strlcat(lvl, " ]", sizeof(lvl));
|
||||||
|
|
||||||
return lvl;
|
return lvl;
|
||||||
@@ -1162,7 +1176,7 @@ static int show_status(char *arg)
|
|||||||
if (heading) {
|
if (heading) {
|
||||||
char title[80];
|
char title[80];
|
||||||
|
|
||||||
snprintf(title, sizeof(title), "%-*s %-*s %-8s %-12s ",
|
snprintf(title, sizeof(title), "%-*s %-*s %-8s %-13s ",
|
||||||
pw, "PID", iw, "IDENT", "STATUS", "RUNLEVELS");
|
pw, "PID", iw, "IDENT", "STATUS", "RUNLEVELS");
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
strlcat(title, "DESCRIPTION", sizeof(title));
|
strlcat(title, "DESCRIPTION", sizeof(title));
|
||||||
@@ -1184,9 +1198,9 @@ static int show_status(char *arg)
|
|||||||
|
|
||||||
lvls = runlevel_string(runlevel, svc->runlevels);
|
lvls = runlevel_string(runlevel, svc->runlevels);
|
||||||
if (strchr(lvls, '\e'))
|
if (strchr(lvls, '\e'))
|
||||||
printf("%-20.20s ", lvls);
|
printf("%-21.21s ", lvls);
|
||||||
else
|
else
|
||||||
printf("%-12.12s ", lvls);
|
printf("%-13.13s ", lvls);
|
||||||
|
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
puts(svc->desc);
|
puts(svc->desc);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
#define MATCH_CMD(l, c, x) \
|
#define MATCH_CMD(l, c, x) \
|
||||||
(!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
|
(!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
|
||||||
|
|
||||||
|
#define IS_RESERVED_RUNLEVEL(l) (l == 0 || l == 6 || l == INIT_LEVEL)
|
||||||
|
|
||||||
extern char *finit_conf;
|
extern char *finit_conf;
|
||||||
extern char *finit_rcsd;
|
extern char *finit_rcsd;
|
||||||
extern svc_t *wdog;
|
extern svc_t *wdog;
|
||||||
|
|||||||
+4
-4
@@ -1051,7 +1051,7 @@ static int service_restart(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip progress if desc disabled or bootstrap task */
|
/* Skip progress if desc disabled or bootstrap task */
|
||||||
if (!svc->desc[0] || svc_in_runlevel(svc, 0))
|
if (!svc->desc[0] || svc_in_runlevel(svc, INIT_LEVEL))
|
||||||
do_progress = 0;
|
do_progress = 0;
|
||||||
|
|
||||||
if (do_progress)
|
if (do_progress)
|
||||||
@@ -1106,13 +1106,13 @@ void service_reload_dynamic(void)
|
|||||||
*/
|
*/
|
||||||
void service_runlevel(int newlevel)
|
void service_runlevel(int newlevel)
|
||||||
{
|
{
|
||||||
if (!rescue && runlevel <= 1 && newlevel > 1)
|
if (!rescue && (runlevel == 1 || runlevel == INIT_LEVEL) && !IS_RESERVED_RUNLEVEL(newlevel))
|
||||||
networking(1);
|
networking(1);
|
||||||
|
|
||||||
sm_set_runlevel(&sm, newlevel);
|
sm_set_runlevel(&sm, newlevel);
|
||||||
sm_step(&sm);
|
sm_step(&sm);
|
||||||
|
|
||||||
if (!rescue && (runlevel <= 1 || runlevel == 6))
|
if (!rescue && IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
networking(0);
|
networking(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1538,7 +1538,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
id = "";
|
id = "";
|
||||||
|
|
||||||
levels = conf_parse_runlevels(runlevels);
|
levels = conf_parse_runlevels(runlevels);
|
||||||
if (runlevel > 0 && !ISOTHER(levels, 0)) {
|
if (runlevel != INIT_LEVEL && !ISOTHER(levels, 0)) {
|
||||||
dbg("Skipping %s%s%s, bootstrap is completed.",
|
dbg("Skipping %s%s%s, bootstrap is completed.",
|
||||||
name, id[0] ? ":" : "", id[0] ? id : "");
|
name, id[0] ? ":" : "", id[0] ? id : "");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ static void sighup_cb(uev_t *w, void *arg, int events)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
warnx("SIGHUP ignored in runlevel S and 6.");
|
warnx("SIGHUP ignored in runlevel S and 6.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ static void sigusr1_cb(uev_t *w, void *arg, int events)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
warnx("SIGUSR1 ignored in runlevel S and 6.");
|
warnx("SIGUSR1 ignored in runlevel S and 6.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ static void sigusr2_cb(uev_t *w, void *arg, int events)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
warnx("SIGUSR2 ignored in runlevel S and 6.");
|
warnx("SIGUSR2 ignored in runlevel S and 6.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -526,7 +526,7 @@ static void sigterm_cb(uev_t *w, void *arg, int events)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runlevel == 0 || runlevel == 6) {
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
warnx("SIGTERM ignored in runlevel S and 6.");
|
warnx("SIGTERM ignored in runlevel S and 6.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,10 +86,10 @@ static char *sm_status(sm_state_t state)
|
|||||||
*/
|
*/
|
||||||
static void nologin(void)
|
static void nologin(void)
|
||||||
{
|
{
|
||||||
if (runlevel == 1 || runlevel == 0 || runlevel == 6)
|
if (runlevel == 1 || IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
touch(FINIT_NOLOGIN_PATH);
|
touch(FINIT_NOLOGIN_PATH);
|
||||||
|
|
||||||
if (prevlevel == 1 || prevlevel == 0 || prevlevel == 6)
|
if (prevlevel == 1 || IS_RESERVED_RUNLEVEL(prevlevel))
|
||||||
erase(FINIT_NOLOGIN_PATH);
|
erase(FINIT_NOLOGIN_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
|
|||||||
*/
|
*/
|
||||||
int svc_clean_bootstrap(svc_t *svc)
|
int svc_clean_bootstrap(svc_t *svc)
|
||||||
{
|
{
|
||||||
if (!ISOTHER(svc->runlevels, 0)) {
|
if (!ISOTHER(svc->runlevels, INIT_LEVEL)) {
|
||||||
svc->pid = 0;
|
svc->pid = 0;
|
||||||
svc_del(svc);
|
svc_del(svc);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+3
-1
@@ -32,6 +32,7 @@
|
|||||||
# include <lite/lite.h>
|
# include <lite/lite.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
@@ -174,7 +175,8 @@ int utmp_set_dead(int pid)
|
|||||||
|
|
||||||
static int encode(int lvl)
|
static int encode(int lvl)
|
||||||
{
|
{
|
||||||
if (!lvl) return 0;
|
if (lvl == INIT_LEVEL)
|
||||||
|
return 0;
|
||||||
return lvl + '0';
|
return lvl + '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user