diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/pies.c | 22 | ||||
-rw-r--r-- | src/pies.h | 13 | ||||
-rw-r--r-- | src/progman.c | 58 | ||||
-rw-r--r-- | src/sysvinit.c | 172 |
5 files changed, 226 insertions, 40 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 44e0a8d..0fca105 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ pies_SOURCES = \ pies.c\ progman.c\ socket.c\ + sysvinit.c\ url.c\ userprivs.c @@ -39,8 +39,6 @@ enum pies_command { }; enum pies_command command; -int initdefault; /* Default runlevel */ -int dfl_level; char *statedir = DEFAULT_STATE_DIR; char *instance; char *pidfile; @@ -834,6 +832,17 @@ static struct tokendef modetab[] = { {"nostartaccept", pies_comp_inetd}, {"pass-fd", pies_comp_pass_fd}, {"pass", pies_comp_pass_fd}, + {"boot", pies_comp_boot}, + {"bootwait", pies_comp_boot}, + {"powerfail", pies_comp_powerfail}, + {"powerwait", pies_comp_powerwait}, + {"powerokwait", pies_comp_powerokwait}, + {"ctrlaltdel", pies_comp_ctrlaltdel}, + {"ondemand", pies_comp_ondemand}, + {"sysinit", pies_comp_sysinit}, + {"powerfailnow", pies_comp_powerfailnow}, + {"kbrequest", pies_comp_kbrequest}, + {NULL} }; @@ -2132,15 +2141,6 @@ set_console_dev () console_device = "/dev/null"; } -static void -inittrans () -{ - if (progman_running_p ()) - /* Noting to do if there are processes left in the previous runlevel */ - return; - -} - int main (int argc, char **argv) { @@ -145,10 +145,10 @@ enum pies_comp_mode /* ** Init-style components */ - + pies_mark_sysvinit, /* Start the process when the specified runlevel is entered and wait for its termination */ - pies_comp_wait, + pies_comp_wait = pies_mark_sysvinit, /* Execute the component once, when the specified runlevel is entered */ pies_comp_once, /* Execute the component during system boot. Ignore runlevel settings. */ @@ -183,6 +183,8 @@ enum pies_comp_mode pies_comp_respawn = pies_comp_exec, }; +#define is_sysvinit(m) ((m)>=pies_mark_sysvinit) + #define CF_DISABLED 0x001 /* The componenet is disabled */ #define CF_PRECIOUS 0x002 /* The component is precious (should not be disabled) */ @@ -274,6 +276,7 @@ extern char *qotdfile; extern int init_process; extern char *console_device; extern int initdefault; +extern int dfl_level; void register_prog (struct component *comp); int progman_running_p (void); @@ -445,5 +448,11 @@ struct inetd_builtin }; struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); + +/* sysvinit.c */ +int runlevel_match (struct component *comp); +void inittrans (void); +int is_comp_wait (struct component *comp); + diff --git a/src/progman.c b/src/progman.c index 639c22f..e25219a 100644 --- a/src/progman.c +++ b/src/progman.c @@ -409,8 +409,11 @@ progman_running_p () struct prog *prog; for (prog = proghead; prog; prog = prog->next) - if (prog->pid > 0) - return 1; + { + if (IS_COMPONENT (prog) && is_comp_wait (prog->v.p.comp) && + prog->pid > 0) + return 1; + } return 0; } @@ -1181,6 +1184,14 @@ prog_start (struct prog *prog) if (prog->pid > 0 || !IS_COMPONENT (prog)) return; + + if (is_sysvinit (prog->v.p.comp->mode) && !init_process && + prog->v.p.status != status_disabled) + { + logmsg (LOG_NOTICE, "disabling sysvinit component %s", prog->tag); + prog->v.p.status = status_disabled; + return; + } /* This call returns 1 in two cases: Either prog is marked as disabled, in which case there's nothing more to do, or one or more of its @@ -1256,9 +1267,17 @@ prog_start (struct prog *prog) prog_start_prologue (prog); switch (prog->v.p.comp->mode) { - case pies_comp_pass_fd: - case pies_comp_exec: - case pies_comp_once: + case pies_comp_accept: + case pies_comp_inetd: + prog_sockenv (prog); + + dup2 (prog->v.p.socket, 0); + dup2 (prog->v.p.socket, 1); + close (prog->v.p.socket); + prog->v.p.socket = -1; + break; + + default: if (init_process) { int fd = console_open (O_RDWR|O_NOCTTY); @@ -1288,16 +1307,6 @@ prog_start (struct prog *prog) } } break; - - case pies_comp_accept: - case pies_comp_inetd: - prog_sockenv (prog); - - dup2 (prog->v.p.socket, 0); - dup2 (prog->v.p.socket, 1); - close (prog->v.p.socket); - prog->v.p.socket = -1; - break; } if (!init_process) @@ -1346,8 +1355,9 @@ prog_start (struct prog *prog) { disable_socket (prog->v.p.socket); } - else if (prog->v.p.comp->mode != pies_comp_exec && - prog->v.p.comp->mode != pies_comp_once) + else if (prog->v.p.comp->mode == pies_comp_accept || + prog->v.p.comp->mode == pies_comp_inetd || + prog->v.p.comp->mode == pies_comp_pass_fd) close (prog->v.p.socket); prog->pid = pid; prog->v.p.status = status_enabled; @@ -1760,14 +1770,6 @@ progman_recompute_alarm () -static int -runlevel_match (struct prog *prog) -{ - if (!initdefault || !prog->v.p.comp->runlevels) - return 1; - return !!strchr (prog->v.p.comp->runlevels, initdefault); -} - void progman_start () { @@ -1781,7 +1783,7 @@ progman_start () if (prog->v.p.comp->mode == pies_comp_inetd) { if ((prog->v.p.comp->flags & CF_DISABLED) - || !runlevel_match (prog)) + || !runlevel_match (prog->v.p.comp)) disable_socket (prog->v.p.socket); else { @@ -1790,7 +1792,7 @@ progman_start () } } else if ((prog->v.p.status == status_enabled && prog->pid == 0 - && runlevel_match (prog)) + && runlevel_match (prog->v.p.comp)) || prog->v.p.status == status_sleeping) prog_start (prog); } @@ -1872,6 +1874,8 @@ prog_start_prerequisites (struct prog *prog) int i; int ret; + if (prog->v.p.status == status_disabled) + return 1; if (!prog->prereq) return 0; /* Ok to startup */ debug (1, ("starting prerequisites of %s", prog->tag)); 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; +} + |