From 6aac230ce3d21f1e71333ec3863c7ea1afd051c3 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sun, 21 Feb 2016 12:40:53 +0200 Subject: Provide fall-back entry in init mode * src/sysvinit.c (inittab_parse): Provide default entry if inittab cannot be read or if it defined no components. * src/comp.c (component_list_is_empty): New function. * src/pies.c (pies_read_config): Always return 0 in init mode. (main): Use LOG_DAEMON in init mode. * src/pies.h (component_list_is_empty): New proto. --- src/comp.c | 6 ++ src/pies.c | 9 +- src/pies.h | 2 + src/sysvinit.c | 283 ++++++++++++++++++++++++++++++++------------------------- 4 files changed, 177 insertions(+), 123 deletions(-) diff --git a/src/comp.c b/src/comp.c index 5ddac36..38e440e 100644 --- a/src/comp.c +++ b/src/comp.c @@ -100,6 +100,12 @@ component_unlink (struct component *comp) list->tail = comp->prev; } +int +component_list_is_empty (void) +{ + return !comp_list[cur].head; +} + struct component * component_lookup_tag (int idx, const char *tag) { diff --git a/src/pies.c b/src/pies.c index 4443689..33244ad 100644 --- a/src/pies.c +++ b/src/pies.c @@ -1569,6 +1569,7 @@ pies_read_config (void) struct grecs_list_entry *ep; int err = 0; + logmsg (LOG_INFO, _("reading configuration")); component_config_begin (); for (ep = config_list->head; ep; ep = ep->next) @@ -1578,6 +1579,9 @@ pies_read_config (void) ++err; } + if (init_process) + err = 0; + if (err) component_config_rollback (); @@ -2008,7 +2012,10 @@ main (int argc, char **argv) /* Set default logging */ if (init_process) - diag_flags = DIAG_TO_STDERR | DIAG_REOPEN_LOG; + { + log_facility = LOG_DAEMON; + diag_flags = DIAG_TO_STDERR | DIAG_REOPEN_LOG; + } else diag_flags = DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR); diff --git a/src/pies.h b/src/pies.h index 5154317..939bd4c 100644 --- a/src/pies.h +++ b/src/pies.h @@ -396,6 +396,8 @@ void component_free (struct component *comp); void component_ref_incr (struct component *comp); void component_ref_decr (struct component *comp); +int component_list_is_empty (void); + void component_config_begin (void); void component_config_rollback (void); void component_config_commit (void); diff --git a/src/sysvinit.c b/src/sysvinit.c index 41d5b9d..695a22a 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -60,7 +60,8 @@ int prevlevel = 'N'; int initdefault; /* Default runlevel */ int dfl_level; -int emergency_shell; +char *emergency_shell = "/sbin/sulogin"; +int emergency; int @@ -442,8 +443,7 @@ sysvinit_set_runlevel (int newlevel) default: if (newlevel == runlevel) - { - } + break; else if (runlevel_index (newlevel) == -1) return -1; else @@ -757,8 +757,8 @@ sysvinit_begin () sysvinit_runlevel_setup (PIES_COMP_DEFAULT); add_extra_sigv (sigv, ARRAY_SIZE (sigv)); sysvinit_sysdep_begin (); - if (emergency_shell) - start_shell ("/sbin/sulogin"); + if (emergency) + start_shell (emergency_shell); } #define IS_RUNNING_DISABLED_PROG(prog) \ @@ -954,149 +954,188 @@ strupr (char *s) return s; } -int -inittab_parse (const char *file) +struct inittab_ctx { - FILE *fp; - size_t size = 0; - char *buf = NULL; - unsigned line_no = 0; - int err = 0; - - fp = fopen (file, "r"); - if (!fp) - { - logmsg (LOG_ERR, - _("cannot open configuration file %s: %s"), - file, strerror (errno)); - return 1; - } + char *buf; + size_t size; + char const *file; + unsigned line_no; +}; - while (getline (&buf, &size, fp) >= 0) - { - char *id, *runlevels, *action, *process, *p; - struct action_parser *ap; - struct component *comp; - struct wordsplit ws; - - line_no++; - for (p = buf; *p && c_isblank (*p); p++) - ; +enum inittab_status + { + inittab_ok, + inittab_err, + inittab_stop + }; - if (!p || *p == '\n') - continue; +static enum inittab_status +inittab_parse_line (struct inittab_ctx *ctx) +{ + char *id, *runlevels, *action, *process, *p; + struct action_parser *ap; + struct component *comp; + struct wordsplit ws; + + ctx->line_no++; + for (p = ctx->buf; *p && c_isblank (*p); p++) + ; - if (*p == '#') + if (!p || *p == '\n') + return inittab_ok; + + if (*p == '#') + { + if (wordsplit (p+1, &ws, WRDSF_DEFFLAGS)) { - if (wordsplit (p+1, &ws, WRDSF_DEFFLAGS)) + logmsg (LOG_ERR, "%s:%u: wordsplit: %s", ctx->file, ctx->line_no, + strerror (errno)); + return inittab_err; + } + /* pies pragma debug N */ + /* pies pragma next FORMAT FILE */ + /* pies pragma stop */ + if (ws.ws_wordc > 2 && strcmp (ws.ws_wordv[0], "pies") == 0 && + strcmp (ws.ws_wordv[1], "pragma") == 0) + { + if (strcmp (ws.ws_wordv[2], "debug") == 0) { - logmsg (LOG_ERR, "%s:%u: wordsplit: %s", file, line_no, - strerror (errno)); - err = 1; + if (ws.ws_wordc == 4) + debug_level = atoi (ws.ws_wordv[3]); } - /* pies pragma debug N */ - /* pies pragma next FORMAT FILE */ - /* pies pragma stop */ - if (ws.ws_wordc > 2 && strcmp (ws.ws_wordv[0], "pies") == 0 && - strcmp (ws.ws_wordv[1], "pragma") == 0) + else if (strcmp (ws.ws_wordv[2], "next") == 0) { - if (strcmp (ws.ws_wordv[2], "debug") == 0) - { - if (ws.ws_wordc == 4) - debug_level = atoi (ws.ws_wordv[3]); - } - else if (strcmp (ws.ws_wordv[2], "next") == 0) + if (ws.ws_wordc >= 5) { - if (ws.ws_wordc >= 5) - { - struct config_syntax *synt = - str_to_config_syntax (ws.ws_wordv[3]); + struct config_syntax *synt = + str_to_config_syntax (ws.ws_wordv[3]); - if (!synt) - logmsg (LOG_ERR, "%s:%u: %s", - file, line_no, _("unknown syntax type")); - else - config_file_add (synt, ws.ws_wordv[4]); - } - else if (ws.ws_wordc == 4) - config_file_add_type (CONF_PIES, ws.ws_wordv[3]); - } - else if (strcmp (ws.ws_wordv[2], "stop") == 0) - { - wordsplit_free (&ws); - break; + if (!synt) + logmsg (LOG_ERR, "%s:%u: %s", + ctx->file, ctx->line_no, _("unknown syntax type")); + else + config_file_add (synt, ws.ws_wordv[4]); } + else if (ws.ws_wordc == 4) + config_file_add_type (CONF_PIES, ws.ws_wordv[3]); } - - wordsplit_free (&ws); - continue; - } - - id = getfld (p, &p); - runlevels = getfld (p, &p); - action = getfld (p, &p); - process = p; - - if (!id || !runlevels || !action || !process) - { - logmsg (LOG_ERR, "%s:%u: %s", file, line_no, _("not enough fields")); - err = 1; - continue; - } - - if (strcmp (action, "initdefault") == 0) - { - if (!runlevels[0] || !is_valid_runlevel (runlevels[0])) + else if (strcmp (ws.ws_wordv[2], "stop") == 0) { - logmsg (LOG_ERR, "%s:%u: %s", - file, line_no, _("invalid runlevel")); - err = 1; + wordsplit_free (&ws); + return inittab_stop; } - else - initdefault = toupper (runlevels[0]); - continue; } + + wordsplit_free (&ws); + return inittab_ok; + } + + id = getfld (p, &p); + runlevels = getfld (p, &p); + action = getfld (p, &p); + process = p; - if (strcmp (action, "off") == 0) - /* Ignore the entry */ - continue; + if (!id || !runlevels || !action || !process) + { + logmsg (LOG_ERR, "%s:%u: %s", + ctx->file, ctx->line_no, _("not enough fields")); + return inittab_err; + } - ap = find_action_parser (action); - if (!ap) + if (strcmp (action, "initdefault") == 0) + { + if (!runlevels[0] || !is_valid_runlevel (runlevels[0])) { - logmsg (LOG_ERR, "%s:%u: %s", file, line_no, _("unknown action")); - err = 1; - continue; + logmsg (LOG_ERR, "%s:%u: %s", + ctx->file, ctx->line_no, _("invalid runlevel")); + return inittab_err; } + else + initdefault = toupper (runlevels[0]); + return inittab_ok; + } + + if (strcmp (action, "off") == 0) + /* Ignore the entry */ + return inittab_ok; + + ap = find_action_parser (action); + if (!ap) + { + logmsg (LOG_ERR, "%s:%u: %s", ctx->file, ctx->line_no, + _("unknown action")); + return inittab_err; + } - comp = component_create (id); - comp->mode = ap->mode; - comp->runlevels = grecs_strdup (strupr (runlevels)); + comp = component_create (id); + comp->mode = ap->mode; + comp->runlevels = grecs_strdup (strupr (runlevels)); - if (wordsplit (process, &ws, WRDSF_DEFFLAGS)) - { - component_free (comp); - logmsg (LOG_ERR, "%s:%u: wordsplit: %s", file, line_no, - strerror (errno)); - err = 1; - continue; - } - wordsplit_getwords (&ws, &comp->argc, &comp->argv); - comp->program = grecs_strdup (comp->argv[0]); - wordsplit_free (&ws); + if (wordsplit (process, &ws, WRDSF_DEFFLAGS)) + { + component_free (comp); + logmsg (LOG_ERR, "%s:%u: wordsplit: %s", ctx->file, ctx->line_no, + strerror (errno)); + return inittab_err; + } + wordsplit_getwords (&ws, &comp->argc, &comp->argv); + comp->program = grecs_strdup (comp->argv[0]); + wordsplit_free (&ws); - comp->flags |= CF_SIGGROUP; + comp->flags |= CF_SIGGROUP; - if (ap->parser && ap->parser (comp, file, line_no)) + if (ap->parser && ap->parser (comp, ctx->file, ctx->line_no)) + { + component_free (comp); + return inittab_err; + } + return inittab_ok; +} + +int +inittab_parse (const char *file) +{ + FILE *fp; + struct inittab_ctx ctx; + int err; + + ctx.size = 0; + ctx.buf = NULL; + ctx.file = file; + ctx.line_no = 0; + + fp = fopen (file, "r"); + if (fp) + { + while (getline (&ctx.buf, &ctx.size, fp) >= 0) { - component_free (comp); - err = 1; - continue; + enum inittab_status st = inittab_parse_line (&ctx); + if (st == inittab_err) + err = 1; + else if (st == inittab_stop) + break; } + fclose (fp); + } + else + { + logmsg (LOG_ERR, + _("cannot open configuration file %s: %s"), + file, strerror (errno)); + err = 1; } - free (buf); - fclose (fp); + if (component_list_is_empty ()) + { + /* Provide default inittab entry */ + ctx.file = __FILE__; + ctx.line_no = __LINE__; + grecs_asprintf (&ctx.buf, &ctx.size, "~~:%s:wait:%s\n", + valid_runlevels, emergency_shell); + inittab_parse_line (&ctx); + } + + free (ctx.buf); return err; } @@ -1182,7 +1221,7 @@ sysvinit_parse_argv (int argc, char **argv) if (!strcmp (arg, "single") || !strcmp (arg, "-s")) dfl_level = 'S'; else if (!strcmp (arg, "-b") || !strcmp (arg, "emergency")) - emergency_shell = 1; + emergency = 1; else if (!arg[1] && strchr (valid_runlevels, (c = toupper (arg[0])))) dfl_level = c; } -- cgit v1.2.1