diff options
Diffstat (limited to 'src/sysvinit.c')
-rw-r--r-- | src/sysvinit.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/sysvinit.c b/src/sysvinit.c new file mode 100644 index 0000000..cfef974 --- /dev/null +++ b/src/sysvinit.c @@ -0,0 +1,172 @@ +/* This file is part of GNU Pies. + Copyright (C) 2013 Sergey Poznyakoff + + GNU Pies is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Pies is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + +#include "pies.h" + +enum boot_state + { + sysinit, + boot, + single0, + single1, + normal, + max_boot_state + }; + +static char *boot_state_name[] = { + "sysinit", + "boot", + "single0", + "single1", + "normal" +}; + +static char boot_state_str[] = "#*sS "; + +static const char valid_runlevels[] = "0123456789S"; + +static int boot_trans_tab[max_boot_state][sizeof(valid_runlevels)-1] = { + /* 0, 1, 2, 3, 4, */ + /* 5, 6, 7, 8, 9, S */ + /* sysinit */ { boot, boot, boot, boot, boot, + boot, boot, boot, boot, boot, single0 }, + /* boot */ { normal, normal, normal, normal, normal, + normal, normal, normal, normal, normal, single1 }, + /* single0 */ { normal, normal, normal, normal, normal, + normal, normal, normal, normal, normal, single0 }, + /* single1 */ { normal, normal, normal, normal, normal, + normal, normal, normal, normal, normal, single1 }, + /* normal */ { normal, normal, normal, normal, normal, + normal, normal, normal, normal, normal, single1 }, +}; + +enum boot_state boot_state; +int runlevel; + +int initdefault; /* Default runlevel */ +int dfl_level; + +static int +runlevel_index (int n) +{ + char *p = strchr (valid_runlevels, n); + if (!p) + return -1; + return p - valid_runlevels; +} + +int +runlevel_match (struct component *comp) +{ + if (init_process) + { + switch (boot_state) + { + case sysinit: + return comp->mode == pies_comp_sysinit; + + case boot: + return comp->mode == pies_comp_boot || + comp->mode == pies_comp_bootwait; + + case single0: + case single1: + case normal: + switch (comp->mode) + { + case pies_comp_sysinit: + case pies_comp_boot: + case pies_comp_bootwait: + return 0; + case pies_comp_powerfail: + case pies_comp_powerwait: + case pies_comp_powerokwait: + case pies_comp_ctrlaltdel: + case pies_comp_ondemand: + case pies_comp_powerfailnow: + case pies_comp_kbrequest: + /* FIXME */ + return 0; + } + + if (!comp->runlevels) + return 1; + return !!strchr (comp->runlevels, runlevel); + } + } + return 1; +} + +void +inittrans () +{ + int n; + int newlevel = 0; + enum boot_state newstate; + + if (progman_running_p ()) + /* Noting to do if there are processes left in the previous runlevel */ + return; + + n = runlevel_index (runlevel); + if (n == -1) + n = 11; /* assume S */ + + newstate = boot_trans_tab[boot_state][n]; + if (newstate != boot_state) + { + debug (1, ("STATE TRANS: %s -> %s", boot_state_name[boot_state], + boot_state_name[newstate])); + boot_state = newstate; + } + + switch (boot_state) + { + case sysinit: + case boot: + break; + case single0: + case single1: + newlevel = 'S'; + break; + case normal: + /* boot -> normal */ + newlevel = dfl_level ? dfl_level : initdefault; + } + if (newlevel && newlevel != runlevel) + { + debug (1, ("RL TRANS: %c -> %c", runlevel, newlevel)); + runlevel = newlevel; + } +} + +/* Return true if the progman should wait for the component to + terminate. */ +int +is_comp_wait (struct component *comp) +{ + switch (comp->mode) + { + case pies_comp_boot: + case pies_comp_powerfail: + case pies_comp_ctrlaltdel: + case pies_comp_powerfailnow: + case pies_comp_kbrequest: + return 0; + } + return 1; +} + |