diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/acl.c | 2 | ||||
-rw-r--r-- | src/acl.h | 2 | ||||
-rw-r--r-- | src/cmdline.opt | 52 | ||||
-rw-r--r-- | src/comp.c | 110 | ||||
-rw-r--r-- | src/ctl.c | 45 | ||||
-rw-r--r-- | src/depmap.c | 2 | ||||
-rw-r--r-- | src/diag.c | 2 | ||||
-rw-r--r-- | src/inetd-bi.c | 2 | ||||
-rw-r--r-- | src/inetd.c | 8 | ||||
-rw-r--r-- | src/inetd.in | 2 | ||||
-rw-r--r-- | src/limits.c | 2 | ||||
-rw-r--r-- | src/meta1parse.c | 5 | ||||
-rw-r--r-- | src/pies.c | 247 | ||||
-rw-r--r-- | src/pies.h | 28 | ||||
-rw-r--r-- | src/pies_syslog.h | 2 | ||||
-rw-r--r-- | src/piesctl-cl.opt | 33 | ||||
-rw-r--r-- | src/piesctl.c | 81 | ||||
-rw-r--r-- | src/pp-setup | 106 | ||||
-rw-r--r-- | src/prog.h | 8 | ||||
-rw-r--r-- | src/progman.c | 248 | ||||
-rw-r--r-- | src/socket.c | 2 | ||||
-rw-r--r-- | src/sysdep.c | 2 | ||||
-rw-r--r-- | src/syslog.c | 81 | ||||
-rw-r--r-- | src/sysvinit.c | 2 | ||||
-rw-r--r-- | src/telinit.opt | 2 | ||||
-rw-r--r-- | src/userprivs.c | 2 | ||||
-rw-r--r-- | src/utmp.c | 2 |
28 files changed, 694 insertions, 398 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7f1aa06..05dfc6d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # This file is part of GNU Pies. -# Copyright (C) 2008-2020 Sergey Poznyakoff +# Copyright (C) 2008-2023 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 @@ -52,9 +52,7 @@ noinst_HEADERS = \ BUILT_SOURCES=cmdline.h piesctl-cl.h telinit.h -incdir=$(pkgdatadir)/$(VERSION)/include -inc_DATA = pp-setup -EXTRA_DIST = cmdline.opt piesctl-cl.opt telinit.opt pp-setup inetd.in +EXTRA_DIST = cmdline.opt piesctl-cl.opt telinit.opt inetd.in SUFFIXES=.opt .c .h .opt.h: @@ -90,12 +88,12 @@ AM_CPPFLAGS=\ -I$(top_builddir)/gnu\ @GRECS_INCLUDES@\ -DDEFAULT_PREPROCESSOR="$(DEFAULT_PREPROCESSOR)"\ - -DDEFAULT_VERSION_INCLUDE_DIR=\"$(incdir)\"\ - -DDEFAULT_INCLUDE_DIR=\"$(pkgdatadir)/include\"\ + -DDEFAULT_INCLUDE_PATH=\"@DEFAULT_INCLUDE_PATH@\"\ -DDEFAULT_STATE_DIR=\"$(pkgstatedir)\"\ -DDEFAULT_PIES_CONTROL_URL='"$(DEFAULT_PIES_CONTROL_URL)"'\ -DDEFAULT_INIT_CONTROL_URL='"$(DEFAULT_INIT_CONTROL_URL)"'\ - -DEMERGENCY_SHELL='"$(EMERGENCY_SHELL)"' + -DEMERGENCY_SHELL='"$(EMERGENCY_SHELL)"' \ + -DFALLBACK_LOG='"$(FALLBACK_LOG)"' EXTRA_SCRIPTS = inetd sbin_SCRIPTS = @INETD@ @@ -1,5 +1,5 @@ /* This file is part of GNU Pies - Copyright (C) 2009-2020 Sergey Poznyakoff + Copyright (C) 2009-2023 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 @@ -1,5 +1,5 @@ /* This file is part of GNU Pies - Copyright (C) 2009-2020 Sergey Poznyakoff + Copyright (C) 2009-2023 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 diff --git a/src/cmdline.opt b/src/cmdline.opt index b69e215..c1b5850 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. -*- c -*- - Copyright (C) 2008-2020 Sergey Poznyakoff + Copyright (C) 2008-2023 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 @@ -14,11 +14,13 @@ You should have received a copy of the GNU General Public License along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ +char *incpath = DEFAULT_INCLUDE_PATH; + OPTIONS_BEGIN("pies", [<process invocation and execution supervisor>], [<>], [<gnu>], - [<copyright_year=2008-2020>], + [<copyright_year=2008-2023>], [<copyright_holder=Sergey Poznyakoff>]) GROUP(Operation Mode) @@ -129,10 +131,28 @@ CPP(#endif) GROUP(Preprocessor) +OPTION(preprocessor,,COMMAND, + [<use COMMAND instead of the default preprocessor>]) +BEGIN + grecs_preprocessor = optarg; +END + +OPTION(no-preprocessor,,, + [<disable preprocessing>]) +BEGIN + grecs_preprocessor = NULL; +END + OPTION(include-directory,I,DIR, [<add include directory>]) BEGIN - grecs_preproc_add_include_dir(optarg); + pp_add_option ("-I", optarg); +END + +OPTION(no-include,,, + [<clear default preprocessor search path>]) +BEGIN + incpath = NULL; END OPTION(define,D,[<NAME[=VALUE]>], @@ -201,6 +221,13 @@ BEGIN command = COM_TRACE_PREREQ; END +OPTION(list-shutdown-sequence,,, + [<list components in shutdown sequence ordering>]) +BEGIN + log_to_stderr_only = 1; + command = COM_LIST_SHUTDOWN_SEQUENCE; +END + OPTION(source-info,,, [<show source info with debugging messages>]) BEGIN @@ -215,13 +242,29 @@ END OPTIONS_END +static void +pies_help_hook (FILE *fp) +{ + if (DEFAULT_PREPROCESSOR) + { + fprintf (fp, _("This pies preprocesses its configuration using %s\n"), + DEFAULT_PREPROCESSOR); + fprintf (fp, _("Preprocessor include path: %s\n"), + DEFAULT_INCLUDE_PATH); + } + else + fprintf (fp, _("This pies does not use configuration preprocessor.\n")); + fputc ('\n', fp); +} + void parse_options (int *pargc, char ***pargv) { int argc = *pargc; char **argv = *pargv; int index; - + + proginfo.print_help_hook = pies_help_hook; if (SYSVINIT_ACTIVE) { sysvinit_parse_argv (argc, argv); @@ -230,6 +273,7 @@ parse_options (int *pargc, char ***pargv) else { GETOPT(argc, argv, index); + pp_init (incpath); } *pargc -= index; *pargv += index; @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2016-2020 Sergey Poznyakoff + Copyright (C) 2016-2023 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 @@ -157,6 +157,7 @@ component_create (const char *name) comp->redir[RETR_OUT].type = comp->redir[RETR_ERR].type = redir_null; comp->tag = grecs_strdup (name); comp->socket_type = SOCK_STREAM; + comp->sigterm = SIGTERM; component_append (comp); } return comp; @@ -218,8 +219,10 @@ argvcmp (char **a, char **b) { size_t i; - if (!a != !b) - return 1; + if (!a) + return !!b; + else if (!b) + return !!a; for (i = 0; a[i]; i++) if (!b[i] || strcmp (b[i], a[i])) @@ -271,8 +274,10 @@ component_match (struct component *comp, struct component *ref) EQ (mode); FN (tag, safe_strcmp); FN (program, safe_strcmp); + FN (command, safe_strcmp); EQ (argc); FN (argv, argvcmp); + FN (envop, envop_cmp); FN (dir, safe_strcmp); FN (prereq, grecs_list_compare); FN (depend, grecs_list_compare); @@ -280,6 +285,7 @@ component_match (struct component *comp, struct component *ref) EQ (max_instances); FN (rmfile, safe_strcmp); FNP (privs, pies_privs_cmp); + EQ (umask); FN (limits, limits_cmp); FN (runlevels, safe_strcmp); EQ (max_rate); @@ -478,6 +484,25 @@ component_build_depmap (void) } } +/* + * Recursively increase shutdown sequence numbers for all prerequisites + * of the given component. + */ +static void +compute_shutdown_sequence (struct component *comp) +{ + pies_depmap_pos_t pos; + struct component *dep; + for (dep = component_depmap_first (depmap_col, comp->arridx, &pos); + dep; + dep = component_depmap_next (pos)) + { + dep->shutdown_seqno++; + compute_shutdown_sequence (dep); + } + depmap_end (pos); +} + void component_config_commit (void) { @@ -527,10 +552,83 @@ component_config_commit (void) /* Build dependency map */ component_build_depmap (); - /* Register new progs */ + /* Register new progs and assign shutdown sequence numbers */ for (comp = comp_list[cur].head; comp; comp = comp->next) - if (!comp->prog) - register_prog (comp); + { + if (!comp->prog) + register_prog (comp); + compute_shutdown_sequence (comp); + } +} + +static int +shutdown_seqno_comp (void const *a, void const *b) +{ + struct component const *ca = *(struct component const **) a; + struct component const *cb = *(struct component const **) b; + if (ca->shutdown_seqno < cb->shutdown_seqno) + return -1; + else if (ca->shutdown_seqno > cb->shutdown_seqno) + return 1; + return 0; +} + +/* + * Returns a list of components in shutdown sequence order. + */ +struct component ** +component_shutdown_list (void) +{ + struct component **a; + size_t i; + + a = grecs_calloc (comp_count, sizeof (a[0])); + memcpy (a, comp_array, comp_count * sizeof (a[0])); + qsort (a, comp_count, sizeof (a[0]), shutdown_seqno_comp); + return a; +} + +/* + * Prints on stdout the list of components in shutdown sequence + * order. + */ +void +components_list_shutdown_sequence (void) +{ + struct component **a = component_shutdown_list (); + size_t i; + + for (i = 0; i < comp_count; i++) + { + printf ("%lu: %s\n", a[i]->shutdown_seqno, a[i]->tag); + } + free (a); +} + +/* + * Computes array if shutdown sequence numbers and stores it in RET. + * Returns number of elements in the computed array. + */ +size_t +components_shutdown_sequence_numbers (unsigned long **ret) +{ + struct component **a = component_shutdown_list (); + unsigned long *idx = grecs_calloc (comp_count, sizeof (idx[0])); + size_t i; + size_t j; + + for (i = j = 0; i < comp_count; i++) + { + unsigned long seqno = idx[i] = a[j]->shutdown_seqno; + while (a[j]->shutdown_seqno == seqno) + { + if (++j == comp_count) + goto end; + } + } + end: + *ret = idx; + return i + 1; } static int @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2007-2020 Sergey Poznyakoff + Copyright (C) 2007-2023 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 @@ -358,7 +358,13 @@ input_append (struct input *inp, char c) logmsg (LOG_ERR, _("protocol error")); return 400; } - inp->input_state = is_content; + if (inp->input_content_length == 0) + { + inp->input_state = is_end; + return 200; + } + else + inp->input_state = is_content; } else { @@ -1923,7 +1929,7 @@ fun_stop (struct json_value *result, struct prog *prog) if (!prog->active) { json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "already stopped"); + json_object_set_string (result, "message", "already stopped"); } else { @@ -1940,7 +1946,7 @@ fun_start (struct json_value *result, struct prog *prog) if (!IS_COMPONENT (prog)) { json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "not a component"); + json_object_set_string (result, "message", "not a component"); } else { @@ -1965,15 +1971,14 @@ fun_start (struct json_value *result, struct prog *prog) else { json_object_set_string (result, "status", "ER"); - /* FIXME: error message */ - json_object_set_string (result, "error_message", - "can't open socket"); + /* FIXME: detailed error message */ + json_object_set_string (result, "message", "can't open socket"); } break; default: json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "already running"); + json_object_set_string (result, "message", "already running"); return 0; } prog->active = 1; @@ -1987,12 +1992,12 @@ fun_restart (struct json_value *result, struct prog *prog) if (!IS_COMPONENT (prog)) { json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "not a component"); + json_object_set_string (result, "message", "not a component"); } else if (!prog->active) { json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "not active"); + json_object_set_string (result, "message", "not active"); } else { @@ -2005,12 +2010,12 @@ fun_restart (struct json_value *result, struct prog *prog) case status_listener: json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "not applicable"); + json_object_set_string (result, "message", "not applicable"); break; default: json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "not running"); + json_object_set_string (result, "message", "not running"); } } return 0; @@ -2208,7 +2213,7 @@ res_runlevel (struct ctlio *io, enum http_method meth, else { json_object_set_string (io->output.reply, "status", "ER"); - json_object_set_string (io->output.reply, "error_message", + json_object_set_string (io->output.reply, "message", "invalid runlevel value"); } } @@ -2221,13 +2226,13 @@ res_runlevel (struct ctlio *io, enum http_method meth, * ["RUNLEVEL=3", "CONSOLE=/dev/tty", ...] * GET /environ/NAME - Get value of variable NAME * { "status":"OK", "value":"..." } - * { "status":"ER", "error_message":"..." } + * { "status":"ER", "message":"..." } * DELETE /environ/NAME - Unset variable * { "status":"OK" } - * { "status":"ER", "error_message":"..." } + * { "status":"ER", "message":"..." } * PUT /environ/NAME=VALUE - Set variable * { "status":"OK" } - * { "status":"ER", "error_message":"..." } + * { "status":"ER", "message":"..." } */ static void env_reply (struct ctlio *io, int ok, int rc) @@ -2379,7 +2384,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json) if (val->type != json_string) { json_object_set_string (io->output.reply, "status", "ER"); - json_object_set_string (io->output.reply, "error_message", + json_object_set_string (io->output.reply, "message", "malformed request"); return; } @@ -2403,7 +2408,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json) if (fails == n) { json_object_set_string (io->output.reply, "status", "ER"); - json_object_set_string (io->output.reply, "error_message", + json_object_set_string (io->output.reply, "message", "no matching files found"); json_value_free (reply); } @@ -2412,7 +2417,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json) json_object_set_string (io->output.reply, "status", "OK"); if (fails) { - json_object_set_string (io->output.reply, "error_message", + json_object_set_string (io->output.reply, "message", "some files not removed"); json_object_set (io->output.reply, "result", reply); } @@ -2478,7 +2483,7 @@ conf_reload (struct ctlio *io) if (pies_reread_config ()) { json_object_set_string (io->output.reply, "status", "ER"); - json_object_set_string (io->output.reply, "error_message", + json_object_set_string (io->output.reply, "message", "configuration syntax error"); } else diff --git a/src/depmap.c b/src/depmap.c index ae5b432..a74a7f0 100644 --- a/src/depmap.c +++ b/src/depmap.c @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2008-2020 Sergey Poznyakoff + Copyright (C) 2008-2023 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 @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2009-2020 Sergey Poznyakoff + Copyright (C) 2009-2023 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 diff --git a/src/inetd-bi.c b/src/inetd-bi.c index 1925157..6cb5478 100644 --- a/src/inetd-bi.c +++ b/src/inetd-bi.c @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2009-2020 Sergey Poznyakoff + Copyright (C) 2009-2023 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 diff --git a/src/inetd.c b/src/inetd.c index b7ae0eb..e65775f 100644 --- a/src/inetd.c +++ b/src/inetd.c @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2009-2020 Sergey Poznyakoff + Copyright (C) 2009-2023 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 @@ -29,10 +29,10 @@ #define IFLD_MIN_COUNT 6 /* Minimum number of fields in entry */ /* FIXME: Copied from grecs/src/tree.c */ -static void -listel_dispose(void *el) +void +listel_dispose (void *el) { - free(el); + free (el); } #define TCPMUX_PREFIX_STR "tcpmux/" diff --git a/src/inetd.in b/src/inetd.in index f2be09d..993aa88 100644 --- a/src/inetd.in +++ b/src/inetd.in @@ -1,6 +1,6 @@ #! /bin/sh # This file is part of GNU Pies. -# Copyright (C) 2008-2020 Sergey Poznyakoff +# Copyright (C) 2008-2023 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 diff --git a/src/limits.c b/src/limits.c index c4796e7..3fd8a4d 100644 --- a/src/limits.c +++ b/src/limits.c @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2008-2020 Sergey Poznyakoff + Copyright (C) 2008-2023 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 diff --git a/src/meta1parse.c b/src/meta1parse.c index 8fe0936..f4cebd7 100644 --- a/src/meta1parse.c +++ b/src/meta1parse.c @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2016-2020 Sergey Poznyakoff + Copyright (C) 2016-2023 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 @@ -345,9 +345,6 @@ meta1_config_parse (const char *name) setflag (&traceflags, "META1_DEBUG_LEX", GRECS_TRACE_LEX); grecs_error_count = 0; - grecs_current_locus_point.file = grecs_install_text (name); - grecs_current_locus_point.line = 1; - grecs_current_locus_point.col = 0; subtree = grecs_meta1_parser (name, traceflags); if (!subtree) @@ -1,5 +1,5 @@ /* This file is part of GNU Pies. - Copyright (C) 2008-2020 Sergey Poznyakoff + Copyright (C) 2008-2023 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 @@ -36,7 +36,8 @@ enum pies_command COM_STOP, COM_DUMP_DEPMAP, COM_TRACE_PREREQ, - COM_TRACE_DEPEND + COM_TRACE_DEPEND, + COM_LIST_SHUTDOWN_SEQUENCE }; enum pies_command command; @@ -323,15 +324,15 @@ static struct tokendef sig_tokendef[] = { void action_free (struct action *act) { - if (!act) - return; - if (act->nstat > 0) - free (act->status); - free (act->addr); - free (act->message); - free (act->command); + if (act) + { + grecs_list_free (act->cond_list); + free (act->addr); + free (act->message); + free (act->command); - free (act); + free (act); + } } static void @@ -340,6 +341,35 @@ free_entry_action (void *act) action_free (act); } +int +strtosignum (char const *arg) +{ + size_t len; + int n; + + if (arg == NULL) + return 0; + + len = strlen (arg); + if (len > 3 && memcmp (arg, "SIG", 3) == 0) + { + if (arg[4] == '+') + { + char *p; + unsigned long un; + + errno = 0; + un = strtoul (arg + 4, &p, 0); + if (un == 0 || *p || errno || un > INT_MAX) + return 0; + n = un; + } + else if (strtotok_ci (sig_tokendef, arg, &n)) + return 0; + } + return n; +} + static struct action * create_action (struct component *comp, grecs_locus_t *locus, @@ -347,22 +377,38 @@ create_action (struct component *comp, const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *)) { int i; - unsigned *retv; - int retc = 0; - int allflag = 0; + struct grecs_list *cond_list; struct action *act; - retv = grecs_calloc (argc, sizeof *retv); if (argc == 0 || (argc == 1 && strcmp (getarg (val, 0, locus), "*") == 0)) - allflag = 1; + cond_list = NULL; else { + cond_list = grecs_list_create (); + cond_list->free_entry = listel_dispose; + for (i = 0; i < argc; i++) { - unsigned n; + struct status_cond *sc; + int n; + int neg = 0; const char *arg = getarg (val, i, locus); size_t len = strlen (arg); + if (*arg == '!') + { + neg = 1; + arg++; + if (*arg == 0) + { + i++; + if (i == argc) + break; + arg = getarg (val, i, locus); + len = strlen (arg); + } + } + if (isdigit (arg[0])) { char *p; @@ -375,22 +421,14 @@ create_action (struct component *comp, } else if (len > 3 && memcmp (arg, "SIG", 3) == 0) { - if (arg[4] == '+') + int signo; + if ((signo = strtosignum (arg)) == 0) { - char *p; - n = strtoul (arg + 4, &p, 0); - if (*p) - { - grecs_error (locus, 0, _("%s: not a number"), p); - continue; - } - } - else if (strtotok_ci (sig_tokendef, arg, (int*) &n)) - { - grecs_error (locus, 0, _("%s: not a signal code"), arg); + grecs_error (locus, 0, _("%s: bad signal specification"), + arg); continue; } - n |= STATUS_SIG_BIT; + n = STATUS_SIG_BIT | signo; } else if (strtotok_ci (ex_tokendef, arg, (int *) &n)) { @@ -398,23 +436,16 @@ create_action (struct component *comp, continue; } - /* Alles in ordnung */ - retv[retc++] = n; - } - } + sc = grecs_malloc (sizeof (sc[0])); + sc->status = n; + sc->neg = neg; - if (retc == 0 && !allflag) - { - free (retv); - return NULL; + grecs_list_append (cond_list, sc); + } } act = grecs_zalloc (sizeof *act); - if (!allflag) - { - act->nstat = retc; - act->status = retv; - } + act->cond_list = cond_list; if (!comp->act_list) { comp->act_list = grecs_list_create (); @@ -626,6 +657,7 @@ parse_legacy_env (char **argv, envop_t **envop) else { msize = len + vlen + 6; + mem = grecs_malloc (msize); snprintf (mem, msize, "${%s:-}%s", name, value); } value = mem; @@ -648,6 +680,7 @@ parse_legacy_env (char **argv, envop_t **envop) else { msize = len + vlen + 6; + mem = grecs_malloc (msize); snprintf (mem, msize, "%s${%s:-}", value, name); } value = mem; @@ -1244,6 +1277,27 @@ _cb_flags (enum grecs_callback_command cmd, return 0; } +static int +_cb_signal (enum grecs_callback_command cmd, + grecs_node_t *node, + void *varptr, void *cb_data) +{ + grecs_locus_t *locus = &node->locus; + grecs_value_t *value = node->v.value; + int n; + + if (grecs_assert_node_value_type (cmd, node, GRECS_TYPE_STRING)) + return 1; + if ((n = strtosignum (value->v.string)) == 0) + { + grecs_error (locus, 0, _("%s: bad signal specification"), + value->v.string); + return 1; + } + *(int*)varptr = n; + return 0; +} + struct grecs_keyword component_keywords[] = { {"mode", N_("mode"), @@ -1283,6 +1337,11 @@ struct grecs_keyword component_keywords[] = { N_("List of flags."), grecs_type_string, GRECS_LIST, NULL, offsetof (struct component, flags), _cb_flags }, + {"sigterm", + N_("SIGNAL"), + N_("Termination signal."), + grecs_type_string, GRECS_DFLT, NULL, offsetof (struct component, sigterm), + _cb_signal }, #if PIES_SYSVINIT_ENABLED {"runlevels", N_("chars"), @@ -1582,6 +1641,9 @@ static struct grecs_keyword syslog_kw[] = { {"tag", N_("string"), N_("Tag syslog messages with this string"), grecs_type_string, GRECS_DFLT, &pies_log_tag}, + {"fallback-file", N_("filename"), N_("Name of the fallback log file"), + grecs_type_string, GRECS_DFLT, + &pies_fallback_file}, #if 0 /* This is reserved for future use */ { @@ -1794,8 +1856,8 @@ struct grecs_keyword pies_keywords[] = { void config_init (void) { - grecs_include_path_setup (DEFAULT_VERSION_INCLUDE_DIR, - DEFAULT_INCLUDE_DIR, NULL); + grecs_preprocessor = DEFAULT_PREPROCESSOR; + grecs_log_to_stderr = log_to_stderr_only; pies_identity_mechanism_register (&system_identity_mechanism); #ifdef WITH_PAM @@ -1894,7 +1956,15 @@ pies_schedule_children (int op) children_op |= op; } -RETSIGTYPE +static int +children_op_toggle (int op) +{ + int result = children_op & op; + children_op &= ~op; + return result; +} + +void sig_handler (int sig) { if (SYSVINIT_ACTIVE && sysvinit_sigtrans (sig, &action)) @@ -1928,7 +1998,7 @@ sig_handler (int sig) } } -RETSIGTYPE +void sigchld_early (int sig) { while (waitpid (-1, NULL, WNOHANG) != -1) @@ -1936,7 +2006,7 @@ sigchld_early (int sig) } void -setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc) +setsigvhan (void (*handler) (int signo), int *sigv, int sigc) { int i; struct sigaction act; @@ -1980,7 +2050,7 @@ add_extra_sigv (int *sigv, int sigc) } void -signal_setup (RETSIGTYPE (*sf) (int)) +signal_setup (void (*sf) (int)) { setsigvhan (sf, default_sigv, ARRAY_SIZE (default_sigv)); if (extra_sigc) @@ -2045,7 +2115,7 @@ pies_check_status (pid_t *ppid) { pid_t pid = pidfile_read (0); - if (pid <= 0) + if (pid <= 0 || pid == getpid ()) return pies_status_ctr; *ppid = pid; @@ -2306,21 +2376,49 @@ set_state_file_names (const char *base) qotdfile = mkfilename (statedir, base, ".qotd"); } -/* Return 1 if pies is run from docker and 0 otherwise. */ static int is_docker (void) { FILE *fp; - char *id = NULL; - int res; - + + // 0 1 + // 0123456789012345678 + static char alphabet[] = "0123456789docker:/\n"; + static unsigned char transition[][20] = { + // 0 1 2 3 4 5 6 7 8 9 d o c k e r : / \n + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10,10,10,10,10, 1,10, 0, 10 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0, 1 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 3, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10, 4,10,10,10,10,10,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10, 5,10,10,10,10,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10, 6,10,10,10,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10, 7,10,10,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10,10, 8,10,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9,10,10, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11, 0, 10 }, + { 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 0, 10 }, + }; + enum { state_init = 0, state_success = 11, state_eof = 12 }; + int state = state_init; + fp = fopen ("/proc/self/cgroup", "r"); if (!fp) return 0; - res = fscanf (fp, "%*d:%*[^:]:/docker/%ms\n", &id) == 1; + + while (state != state_success && state != state_eof) + { + int c = fgetc (fp); + if (c == EOF) + state = state_eof; + else + { + char *p = strchr (alphabet, c); + int a = p ? p - alphabet : sizeof (alphabet) - 1; + state = transition[state] |