diff options
-rw-r--r-- | src/pies.c | 12 | ||||
-rw-r--r-- | src/pies.h | 11 | ||||
-rw-r--r-- | src/progman.c | 55 | ||||
-rw-r--r-- | src/sysvinit.c | 124 |
4 files changed, 142 insertions, 60 deletions
@@ -956,13 +956,13 @@ _cb_flags (enum grecs_callback_command cmd, grecs_error (locus, 0, _("too many arguments")); return 1; } return 0; } -static const char valid_runlevels[] = "0123456Ss"; +static const char valid_runlevels[] = "0123456789Ss"; static int _cb_initdefault (enum grecs_callback_command cmd, grecs_locus_t *locus, void *varptr, grecs_value_t *value, void *cb_data) { @@ -2306,12 +2306,13 @@ main (int argc, char **argv) } if (init_process) { foreground = 1; set_console_dev (); + sysvinit_begin (); } else switch (pies_check_status (&pid)) { case pies_status_ctr: break; @@ -2357,15 +2358,18 @@ main (int argc, char **argv) progman_create_sockets (); progman_start (); do { - if (init_process) - inittrans (); - if (!children_cleanup) + if (init_process && inittrans ()) + { + got_alarm = 1; + action = ACTION_CONT; + } + else if (!children_cleanup) pies_pause (); switch (action) { case ACTION_COMPRELOAD: stop_components (); progman_cleanup (0); @@ -180,14 +180,12 @@ enum pies_comp_mode pies_comp_kbrequest, /* Restart the component wherever it terminates */ 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) */ #define CF_WAIT 0x004 /* Wait for the component instance to terminate. */ #define CF_TCPMUX 0x008 /* A plain TCPMUX service */ @@ -250,12 +248,14 @@ struct component struct redirector redir[2]; /* Repeaters for stdout and stderr */ /* Actions to execute on various exit codes: */ struct action *act_head, *act_tail; struct action act_temp; /* Auxiliary object used during configuration */ }; +#define is_sysvinit(cp) ((cp)->mode >= pies_mark_sysvinit || (cp)->runlevels) + union pies_sockaddr_storage { struct sockaddr s; struct sockaddr_in s_in; struct sockaddr_un s_un; }; @@ -298,12 +298,15 @@ struct component *progman_lookup_tcpmux (const char *service, void progman_run_comp (struct component *comp, int fd, union pies_sockaddr_storage *sa, socklen_t salen); void progman_iterate_comp (int (*fun) (struct component *, void *), void *data); +void progman_sysvinit_enable (int (*fun) (struct component *, int, void *), + void *data); + void fd_report (int fd, const char *msg); int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen); void log_setup (int want_stderr); void signal_setup (RETSIGTYPE (*sf)(int)); @@ -447,12 +450,12 @@ struct inetd_builtin void (*fun) (int, struct component const *); }; struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); /* sysvinit.c */ -int runlevel_match (struct component *comp); -void inittrans (void); +void sysvinit_begin (void); +int inittrans (void); int is_comp_wait (struct component *comp); diff --git a/src/progman.c b/src/progman.c index f0d0de6..15b8c44 100644 --- a/src/progman.c +++ b/src/progman.c @@ -103,12 +103,35 @@ progman_iterate_comp (int (*fun) (struct component *, void *), void *data) && !(prog->v.p.comp->mode == pies_comp_inetd && prog->v.p.listener) && fun (prog->v.p.comp, data)) break; } +void +progman_sysvinit_enable (int (*fun) (struct component *, int, void *), + void *data) +{ + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + if (IS_COMPONENT (prog) && is_sysvinit (prog->v.p.comp)) + { + int rc = fun (prog->v.p.comp, prog->v.p.status == status_finished, + data); + if (rc < 0) + continue; + if (rc) + prog->v.p.status = status_enabled; + else + prog->v.p.status = status_disabled; + debug (1, ("%s: %s", prog->tag, + prog->v.p.status == status_enabled ? + "enabled" : "disabled")); + } +} + static struct prog * prog_lookup_by_pid (pid_t pid) { struct prog *prog; for (prog = proghead; prog; prog = prog->next) @@ -409,13 +432,16 @@ progman_running_p () struct prog *prog; for (prog = proghead; prog; prog = prog->next) { if (IS_COMPONENT (prog) && is_comp_wait (prog->v.p.comp) && prog->pid > 0) - return 1; + { + debug (1, ("COMP %s still running", prog->tag)); + return 1; + } } return 0; } size_t progman_running_count () @@ -1182,20 +1208,27 @@ prog_start (struct prog *prog) int redir[2]; fd_set fdset; if (prog->pid > 0 || !IS_COMPONENT (prog)) return; - if (is_sysvinit (prog->v.p.comp->mode) && !init_process && - prog->v.p.status != status_disabled) + if (is_sysvinit (prog->v.p.comp)) { - logmsg (LOG_NOTICE, "disabling sysvinit component %s", prog->tag); - prog->v.p.status = status_disabled; - return; + if (!init_process) + { + if (prog->v.p.status != status_disabled) + { + logmsg (LOG_NOTICE, "disabling sysvinit component %s", + prog->tag); + prog->v.p.status = status_disabled; + } + return; + } + debug (1, ("ok to start %s", prog->v.p.comp->tag)); } - + /* 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 prerequisites are in status_stopping. In the latter case either the components in question will exit or a SIGALRM will get delivered. In both cases, it will cause further processing of `prog'. */ if (prog_start_prerequisites (prog)) @@ -1779,23 +1812,21 @@ progman_start () debug (1, ("starting components")); for (prog = proghead; prog; prog = prog->next) if (IS_COMPONENT (prog)) { if (prog->v.p.comp->mode == pies_comp_inetd) { - if ((prog->v.p.comp->flags & CF_DISABLED) - || !runlevel_match (prog->v.p.comp)) + if (prog->v.p.comp->flags & CF_DISABLED) disable_socket (prog->v.p.socket); else { prog->v.p.status = status_listener; enable_socket (prog->v.p.socket); } } - else if ((prog->v.p.status == status_enabled && prog->pid == 0 - && runlevel_match (prog->v.p.comp)) + else if ((prog->v.p.status == status_enabled && prog->pid == 0) || prog->v.p.status == status_sleeping) prog_start (prog); } } static void @@ -2456,13 +2487,13 @@ progman_cleanup (int expect_term) prog_stop_redirectors (prog); destroy_prog (&prog); react (listener, status, pid); if (listener->v.p.comp->flags & CF_WAIT) enable_socket (listener->v.p.socket); } - else if (is_sysvinit(prog->v.p.comp->mode)) + else if (prog->v.p.comp->mode >= pies_mark_sysvinit) { prog->v.p.status = status_finished; } else { prog->v.p.status = status_enabled; diff --git a/src/sysvinit.c b/src/sysvinit.c index e09802f..5a0d98a 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -51,89 +51,118 @@ static int boot_trans_tab[max_boot_state][sizeof(valid_runlevels)-1] = { 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 runlevel = 0; int initdefault; /* Default runlevel */ int dfl_level; static int runlevel_index (int n) { - char *p = strchr (valid_runlevels, n); + char *p; + + if (n == 0) + return -1; + + p = strchr (valid_runlevels, n); if (!p) return -1; return p - valid_runlevels; } -int -runlevel_match (struct component *comp) +static int +enablecomp (struct component *comp, int finished, void *data) { - if (init_process) + int *wait = data; + int rc; + + switch (boot_state) { - 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 sysinit: + return comp->mode == pies_comp_sysinit; - 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; - } + case boot: + return comp->mode == pies_comp_boot || comp->mode == pies_comp_bootwait; - if (!comp->runlevels) - return 1; - return !!strchr (comp->runlevels, runlevel); + 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; } } - return 1; + rc = !!strchr (comp->runlevels, runlevel); + if (!rc) + return rc; + if (finished) + return -1; + if (wait) + { + if (comp->mode == pies_comp_wait) + { + *wait = 1; + return 1; + } + return 0; + } + return rc; } void +sysvinit_begin () +{ + progman_sysvinit_enable (enablecomp, NULL); +} + +int inittrans () { int n; int newlevel = 0; enum boot_state newstate; - + int trans = 0; + static int wait = 0; + if (progman_running_p ()) /* Noting to do if there are processes left in the previous runlevel */ - return; + return 0; - n = runlevel_index (runlevel); + if (runlevel == 0) + n = runlevel_index (dfl_level ? dfl_level : initdefault); + else + n = runlevel_index (runlevel); if (n == -1) - n = 11; /* assume S */ + n = runlevel_index ('S'); newstate = boot_trans_tab[boot_state][n]; + debug (1, ("STATE TRANS: %s(%c,%d) -> %s", boot_state_name[boot_state], + runlevel,n, + boot_state_name[newstate])); if (newstate != boot_state) { debug (1, ("STATE TRANS: %s -> %s", boot_state_name[boot_state], boot_state_name[newstate])); boot_state = newstate; + trans = 1; } switch (boot_state) { case sysinit: case boot: @@ -147,13 +176,28 @@ inittrans () newlevel = dfl_level ? dfl_level : initdefault; } if (newlevel && newlevel != runlevel) { debug (1, ("RL TRANS: %c -> %c", runlevel, newlevel)); runlevel = newlevel; + trans = 1; + wait = 0; + } + if (wait) + trans = 1; + if (trans) + { + if (wait == 0) + { + progman_sysvinit_enable (enablecomp, &wait); + if (wait) + return 1; + } + progman_sysvinit_enable (enablecomp, NULL); } + return trans; } /* Return true if the progman should wait for the component to terminate. */ int is_comp_wait (struct component *comp) |