aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am12
-rw-r--r--src/acl.c2
-rw-r--r--src/acl.h2
-rw-r--r--src/cmdline.opt52
-rw-r--r--src/comp.c110
-rw-r--r--src/ctl.c45
-rw-r--r--src/depmap.c2
-rw-r--r--src/diag.c2
-rw-r--r--src/inetd-bi.c2
-rw-r--r--src/inetd.c8
-rw-r--r--src/inetd.in2
-rw-r--r--src/limits.c2
-rw-r--r--src/meta1parse.c5
-rw-r--r--src/pies.c247
-rw-r--r--src/pies.h28
-rw-r--r--src/pies_syslog.h2
-rw-r--r--src/piesctl-cl.opt33
-rw-r--r--src/piesctl.c81
-rw-r--r--src/pp-setup106
-rw-r--r--src/prog.h8
-rw-r--r--src/progman.c248
-rw-r--r--src/socket.c2
-rw-r--r--src/sysdep.c2
-rw-r--r--src/syslog.c81
-rw-r--r--src/sysvinit.c2
-rw-r--r--src/telinit.opt2
-rw-r--r--src/userprivs.c2
-rw-r--r--src/utmp.c2
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@
diff --git a/src/acl.c b/src/acl.c
index 582aa50..f01929e 100644
--- a/src/acl.c
+++ b/src/acl.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/acl.h b/src/acl.h
index 93614c6..83922bc 100644
--- a/src/acl.h
+++ b/src/acl.h
@@ -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;
diff --git a/src/comp.c b/src/comp.c
index 4d6c9f7..d823739 100644
--- a/src/comp.c
+++ b/src/comp.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
@@ -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
diff --git a/src/ctl.c b/src/ctl.c
index 21b0642..cc16912 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -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
diff --git a/src/diag.c b/src/diag.c
index ed5e5e3..f746379 100644
--- a/src/diag.c
+++ b/src/diag.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-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)
diff --git a/src/pies.c b/src/pies.c
index b6b0193..2aef512 100644
--- a/src/pies.c
+++ b/src/pies.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
@@ -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]