summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-05-24 09:45:25 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-05-24 10:50:39 (GMT)
commit6dd0ec08db301984b8f8f9082f28006d5915c183 (patch) (side-by-side diff)
treee916ad37fbd3cbcaf85103667f28e0d47f3c2e45
parent2a646ee7cbbcb6f4bbd8f38bb3c1e1418550f3fc (diff)
downloadpies-6dd0ec08db301984b8f8f9082f28006d5915c183.tar.gz
pies-6dd0ec08db301984b8f8f9082f28006d5915c183.tar.bz2
Initial implementation of "startup" components.
These are components that are run at program startup. Starting other components is delayed until all startup components terminate. This is similar to SysV "bootwait" components. Upon termination, startup components are removed from the configuration. They are not renewed upon configuratuion reload. * src/comp.c (comp_array_remove): Remove from the depmap as well. (component_ref_decr): Use comp_array_remove for active components and plain component_free for inactive ones. (component_build_depmap): Use comp_array_remove. (component_config_commit): Special handling for pies_comp_startup components. * src/pies.c (modetab): New component modes: "startup" and "shutdown". (main): Run program_init_startup. * src/pies.h (pies_comp_mode): New modes: pies_comp_startup and pies_comp_shutdown. (program_init_startup): New proto. * src/progman.c (progman_waiting_p): Return 1 if a startup component is still running. (program_init_startup): New function. (progman_cleanup): Handle pies_comp_startup termination. * src/socket.c (switch_eids): Avoid unnecessary calls to setegid and seteuid. * tests/atlocal.in (auxdir): New variable. * tests/mailer: Move to tests/aux/ * tests/respawn: Move to tests/aux/ * tests/retcode: Move to tests/aux/ * tests/aux/startup: New auxiliary program. * tests/redirect.at: Start components from $auxdir. * tests/respawn.at: Likewise. * tests/ret-exec.at: Likewise. * tests/ret-notify.at: Likewise. * tests/startup.at: New file. * tests/testsuite.at: Include startup.at * tests/Makefile.am: Add new tests.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/comp.c87
-rw-r--r--src/pies.c115
-rw-r--r--src/pies.h38
-rw-r--r--src/progman.c291
-rw-r--r--src/socket.c54
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/atlocal.in2
-rwxr-xr-xtests/aux/mailer (renamed from tests/mailer)0
-rwxr-xr-xtests/aux/respawn (renamed from tests/respawn)0
-rwxr-xr-xtests/aux/retcode (renamed from tests/retcode)0
-rwxr-xr-xtests/aux/startup7
-rw-r--r--tests/redirect.at2
-rw-r--r--tests/respawn.at2
-rw-r--r--tests/ret-exec.at4
-rw-r--r--tests/ret-notify.at6
-rw-r--r--tests/startup.at84
-rw-r--r--tests/testsuite.at1
17 files changed, 442 insertions, 260 deletions
diff --git a/src/comp.c b/src/comp.c
index c3e998a..2346306 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -26,2 +26,7 @@ struct complist
+/* 0 on the first load, and 1 on all subsequent reloads. Tells the
+ component_config_commit whether we're starting from scratch or just
+ updating an already loaded configuration */
+static int loaded;
+
static struct complist comp_list[2];
@@ -34,3 +39,3 @@ static pies_depmap_t depmap;
-static int
+static inline int
next_index (void)
@@ -40,3 +45,3 @@ next_index (void)
-static int
+static inline int
prev_index (void)
@@ -87,2 +92,18 @@ component_append (struct component *comp)
void
+comp_array_remove (size_t i)
+{
+ struct component *comp = comp_array[i];
+
+ depmap_remove (depmap, i);
+ while (i < comp_count -1)
+ {
+ comp_array[i] = comp_array[i+1];
+ comp_array[i]->arridx = i;
+ i++;
+ }
+ component_free (comp);
+ comp_count--;
+}
+
+void
component_unlink (struct component *comp)
@@ -203,3 +224,8 @@ component_ref_decr (struct component *comp)
if (--comp->ref_count == 0)
- component_free (comp);
+ {
+ if (component_is_active (comp))
+ comp_array_remove (comp->arridx);
+ else
+ component_free (comp);
+ }
}
@@ -427,13 +453,2 @@ report_cyclic_dependency (pies_depmap_t dp, size_t idx)
void
-comp_array_remove (size_t i)
-{
- struct component *comp = comp_array[i];
- if (i < comp_count - 1)
- memmove (&comp_array[i], &comp_array[i+1],
- (comp_count - i - 1) * sizeof comp_array[0]);
- component_free (comp);
- comp_count--;
-}
-
-void
component_build_depmap (void)
@@ -462,3 +477,2 @@ component_build_depmap (void)
comp_array_remove (i);
- depmap_remove (depmap, i);
continue;
@@ -499,6 +513,3 @@ component_build_depmap (void)
if (comp_array[i]->flags & CF_REMOVE)
- {
- comp_array_remove (i);
- depmap_remove (depmap, i);
- }
+ comp_array_remove (i);
else
@@ -530,18 +541,32 @@ component_config_commit (void)
- /* Rearrange components, registering prog entries for the new ones */
- for (comp = list->head, i = 0; comp; comp = comp->next, i++)
+ /* Rearrange components, registering entries for the new ones */
+ for (comp = list->head, i = 0; comp; )
{
- match = complist_find_match (prev, comp);
- if (match)
+ struct component *next = comp->next;
+ if (loaded && comp->mode == pies_comp_startup)
{
- component_merge (match, comp);
- component_unlink (match);
- match->listidx = cur;
- component_link (match, comp->prev);
+ /* Ignore startup components */
+ component_unlink (comp);
component_free (comp);
- comp = match;
}
- comp_array[i] = comp;
- comp->arridx = i;
+ else
+ {
+ match = complist_find_match (prev, comp);
+ if (match)
+ {
+ component_merge (match, comp);
+ component_unlink (match);
+ match->listidx = cur;
+ component_link (match, comp->prev);
+ component_free (comp);
+ comp = match;
+ }
+ comp_array[i] = comp;
+ comp->arridx = i;
+ i++;
+ }
+ comp = next;
}
+ /* Adjust comp_count */
+ comp_count = i;
@@ -562,2 +587,4 @@ component_config_commit (void)
register_prog (comp);
+
+ loaded = 1;
}
diff --git a/src/pies.c b/src/pies.c
index 89c0b7e..98488a6 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -134,3 +134,3 @@ config_file_remove (const char *name)
struct grecs_list_entry *ep;
-
+
for (ep = config_list->head; ep; ep = ep->next)
@@ -158,3 +158,3 @@ config_file_list_serialize (struct json_value *ar)
struct grecs_list_entry *ep;
-
+
for (ep = config_list->head; ep; ep = ep->next)
@@ -329,3 +329,3 @@ action_free (struct action *act)
free (act->command);
-
+
free (act);
@@ -361,3 +361,3 @@ create_action (struct component *comp,
size_t len = strlen (arg);
-
+
if (isdigit (arg[0]))
@@ -396,3 +396,3 @@ create_action (struct component *comp,
}
-
+
/* Alles in ordnung */
@@ -401,3 +401,3 @@ create_action (struct component *comp,
}
-
+
if (retc == 0 && !allflag)
@@ -474,3 +474,3 @@ return_code_section_parser (enum grecs_callback_command cmd,
}
-
+
switch (value->type)
@@ -480,3 +480,3 @@ return_code_section_parser (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_ARRAY:
@@ -485,3 +485,3 @@ return_code_section_parser (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_LIST:
@@ -494,3 +494,3 @@ return_code_section_parser (enum grecs_callback_command cmd,
break;
-
+
case grecs_callback_section_end:
@@ -544,3 +544,3 @@ _cb_command (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_ARRAY:
@@ -704,3 +704,3 @@ _cb_redir (enum grecs_callback_command cmd,
int res;
-
+
switch (value->type)
@@ -721,3 +721,3 @@ _cb_redir (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_ARRAY:
@@ -741,3 +741,3 @@ _cb_redir (enum grecs_callback_command cmd,
return 0;
-
+
switch (res)
@@ -746,3 +746,3 @@ _cb_redir (enum grecs_callback_command cmd,
break;
-
+
case redir_syslog:
@@ -757,3 +757,3 @@ _cb_redir (enum grecs_callback_command cmd,
break;
-
+
case redir_file:
@@ -766,3 +766,3 @@ _cb_redir (enum grecs_callback_command cmd,
break;
-
+
default:
@@ -770,3 +770,3 @@ _cb_redir (enum grecs_callback_command cmd,
}
-
+
return 0;
@@ -775,4 +775,4 @@ _cb_redir (enum grecs_callback_command cmd,
static struct tokendef socktype_xtab[] = {
- { "stream", SOCK_STREAM },
- { "dgram", SOCK_DGRAM },
+ { "stream", SOCK_STREAM },
+ { "dgram", SOCK_DGRAM },
{ "seqpacket", SOCK_SEQPACKET },
@@ -822,2 +822,4 @@ static struct tokendef modetab[] = {
{"pass", pies_comp_pass_fd},
+ {"startup", pies_comp_startup},
+ {"shutdown", pies_comp_shutdown},
{"boot", pies_comp_boot},
@@ -827,3 +829,3 @@ static struct tokendef modetab[] = {
{"powerokwait", pies_comp_powerokwait},
- {"ctrlaltdel", pies_comp_ctrlaltdel},
+ {"ctrlaltdel", pies_comp_ctrlaltdel},
{"ondemand", pies_comp_ondemand},
@@ -922,3 +924,3 @@ _cb_flags (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_LIST:
@@ -926,3 +928,3 @@ _cb_flags (enum grecs_callback_command cmd,
struct grecs_list_entry *ep;
-
+
for (ep = value->v.list->head; ep; ep = ep->next)
@@ -941,3 +943,3 @@ _cb_flags (enum grecs_callback_command cmd,
break;
-
+
case GRECS_TYPE_ARRAY:
@@ -1230,3 +1232,3 @@ find_component_keyword (const char *ident)
struct grecs_keyword *kwp;
-
+
for (kwp = component_keywords; kwp->ident; kwp++)
@@ -1258,3 +1260,3 @@ component_section_parser (enum grecs_callback_command cmd,
break;
-
+
case grecs_callback_set_value:
@@ -1536,3 +1538,3 @@ pies_config_parse (char const *name)
return 1;
-
+
for (node = tree; node; node = node->next)
@@ -1552,3 +1554,3 @@ pies_config_parse (char const *name)
return 1;
-
+
return 0;
@@ -1575,3 +1577,3 @@ pies_read_config (void)
component_config_begin ();
-
+
for (ep = config_list->head; ep; ep = ep->next)
@@ -1585,6 +1587,6 @@ pies_read_config (void)
err = 0;
-
+
if (err)
component_config_rollback ();
-
+
return err;
@@ -1658,3 +1660,3 @@ setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc)
struct sigaction act;
-
+
act.sa_flags = 0;
@@ -1781,3 +1783,3 @@ request_restart_components (size_t cc, char **cv)
size_t i, j;
-
+
argv = grecs_calloc (5 + 3 * cc - 1, sizeof (*argv));
@@ -1805,3 +1807,3 @@ list_components (void)
char *argv[5];
-
+
argv[0] = "piesctl";
@@ -1944,3 +1946,3 @@ set_mailer_argcv (void)
struct wordsplit ws;
-
+
if (wordsplit (mailer_command_line, &ws, WRDSF_DEFFLAGS))
@@ -2035,3 +2037,3 @@ main (int argc, char **argv)
int i;
-
+
set_program_name (argv[0]);
@@ -2045,6 +2047,6 @@ main (int argc, char **argv)
grecs_print_diag_fun = pies_diag_printer;
-
+
pies_master_argc = argc;
pies_master_argv = argv;
-
+
set_quoting_style (NULL, shell_quoting_style);
@@ -2060,3 +2062,3 @@ main (int argc, char **argv)
}
-
+
/* Set default logging */
@@ -2069,5 +2071,5 @@ main (int argc, char **argv)
diag_flags = DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR);
-
+
diag_setup (diag_flags);
-
+
config_init ();
@@ -2075,3 +2077,3 @@ main (int argc, char **argv)
parse_options (&argc, &argv);
-
+
if (argc && !(command == COM_RESTART_COMPONENT
@@ -2083,3 +2085,3 @@ main (int argc, char **argv)
}
-
+
if (!instance)
@@ -2121,3 +2123,3 @@ main (int argc, char **argv)
set_mailer_argcv ();
-
+
if (lint_mode)
@@ -2127,3 +2129,3 @@ main (int argc, char **argv)
diag_setup (log_to_stderr_only ? DIAG_TO_STDERR : 0);
-
+
if (!control.url)
@@ -2139,3 +2141,3 @@ main (int argc, char **argv)
}
-
+
switch (command)
@@ -2147,3 +2149,3 @@ main (int argc, char **argv)
exit (request_restart_components (argc, argv));
-
+
case COM_RELOAD:
@@ -2164,7 +2166,7 @@ main (int argc, char **argv)
exit (0);
-
- case COM_TRACE_PREREQ:
+
+ case COM_TRACE_PREREQ:
components_trace (argv, depmap_col);
exit (0);
-
+
default:
@@ -2195,3 +2197,3 @@ main (int argc, char **argv)
break;
-
+
case pies_status_running:
@@ -2201,3 +2203,3 @@ main (int argc, char **argv)
}
-
+
if (!foreground)
@@ -2214,3 +2216,3 @@ main (int argc, char **argv)
logmsg (LOG_INFO, _("%s %s starting"), proginfo.package, proginfo.version);
-
+
if (!init_process)
@@ -2221,3 +2223,3 @@ main (int argc, char **argv)
}
-
+
if (pies_master_argv[0][0] != '/')
@@ -2230,2 +2232,3 @@ main (int argc, char **argv)
progman_create_sockets ();
+ program_init_startup ();
progman_start ();
@@ -2263,3 +2266,3 @@ main (int argc, char **argv)
break;
-
+
case ACTION_STOP:
@@ -2278,3 +2281,3 @@ main (int argc, char **argv)
break;
-
+
case ACTION_KBREQUEST:
diff --git a/src/pies.h b/src/pies.h
index a7f6567..bdc406b 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -106,3 +106,3 @@ struct action
char *message; /* Notification mail. */
- char *command; /* Execute this command */
+ char *command; /* Execute this command */
};
@@ -139,3 +139,10 @@ enum pies_comp_mode
pies_comp_pass_fd,
-
+
+ /* Components of this type runs once on program startup. Running other
+ components is delayed until the last startup component finishes. */
+ pies_comp_startup,
+
+ /* FIXME: Runs before program termination */
+ pies_comp_shutdown,
+
/*
@@ -146,3 +153,3 @@ enum pies_comp_mode
for its termination */
- pies_comp_wait = pies_mark_sysvinit,
+ pies_comp_wait = pies_mark_sysvinit,
/* Execute the component once, when the specified runlevel is entered */
@@ -164,3 +171,3 @@ enum pies_comp_mode
pressed the Ctrl+Alt+Del combination. */
- pies_comp_ctrlaltdel,
+ pies_comp_ctrlaltdel,
/* Execute the component when a specified ondemand runlevel is called */
@@ -186,12 +193,12 @@ enum pies_comp_mode
#define CF_PRECIOUS 0x002 /* The component is precious (should not
- be disabled) */
+ be disabled) */
#define CF_WAIT 0x004 /* Wait for the component instance to
- terminate. */
+ terminate. */
#define CF_TCPMUX 0x008 /* A plain TCPMUX service */
#define CF_TCPMUXPLUS 0x010 /* A TCPMUX-plus service, i.e. pies
- must emit a '+' response before starting
- it */
+ must emit a '+' response before starting
+ it */
#define CF_INTERNAL 0x020 /* An internal inetd service */
#define CF_SOCKENV 0x040 /* Component wants socket information in
- the environment */
+ the environment */
#define CF_RESOLVE 0x080 /* Resolve IP addresses */
@@ -212,5 +219,5 @@ struct component
size_t arridx; /* Index of this component. */
- size_t ref_count; /* Reference count. */
+ size_t ref_count; /* Reference count. */
struct prog *prog; /* Prog associated with this component. */
-
+
enum pies_comp_mode mode;
@@ -234,3 +241,3 @@ struct component
char *runlevels;
-
+
/* For inetd components */
@@ -255,5 +262,5 @@ struct component
char *max_ip_connections_message;
-
+
/* Redirectors: */
- int facility; /* Syslog facility. */
+ int facility; /* Syslog facility. */
struct redirector redir[2]; /* Repeaters for stdout and stderr */
@@ -336,2 +343,3 @@ int pies_reread_config (void);
void register_prog (struct component *comp);
+void program_init_startup (void);
int progman_waiting_p (void);
@@ -596,3 +604,3 @@ struct sysvinit_request
#define SYSV_ACCT_PROC_START 2
-#define SYSV_ACCT_PROC_STOP 3
+#define SYSV_ACCT_PROC_STOP 3
diff --git a/src/progman.c b/src/progman.c
index 1b09cd5..5bc4eb3 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -67,3 +67,3 @@ progman_lookup_component (const char *tag)
return NULL;
-}
+}
@@ -124,3 +124,3 @@ link_prog (struct prog *prog, struct prog *ref)
prog->next = ref->next;
-
+
if ((x = ref->next))
@@ -153,3 +153,3 @@ destroy_prog (struct prog **pp)
struct prog *p = *pp;
-
+
unlink_prog (p);
@@ -160,4 +160,4 @@ destroy_prog (struct prog **pp)
if (p->v.p.status == status_listener && p->v.p.socket != -1)
- deregister_socket (p->v.p.socket);
- /* FIXME: Remove also all dependent progs (esp. tcpmux) */
+ deregister_socket (p->v.p.socket);
+ /* FIXME: Remove also all dependent progs (esp. tcpmux) */
if (p->v.p.redir[RETR_OUT])
@@ -167,3 +167,3 @@ destroy_prog (struct prog **pp)
break;
-
+
case TYPE_REDIRECTOR:
@@ -184,3 +184,3 @@ destroy_prog (struct prog **pp)
break;
-
+
case TYPE_COMMAND:
@@ -258,3 +258,3 @@ find_prog_ref (struct component *comp)
}
-
+
if (comp->prog)
@@ -272,3 +272,3 @@ find_prog_ref (struct component *comp)
}
-
+
static struct prog *
@@ -277,3 +277,3 @@ register_prog0 (struct component *comp)
struct prog *newp;
-
+
newp = grecs_zalloc (sizeof (*newp));
@@ -293,3 +293,3 @@ register_prog0 (struct component *comp)
newp->active = 1;
-
+
if (comp->mode != pies_comp_exec)
@@ -319,2 +319,15 @@ register_command (char *tag, char *command, pid_t pid)
+static inline int
+progman_startup_phase (void)
+{
+ struct prog *prog;
+
+ for (prog = proghead; prog; prog = prog->next)
+ {
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ return 1;
+ }
+ return 0;
+}
+
int
@@ -323,6 +336,8 @@ progman_waiting_p (void)
struct prog *prog;
-
+
for (prog = proghead; prog; prog = prog->next)
{
- if (IS_COMPONENT (prog) && prog->wait && prog->pid > 0)
+ if (IS_COMPONENT (prog)
+ && prog->pid > 0
+ && (prog->wait || prog->v.p.comp->mode == pies_comp_startup))
{
@@ -408,3 +423,3 @@ open_redirector (struct prog *master, int stream)
return redirect_to_file (master, stream);
-
+
case redir_syslog:
@@ -412,3 +427,3 @@ open_redirector (struct prog *master, int stream)
}
-
+
if (pipe (p))
@@ -418,3 +433,3 @@ open_redirector (struct prog *master, int stream)
}
-
+
switch (pid = fork ())
@@ -430,6 +445,6 @@ open_redirector (struct prog *master, int stream)
close_fds (&fdset);
-
+
diag_setup (0);
signal_setup (redir_exit);
-
+
close (p[1]);
@@ -443,3 +458,3 @@ open_redirector (struct prog *master, int stream)
_exit (0);
-
+
case -1:
@@ -468,3 +483,3 @@ conn_class_hasher (void *data, unsigned long n_buckets)
size_t len;
-
+
while ((ch = *tag++))
@@ -532,3 +547,3 @@ conn_class_lookup (const char *tag,
}
-
+
probe->count = 0;
@@ -727,3 +742,3 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
size_t len;
-
+
if (a && b)
@@ -755,3 +770,3 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
}
-
+
static void
@@ -762,3 +777,3 @@ environ_setup (char **hint)
size_t count, i, j, n;
-
+
if (!hint)
@@ -771,3 +786,3 @@ environ_setup (char **hint)
}
-
+
/* Count new environment size */
@@ -777,3 +792,3 @@ environ_setup (char **hint)
count++;
-
+
for (i = 0; hint[i]; i++)
@@ -783,6 +798,6 @@ environ_setup (char **hint)
new_env = grecs_calloc (count + 1, sizeof new_env[0]);
-
+
/* Populate the environment. */
n = 0;
-
+
if (old_env)
@@ -797,3 +812,3 @@ environ_setup (char **hint)
char *p;
-
+
if (hint[i][0] == '-')
@@ -808,3 +823,3 @@ environ_setup (char **hint)
j = n;
-
+
if ((p = strchr (hint[i], '=')))
@@ -813,3 +828,3 @@ environ_setup (char **hint)
continue; /* Ignore erroneous entry */
- if (p[-1] == '+')
+ if (p[-1] == '+')
new_env[j] = env_concat (hint[i], p - hint[i] - 1,
@@ -837,3 +852,3 @@ environ_setup (char **hint)
free (environ);
-
+
environ = new_env;
@@ -854,3 +869,3 @@ prog_sockenv (struct prog *prog)
const char *proto = NULL;
-
+
if (!(prog->v.p.comp->flags & CF_SOCKENV))
@@ -861,3 +876,3 @@ prog_sockenv (struct prog *prog)
add_env (ENV_SOCKTYPE, proto);
-
+
if (prog->v.p.comp->socket_url)
@@ -870,3 +885,3 @@ prog_sockenv (struct prog *prog)
add_env (ENV_PROTO, proto);
-
+
if (getsockname (prog->v.p.socket,
@@ -922,3 +937,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
time_t now;
-
+
time (&now);
@@ -932,3 +947,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
}
-
+
if (prog->v.p.failcount > max_count)
@@ -940,3 +955,3 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
}
-
+
return 0;
@@ -963,3 +978,3 @@ check_connection_rate (struct prog *prog)
size_t max_rate = prog->v.p.comp->max_rate
- ? prog->v.p.comp->max_rate : default_max_rate;
+ ? prog->v.p.comp->max_rate : default_max_rate;
if (max_rate && check_rate (prog, 60, max_rate))
@@ -1011,3 +1026,3 @@ prog_start_prologue (struct prog *prog)
}
-
+
environ_setup (prog->v.p.comp->env ?
@@ -1022,3 +1037,3 @@ prog_start_prologue (struct prog *prog)
umask (prog->v.p.comp->umask);
-
+
set_limits (prog_tag (prog),
@@ -1026,3 +1041,3 @@ prog_start_prologue (struct prog *prog)
prog->v.p.comp->limits : pies_limits);
-
+
if (debug_level >= 1)
@@ -1031,3 +1046,3 @@ prog_start_prologue (struct prog *prog)
struct component *comp = prog->v.p.comp;
-
+
logmsg_printf (LOG_DEBUG, "executing");
@@ -1049,3 +1064,3 @@ prog_execute (struct prog *prog)
}
-
+
execvp (prog->v.p.comp->program ?
@@ -1079,3 +1094,3 @@ prog_start (struct prog *prog)
fd_set fdset;
-
+
if (prog->pid > 0 || !IS_COMPONENT (prog))
@@ -1125,3 +1140,3 @@ prog_start (struct prog *prog)
break;
-
+
case pies_comp_accept:
@@ -1141,5 +1156,5 @@ prog_start (struct prog *prog)
}
-
+
debug (1, (_("starting %s"), prog_tag (prog)));
-
+
if (prog->v.p.comp->rmfile)
@@ -1160,3 +1175,3 @@ prog_start (struct prog *prog)
redir[RETR_ERR] = open_redirector (prog, RETR_ERR);
-
+
switch (pid = fork ())
@@ -1169,12 +1184,12 @@ prog_start (struct prog *prog)
switch (prog->v.p.comp->mode)
- {
- case pies_comp_accept:
- case pies_comp_inetd:
+ {
+ 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);
+ dup2 (prog->v.p.socket, 0);
+ dup2 (prog->v.p.socket, 1);
+ close (prog->v.p.socket);
prog->v.p.socket = -1;
- break;
+ break;
@@ -1184,3 +1199,3 @@ prog_start (struct prog *prog)
int fd = console_open (O_RDWR|O_NOCTTY);
- if (fd < 0)
+ if (fd < 0)
{
@@ -1220,4 +1235,4 @@ prog_start (struct prog *prog)
}
- break;
- }
+ break;
+ }
@@ -1238,3 +1253,3 @@ prog_start (struct prog *prog)
}
-
+
/* Close unneeded descripitors */
@@ -1249,4 +1264,4 @@ prog_start (struct prog *prog)
prog_execute (prog);
-
-
+
+
case -1:
@@ -1293,3 +1308,3 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
int rc;
-
+
if (!acl)
@@ -1300,3 +1315,3 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
input.identity = identity;
-
+
rc = pies_acl_check (acl, &input, 1);
@@ -1317,3 +1332,3 @@ fd_report (int fd, const char *msg)
size_t len;
-
+
if (!msg)
@@ -1336,3 +1351,3 @@ fd_report (int fd, const char *msg)
}
-}
+}
@@ -1346,3 +1361,3 @@ _prog_accept (struct prog *p)
struct conn_class *pcclass;
-
+
fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen);
@@ -1353,3 +1368,3 @@ _prog_accept (struct prog *p)
}
-
+
if (debug_level >= 1)
@@ -1396,3 +1411,3 @@ _prog_accept (struct prog *p)
}
-
+
if (check_connection_rate (p))
@@ -1449,3 +1464,3 @@ _prog_wait (struct prog *p)
}
-
+
int
@@ -1458,3 +1473,3 @@ progman_accept (int socket, void *data)
return _prog_accept (p);
-
+
return _prog_wait (p);
@@ -1528,2 +1543,21 @@ progman_recompute_alarm (void)
void
+program_init_startup (void)
+{
+ struct prog *prog;
+
+ for (prog = proghead; prog; prog = prog->next)
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ {
+ debug (1, ("running startup components"));
+ break;
+ }
+
+ for (; prog; prog = prog->next)
+ if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
+ {
+ prog_start (prog);
+ }
+}
+
+void
progman_start (void)
@@ -1533,5 +1567,6 @@ progman_start (void)
if (progman_waiting_p ())
- /* Noting to do if there are processes left in the previous runlevel */
+ /* Noting to do if there are processes left in the previous runlevel
+ (in sysv-init mode) or startup components running. */
return;
-
+
debug (1, ("starting components"));
@@ -1567,4 +1602,4 @@ check_stopping (struct prog *prog, time_t now)
if (prog->pid == 0)
- logmsg (LOG_EMERG,
- _("INTERNAL ERROR: attempting to kill unexisting process %s"),
+ logmsg (LOG_EMERG,
+ _("INTERNAL ERROR: attempting to kill unexisting process %s"),
prog_tag (prog));
@@ -1627,3 +1662,3 @@ progman_wake_sleeping (int onalrm)
break;
-
+
case status_stopping:
@@ -1636,3 +1671,3 @@ progman_wake_sleeping (int onalrm)
break;
-
+
default:
@@ -1649,3 +1684,3 @@ prog_start_prerequisites (struct prog *prog)
int warned = 0;
-
+
if (!prog->active)
@@ -1657,3 +1692,3 @@ prog_start_prerequisites (struct prog *prog)
struct prog *p;
-
+
if (!comp->prog || comp->flags & CF_PRECIOUS)
@@ -1671,3 +1706,3 @@ prog_start_prerequisites (struct prog *prog)
}
-
+
p = comp->prog;
@@ -1677,6 +1712,6 @@ prog_start_prerequisites (struct prog *prog)
continue;
-
+
case status_stopped:
break;
-
+
case status_listener:
@@ -1702,3 +1737,3 @@ prog_start_prerequisites (struct prog *prog)
depmap_end (pos);
-
+
return ret;
@@ -1759,3 +1794,3 @@ prog_stop (struct prog *prog, int sig)
kill (prog->pid, sig);
-}
+}
@@ -1789,3 +1824,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
prio = LOG_ERR;
-
+
if (WIFEXITED (status))
@@ -1803,3 +1838,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
char const *coremsg = "";
-
+
if (expect_term && WTERMSIG (status) == SIGTERM)
@@ -1825,3 +1860,3 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
static void propagate_child_exit (pid_t) ATTRIBUTE_NORETURN;
-
+
static void
@@ -1857,3 +1892,3 @@ wordsplit_string (struct wordsplit const *ws)
size_t len = 0;
-
+
for (i = 0; i < count; i++)
@@ -1885,3 +1920,3 @@ send_msg (char *rcpts, const char *msg_text)
size_t size;
-
+
ws.ws_offs = mailer_argc;
@@ -1898,3 +1933,3 @@ send_msg (char *rcpts, const char *msg_text)
debug (1, (_("sending notification to %s"), rcpts));
-
+
/* Copy mailer arguments */
@@ -1913,3 +1948,3 @@ send_msg (char *rcpts, const char *msg_text)
size_t len;
-
+
while (*arg && c_isblank (*arg))
@@ -1936,6 +1971,6 @@ send_msg (char *rcpts, const char *msg_text)
ws.ws_wordv[k] = NULL;
-
+
/* Fork a child: */
child_pid = fork ();
-
+
if (child_pid < 0)
@@ -1957,3 +1992,3 @@ send_msg (char *rcpts, const char *msg_text)
}
-
+
/* Child process */
@@ -1969,3 +2004,3 @@ send_msg (char *rcpts, const char *msg_text)
}
-
+
grand_child_pid = fork ();
@@ -2032,3 +2067,3 @@ notify_get_tag (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
+ return WRDSE_OK;
}
@@ -2041,3 +2076,3 @@ notify_get_termination (char **ret, void *data)
char *s;
-
+
if (WIFEXITED (clos->status))
@@ -2055,5 +2090,5 @@ notify_get_termination (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
+ return WRDSE_OK;
}
-
+
static int
@@ -2064,3 +2099,3 @@ notify_get_retcode (char **ret, void *data)
size_t l = 0;
-
+
if (WIFEXITED (clos->status))
@@ -2074,5 +2109,5 @@ notify_get_retcode (char **ret, void *data)
*ret = s;
- return WRDSE_OK;
-}
-
+ return WRDSE_OK;
+}
+
struct notify_variable
@@ -2092,3 +2127,3 @@ static struct notify_variable notify_vartab[] = {
};
-
+
static int
@@ -2102,3 +2137,3 @@ notify_getvar (char **ret, const char *vptr, size_t vlen, void *data)
}
-
+
static void
@@ -2122,3 +2157,3 @@ notify (const char *tag, int status, struct action *act)
closure.act = act;
-
+
env[PROGRAM_NAME_IDX] = program_name;
@@ -2146,3 +2181,3 @@ status_matches_p (struct action *act, unsigned status)
int i;
-
+
if (act->nstat == 0)
@@ -2186,3 +2221,3 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
close_fds (NULL);
-
+
argv[0] = "/bin/sh";
@@ -2210,3 +2245,3 @@ react (struct prog *prog, int status, pid_t pid)
list = default_component.act_list;
-
+
if (WIFEXITED (status))
@@ -2235,3 +2270,3 @@ react (struct prog *prog, int status, pid_t pid)
struct action *act = ep->data;
-
+
if (status_matches_p (act, retcode))
@@ -2242,3 +2277,3 @@ react (struct prog *prog, int status, pid_t pid)
}
-
+
switch (act->act)
@@ -2249,3 +2284,3 @@ react (struct prog *prog, int status, pid_t pid)
break;
-
+
case action_disable:
@@ -2265,3 +2300,3 @@ react (struct prog *prog, int status, pid_t pid)
}
-
+
if (!list && prog->v.p.comp->mode != pies_comp_inetd)
@@ -2296,3 +2331,3 @@ progman_cleanup (int expect_term)
struct prog *listener = prog->v.p.listener;
-
+
listener->v.p.num_instances--;
@@ -2309,3 +2344,3 @@ progman_cleanup (int expect_term)
}
-
+
prog_stop_redirectors (prog);
@@ -2323,2 +2358,10 @@ progman_cleanup (int expect_term)
}
+ else if (prog->v.p.comp->mode == pies_comp_startup)
+ {
+ debug (1, (_("removing startup component %s, pid=%lu"),
+ prog_tag (prog), (unsigned long)pid));
+ destroy_prog (&prog);
+ if (!progman_startup_phase ())
+ pies_schedule_children (PIES_CHLD_WAKEUP);
+ }
else
@@ -2331,3 +2374,3 @@ progman_cleanup (int expect_term)
prog->v.p.status = status_finished;
-
+
if (prog->wait)
@@ -2353,3 +2396,3 @@ progman_cleanup (int expect_term)
}
-
+
break;
@@ -2373,3 +2416,3 @@ progman_cleanup (int expect_term)
}
-
+
if (!expect_term)
@@ -2391,3 +2434,3 @@ progman_stop_component (struct prog **progptr)
break;
-
+
case status_listener:
@@ -2415,3 +2458,3 @@ progman_stop_component (struct prog **progptr)
break;
-
+
case status_finished:
@@ -2443,3 +2486,3 @@ prog_activate_listener (struct prog *prog)
struct component *comp = prog->v.p.comp;
-
+
logmsg (LOG_INFO, _("activating listener %s"), prog_tag (prog));
@@ -2537,7 +2580,7 @@ progman_gc (void)
}
-
+
/* FIXME: Report remaining programs */
-
+
}
-
+
/* EOF */
diff --git a/src/socket.c b/src/socket.c
index aa01543..40c7aa7 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -25,9 +25,12 @@ switch_eids (uid_t *puid, gid_t *pgid, mode_t *pumask)
mode_t omask = umask (*pumask);
-
- if (setegid (*pgid))
- logmsg (LOG_ERR, _("cannot switch to EGID %lu: %s"),
- (unsigned long) *pgid, strerror (errno));
- if (seteuid (*puid))
- logmsg (LOG_ERR, _("cannot switch to EUID %lu: %s"),
- (unsigned long) *puid, strerror (errno));
+
+ if ((*puid && *puid != ouid) || (*pgid && *pgid != ogid))
+ {
+ if (setegid (*pgid))
+ logmsg (LOG_ERR, _("cannot switch to EGID %lu: %s"),
+ (unsigned long) *pgid, strerror (errno));
+ if (seteuid (*puid))
+ logmsg (LOG_ERR, _("cannot switch to EUID %lu: %s"),
+ (unsigned long) *puid, strerror (errno));
+ }
*puid = ouid;
@@ -53,3 +56,3 @@ create_socket (struct pies_url *url, int socket_type,
int switch_back;
-
+
if (strcmp (url->scheme, "unix") == 0
@@ -60,3 +63,3 @@ create_socket (struct pies_url *url, int socket_type,
const char *group = NULL;
-
+
user = url->user;
@@ -101,3 +104,3 @@ create_socket (struct pies_url *url, int socket_type,
}
-
+
if (user)
@@ -113,3 +116,3 @@ create_socket (struct pies_url *url, int socket_type,
}
-
+
if (group)
@@ -124,3 +127,3 @@ create_socket (struct pies_url *url, int socket_type,
}
-
+
if (strlen (url->path) > sizeof addr.s_un.sun_path)
@@ -161,3 +164,3 @@ create_socket (struct pies_url *url, int socket_type,
short port = url->port;
-
+
uid = 0;
@@ -168,3 +171,3 @@ create_socket (struct pies_url *url, int socket_type,
socklen = sizeof (addr.s_in);
-
+
if (!host)
@@ -187,3 +190,3 @@ create_socket (struct pies_url *url, int socket_type,
break;
-
+
default:
@@ -200,3 +203,3 @@ create_socket (struct pies_url *url, int socket_type,
}
-
+
fd = socket (addr.sa.sa_family, socket_type, url->proto);
@@ -252,3 +255,3 @@ pass_fd0 (int fd, int payload)
# endif /* ! CMSG_SPACE */
-
+
char control[CMSG_SPACE (sizeof (int))];
@@ -292,3 +295,3 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
struct sockaddr_un addr;
-
+
if (strlen (socket_name) > sizeof addr.sun_path)
@@ -300,3 +303,3 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
strcpy (addr.sun_path, socket_name);
-
+
for (;;)
@@ -364,3 +367,3 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
struct timeval tv;
-
+
FD_ZERO (&fds);
@@ -432,3 +435,3 @@ calc_fd_max (void)
void *
-register_socket (int fd,
+register_socket (int fd,
socket_handler_t rd,
@@ -456,3 +459,3 @@ register_socket (int fd,
}
-
+
si_tail = sip;
@@ -495,3 +498,3 @@ delete_sockinst (struct sockinst *sp)
fd_max = -1;
-
+
if (sp->prev)
@@ -574,3 +577,3 @@ pies_pause (void)
return;
-
+
if (fd_max == -1)
@@ -583,3 +586,3 @@ pies_pause (void)
fd_set exset = fdset[PIES_EVT_EX];
-
+
int rc = select (fd_max + 1, &rdset, &wrset, &exset, NULL);
@@ -639,2 +642 @@ pies_pause (void)
}
-
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 447104b..b2f2719 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,3 +16,9 @@
-EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 respawn retcode mailer
+AUXTOOLS = \
+ aux/respawn\
+ aux/retcode\
+ aux/mailer\
+ aux/startup
+
+EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 $(AUXTOOLS)
DISTCLEANFILES = atconfig $(check_SCRIPTS)
@@ -48,2 +54,3 @@ TESTSUITE_AT = \
ret-notify.at\
+ startup.at\
version.at
diff --git a/tests/atlocal.in b/tests/atlocal.in
index 9069bbd..1992b80 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -6,3 +6,3 @@ PATH=@abs_builddir@:@abs_top_builddir@/src:$srcdir:$PATH
XFAILFILE=$abs_builddir/.badversion
-
+auxdir="$abs_srcdir/aux"
trimws() {
diff --git a/tests/mailer b/tests/aux/mailer
index f832ff5..f832ff5 100755
--- a/tests/mailer
+++ b/tests/aux/mailer
diff --git a/tests/respawn b/tests/aux/respawn
index 11d59f6..11d59f6 100755
--- a/tests/respawn
+++ b/tests/aux/respawn
diff --git a/tests/retcode b/tests/aux/retcode
index b827ba9..b827ba9 100755
--- a/tests/retcode
+++ b/tests/aux/retcode
diff --git a/tests/aux/startup b/tests/aux/startup
new file mode 100755
index 0000000..b9d92a3
--- a/dev/null
+++ b/tests/aux/startup
@@ -0,0 +1,7 @@
+#!/bin/sh
+dir=${1:?}
+time=${2:?}
+tag=${3:?}
+
+touch $dir/$tag
+sleep $time
diff --git a/tests/redirect.at b/tests/redirect.at
index 9e53ba2..3a8cca7 100644
--- a/tests/redirect.at
+++ b/tests/redirect.at
@@ -26,3 +26,3 @@ component test {
mode respawn;
- command "$abs_srcdir/respawn -tag respawn -append -pid $comp_pid_file";
+ command "$auxdir/respawn -tag respawn -append -pid $comp_pid_file";
stdout file "$outfile";
diff --git a/tests/respawn.at b/tests/respawn.at
index 8d72c40..4a8e3a7 100644
--- a/tests/respawn.at
+++ b/tests/respawn.at
@@ -25,3 +25,3 @@ component test {
mode respawn;
- command "$abs_srcdir/respawn -append -pid $comp_pid_file";
+ command "$auxdir/respawn -append -pid $comp_pid_file";
}
diff --git a/tests/ret-exec.at b/tests/ret-exec.at
index bf2c1a4..0b3d716 100644
--- a/tests/ret-exec.at
+++ b/tests/ret-exec.at
@@ -28,6 +28,6 @@ component test {
return-code 10 {
- exec "$abs_srcdir/retcode $report_file";
+ exec "$auxdir/retcode $report_file";
action disable;
}
- command "$abs_srcdir/respawn -sleep 2 -pid $comp_pid_file -exit 10";
+ command "$auxdir/respawn -sleep 2 -pid $comp_pid_file -exit 10";
}
diff --git a/tests/ret-notify.at b/tests/ret-notify.at
index d1a7f39..a7768aa 100644
--- a/tests/ret-notify.at
+++ b/tests/ret-notify.at
@@ -24,4 +24,4 @@ report_file=$PWD/report
cat > pies.conf <<_EOT
-mailer-program "$abs_srcdir/mailer";
-mailer-command-line "$abs_srcdir/mailer $report_file";
+mailer-program "$auxdir/mailer";
+mailer-command-line "$auxdir/mailer $report_file";
component test {
@@ -32,3 +32,3 @@ component test {
}
- command "$abs_srcdir/respawn -sleep 2 -exit 10";
+ command "$auxdir/respawn -sleep 2 -exit 10";
}
diff --git a/tests/startup.at b/tests/startup.at
new file mode 100644
index 0000000..72017ce
--- a/dev/null
+++ b/tests/startup.at
@@ -0,0 +1,84 @@
+# This file is part of GNU pies testsuite. -*- Autotest -*-
+# Copyright (C) 2019 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/>.
+
+AT_SETUP([Startup components])
+
+AT_CHECK([
+PIES_XFAIL_CHECK
+PIES_CONTROL_INIT
+comp_pid_file=$PWD/comp.pid
+
+cat > pies.conf <<_EOT
+component b1 {
+ mode startup;
+ command "$auxdir/startup $PWD 1 b1";
+}
+
+component b2 {
+ mode startup;
+ command "$auxdir/startup $PWD 2 b2";
+}
+
+component test {
+ mode respawn;
+ command "$auxdir/respawn -append -pid $comp_pid_file";
+}
+_EOT
+
+pies --config-file control.conf --config-file pies.conf
+
+n=0
+res=
+b1=
+b2=
+while :
+do
+ echo "n=$n" >> tracefile
+ if test -z "$b1" && test -f b1; then
+ res="${res}b1"
+ b1=1
+ echo "got b1" >> tracefile
+ fi
+ if test -z "$b2" && test -f b2; then
+ res="${res}b2"
+ b2=1
+ echo "got b2" >> tracefile
+ fi
+ if test -f $comp_pid_file; then
+ echo "got pidfile" >> tracefile
+ res="${res}pid"
+ break
+ fi
+ sleep 1
+ n=$(($n + 1))
+ if test $n -gt 10; then
+ echo >&2 "timed out"
+ break
+ fi
+done
+
+PIES_STOP
+case $res in
+b1b2pid|b2b1pid) echo b1b2pid;;
+*) echo $res
+esac
+],
+[0],
+[b1b2pid
+])
+
+AT_CLEANUP
+
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 03ddd50..2a1167d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -67 +67,2 @@ m4_include([ret-exec.at])
m4_include([ret-notify.at])
+m4_include([startup.at])

Return to:

Send suggestions and report system problems to the System administrator.