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) (unidiff)
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
@@ -24,6 +24,11 @@ struct complist
24 struct component *tail; 24 struct component *tail;
25}; 25};
26 26
27/* 0 on the first load, and 1 on all subsequent reloads. Tells the
28 component_config_commit whether we're starting from scratch or just
29 updating an already loaded configuration */
30static int loaded;
31
27static struct complist comp_list[2]; 32static struct complist comp_list[2];
28static int cur; 33static int cur;
29 34
@@ -32,13 +37,13 @@ static size_t comp_count;
32 37
33static pies_depmap_t depmap; 38static pies_depmap_t depmap;
34 39
35static int 40static inline int
36next_index (void) 41next_index (void)
37{ 42{
38 return (cur + 1) % ARRAY_SIZE (comp_list); 43 return (cur + 1) % ARRAY_SIZE (comp_list);
39} 44}
40 45
41static int 46static inline int
42prev_index (void) 47prev_index (void)
43{ 48{
44 return (cur + ARRAY_SIZE (comp_list) - 1) % ARRAY_SIZE (comp_list); 49 return (cur + ARRAY_SIZE (comp_list) - 1) % ARRAY_SIZE (comp_list);
@@ -85,6 +90,22 @@ component_append (struct component *comp)
85} 90}
86 91
87void 92void
93comp_array_remove (size_t i)
94{
95 struct component *comp = comp_array[i];
96
97 depmap_remove (depmap, i);
98 while (i < comp_count -1)
99 {
100 comp_array[i] = comp_array[i+1];
101 comp_array[i]->arridx = i;
102 i++;
103 }
104 component_free (comp);
105 comp_count--;
106}
107
108void
88component_unlink (struct component *comp) 109component_unlink (struct component *comp)
89{ 110{
90 struct complist *list = &comp_list[comp->listidx]; 111 struct complist *list = &comp_list[comp->listidx];
@@ -201,7 +222,12 @@ component_ref_decr (struct component *comp)
201{ 222{
202 assert (comp->ref_count > 0); 223 assert (comp->ref_count > 0);
203 if (--comp->ref_count == 0) 224 if (--comp->ref_count == 0)
204 component_free (comp); 225 {
226 if (component_is_active (comp))
227 comp_array_remove (comp->arridx);
228 else
229 component_free (comp);
230 }
205} 231}
206 232
207static int 233static int
@@ -425,17 +451,6 @@ report_cyclic_dependency (pies_depmap_t dp, size_t idx)
425} 451}
426 452
427void 453void
428comp_array_remove (size_t i)
429{
430 struct component *comp = comp_array[i];
431 if (i < comp_count - 1)
432 memmove (&comp_array[i], &comp_array[i+1],
433 (comp_count - i - 1) * sizeof comp_array[0]);
434 component_free (comp);
435 comp_count--;
436}
437
438void
439component_build_depmap (void) 454component_build_depmap (void)
440{ 455{
441 size_t i; 456 size_t i;
@@ -460,7 +475,6 @@ component_build_depmap (void)
460 "which is not declared"), 475 "which is not declared"),
461 comp->tag, tag); 476 comp->tag, tag);
462 comp_array_remove (i); 477 comp_array_remove (i);
463 depmap_remove (depmap, i);
464 continue; 478 continue;
465 } 479 }
466 depmap_set (depmap, i, tgt); 480 depmap_set (depmap, i, tgt);
@@ -497,10 +511,7 @@ component_build_depmap (void)
497 511
498 for (i = 0; i < comp_count;) 512 for (i = 0; i < comp_count;)
499 if (comp_array[i]->flags & CF_REMOVE) 513 if (comp_array[i]->flags & CF_REMOVE)
500 { 514 comp_array_remove (i);
501 comp_array_remove (i);
502 depmap_remove (depmap, i);
503 }
504 else 515 else
505 i++; 516 i++;
506 517
@@ -528,22 +539,36 @@ component_config_commit (void)
528 comp_array = grecs_realloc (comp_array, i * sizeof (comp_array[0])); 539 comp_array = grecs_realloc (comp_array, i * sizeof (comp_array[0]));
529 comp_count = i; 540 comp_count = i;
530 541
531 /* Rearrange components, registering prog entries for the new ones */ 542 /* Rearrange components, registering entries for the new ones */
532 for (comp = list->head, i = 0; comp; comp = comp->next, i++) 543 for (comp = list->head, i = 0; comp; )
533 { 544 {
534 match = complist_find_match (prev, comp); 545 struct component *next = comp->next;
535 if (match) 546 if (loaded && comp->mode == pies_comp_startup)
536 { 547 {
537 component_merge (match, comp); 548 /* Ignore startup components */
538 component_unlink (match); 549 component_unlink (comp);
539 match->listidx = cur;
540 component_link (match, comp->prev);
541 component_free (comp); 550 component_free (comp);
542 comp = match;
543 } 551 }
544 comp_array[i] = comp; 552 else
545 comp->arridx = i; 553 {
554 match = complist_find_match (prev, comp);
555 if (match)
556 {
557 component_merge (match, comp);
558 component_unlink (match);
559 match->listidx = cur;
560 component_link (match, comp->prev);
561 component_free (comp);
562 comp = match;
563 }
564 comp_array[i] = comp;
565 comp->arridx = i;
566 i++;
567 }
568 comp = next;
546 } 569 }
570 /* Adjust comp_count */
571 comp_count = i;
547 572
548 /* Mark orphaned progs for termination */ 573 /* Mark orphaned progs for termination */
549 list = &comp_list[prev]; 574 list = &comp_list[prev];
@@ -560,6 +585,8 @@ component_config_commit (void)
560 for (comp = comp_list[cur].head; comp; comp = comp->next) 585 for (comp = comp_list[cur].head; comp; comp = comp->next)
561 if (!comp->prog) 586 if (!comp->prog)
562 register_prog (comp); 587 register_prog (comp);
588
589 loaded = 1;
563} 590}
564 591
565static int 592static int
diff --git a/src/pies.c b/src/pies.c
index 89c0b7e..98488a6 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -132,7 +132,7 @@ int
132config_file_remove (const char *name) 132config_file_remove (const char *name)
133{ 133{
134 struct grecs_list_entry *ep; 134 struct grecs_list_entry *ep;
135 135
136 for (ep = config_list->head; ep; ep = ep->next) 136 for (ep = config_list->head; ep; ep = ep->next)
137 { 137 {
138 struct config_file *file = ep->data; 138 struct config_file *file = ep->data;
@@ -156,7 +156,7 @@ void
156config_file_list_serialize (struct json_value *ar) 156config_file_list_serialize (struct json_value *ar)
157{ 157{
158 struct grecs_list_entry *ep; 158 struct grecs_list_entry *ep;
159 159
160 for (ep = config_list->head; ep; ep = ep->next) 160 for (ep = config_list->head; ep; ep = ep->next)
161 { 161 {
162 struct config_file *file = ep->data; 162 struct config_file *file = ep->data;
@@ -327,7 +327,7 @@ action_free (struct action *act)
327 free (act->addr); 327 free (act->addr);
328 free (act->message); 328 free (act->message);
329 free (act->command); 329 free (act->command);
330 330
331 free (act); 331 free (act);
332} 332}
333 333
@@ -359,7 +359,7 @@ create_action (struct component *comp,
359 unsigned n; 359 unsigned n;
360 const char *arg = getarg (val, i, locus); 360 const char *arg = getarg (val, i, locus);
361 size_t len = strlen (arg); 361 size_t len = strlen (arg);
362 362
363 if (isdigit (arg[0])) 363 if (isdigit (arg[0]))
364 { 364 {
365 char *p; 365 char *p;
@@ -394,12 +394,12 @@ create_action (struct component *comp,
394 grecs_error (locus, 0, _("%s: not a return code"), arg); 394 grecs_error (locus, 0, _("%s: not a return code"), arg);
395 continue; 395 continue;
396 } 396 }
397 397
398 /* Alles in ordnung */ 398 /* Alles in ordnung */
399 retv[retc++] = n; 399 retv[retc++] = n;
400 } 400 }
401 } 401 }
402 402
403 if (retc == 0 && !allflag) 403 if (retc == 0 && !allflag)
404 { 404 {
405 free (retv); 405 free (retv);
@@ -472,18 +472,18 @@ return_code_section_parser (enum grecs_callback_command cmd,
472 grecs_error (locus, 0, _("missing tag")); 472 grecs_error (locus, 0, _("missing tag"));
473 return 1; 473 return 1;
474 } 474 }
475 475
476 switch (value->type) 476 switch (value->type)
477 { 477 {
478 case GRECS_TYPE_STRING: 478 case GRECS_TYPE_STRING:
479 act = create_action (comp, locus, value, 1, _get_string_arg); 479 act = create_action (comp, locus, value, 1, _get_string_arg);
480 break; 480 break;
481 481
482 case GRECS_TYPE_ARRAY: 482 case GRECS_TYPE_ARRAY:
483 act = create_action (comp, locus, value, 483 act = create_action (comp, locus, value,
484 value->v.arg.c, _get_array_arg); 484 value->v.arg.c, _get_array_arg);
485 break; 485 break;
486 486
487 case GRECS_TYPE_LIST: 487 case GRECS_TYPE_LIST:
488 count = grecs_list_size (value->v.list); 488 count = grecs_list_size (value->v.list);
489 act = create_action (comp, locus, value, count, _get_list_arg); 489 act = create_action (comp, locus, value, count, _get_list_arg);
@@ -492,7 +492,7 @@ return_code_section_parser (enum grecs_callback_command cmd,
492 return 1; 492 return 1;
493 *(struct action **) cb_data = act; 493 *(struct action **) cb_data = act;
494 break; 494 break;
495 495
496 case grecs_callback_section_end: 496 case grecs_callback_section_end:
497 break; 497 break;
498 498
@@ -542,7 +542,7 @@ _cb_command (enum grecs_callback_command cmd,
542 wordsplit_get_words (&ws, &comp->argc, &comp->argv); 542 wordsplit_get_words (&ws, &comp->argc, &comp->argv);
543 wordsplit_free (&ws); 543 wordsplit_free (&ws);
544 break; 544 break;
545 545
546 case GRECS_TYPE_ARRAY: 546 case GRECS_TYPE_ARRAY:
547 comp->argv = config_array_to_argv (value, locus, &comp->argc); 547 comp->argv = config_array_to_argv (value, locus, &comp->argc);
548 break; 548 break;
@@ -702,7 +702,7 @@ _cb_redir (enum grecs_callback_command cmd,
702 {NULL} 702 {NULL}
703 }; 703 };
704 int res; 704 int res;
705 705
706 switch (value->type) 706 switch (value->type)
707 { 707 {
708 case GRECS_TYPE_STRING: 708 case GRECS_TYPE_STRING:
@@ -719,7 +719,7 @@ _cb_redir (enum grecs_callback_command cmd,
719 return 0; 719 return 0;
720 } 720 }
721 break; 721 break;
722 722
723 case GRECS_TYPE_ARRAY: 723 case GRECS_TYPE_ARRAY:
724 if (assert_grecs_value_type (locus, value->v.arg.v[0], 724 if (assert_grecs_value_type (locus, value->v.arg.v[0],
725 GRECS_TYPE_STRING)) 725 GRECS_TYPE_STRING))
@@ -739,12 +739,12 @@ _cb_redir (enum grecs_callback_command cmd,
739 if (assert_grecs_value_type (locus, value->v.arg.v[1], 739 if (assert_grecs_value_type (locus, value->v.arg.v[1],
740 GRECS_TYPE_STRING)) 740 GRECS_TYPE_STRING))
741 return 0; 741 return 0;
742 742
743 switch (res) 743 switch (res)
744 { 744 {
745 case redir_null: 745 case redir_null:
746 break; 746 break;
747 747
748 case redir_syslog: 748 case redir_syslog:
749 if (string_to_syslog_priority (value->v.arg.v[1]->v.string, 749 if (string_to_syslog_priority (value->v.arg.v[1]->v.string,
750 &rp->v.prio)) 750 &rp->v.prio))
@@ -755,7 +755,7 @@ _cb_redir (enum grecs_callback_command cmd,
755 return 0; 755 return 0;
756 } 756 }
757 break; 757 break;
758 758
759 case redir_file: 759 case redir_file:
760 rp->v.file = grecs_strdup (value->v.arg.v[1]->v.string); 760 rp->v.file = grecs_strdup (value->v.arg.v[1]->v.string);
761 break; 761 break;
@@ -764,17 +764,17 @@ _cb_redir (enum grecs_callback_command cmd,
764 rp->type = res; 764 rp->type = res;
765 } 765 }
766 break; 766 break;
767 767
768 default: 768 default:
769 grecs_error (locus, 0, _("unexpected list")); 769 grecs_error (locus, 0, _("unexpected list"));
770 } 770 }
771 771
772 return 0; 772 return 0;
773} 773}
774 774
775static struct tokendef socktype_xtab[] = { 775static struct tokendef socktype_xtab[] = {
776 { "stream", SOCK_STREAM }, 776 { "stream", SOCK_STREAM },
777 { "dgram", SOCK_DGRAM }, 777 { "dgram", SOCK_DGRAM },
778 { "seqpacket", SOCK_SEQPACKET }, 778 { "seqpacket", SOCK_SEQPACKET },
779 { "raw", SOCK_RAW }, 779 { "raw", SOCK_RAW },
780 { "rdm", SOCK_RDM }, 780 { "rdm", SOCK_RDM },
@@ -820,12 +820,14 @@ static struct tokendef modetab[] = {
820 {"nostartaccept", pies_comp_inetd}, 820 {"nostartaccept", pies_comp_inetd},
821 {"pass-fd", pies_comp_pass_fd}, 821 {"pass-fd", pies_comp_pass_fd},
822 {"pass", pies_comp_pass_fd}, 822 {"pass", pies_comp_pass_fd},
823 {"startup", pies_comp_startup},
824 {"shutdown", pies_comp_shutdown},
823 {"boot", pies_comp_boot}, 825 {"boot", pies_comp_boot},
824 {"bootwait", pies_comp_boot}, 826 {"bootwait", pies_comp_boot},
825 {"powerfail", pies_comp_powerfail}, 827 {"powerfail", pies_comp_powerfail},
826 {"powerwait", pies_comp_powerwait}, 828 {"powerwait", pies_comp_powerwait},
827 {"powerokwait", pies_comp_powerokwait}, 829 {"powerokwait", pies_comp_powerokwait},
828 {"ctrlaltdel", pies_comp_ctrlaltdel}, 830 {"ctrlaltdel", pies_comp_ctrlaltdel},
829 {"ondemand", pies_comp_ondemand}, 831 {"ondemand", pies_comp_ondemand},
830 {"sysinit", pies_comp_sysinit}, 832 {"sysinit", pies_comp_sysinit},
831 {"powerfailnow", pies_comp_powerfailnow}, 833 {"powerfailnow", pies_comp_powerfailnow},
@@ -920,11 +922,11 @@ _cb_flags (enum grecs_callback_command cmd,
920 return 1; 922 return 1;
921 } 923 }
922 break; 924 break;
923 925
924 case GRECS_TYPE_LIST: 926 case GRECS_TYPE_LIST:
925 { 927 {
926 struct grecs_list_entry *ep; 928 struct grecs_list_entry *ep;
927 929
928 for (ep = value->v.list->head; ep; ep = ep->next) 930 for (ep = value->v.list->head; ep; ep = ep->next)
929 { 931 {
930 const grecs_value_t *vp = ep->data; 932 const grecs_value_t *vp = ep->data;
@@ -939,7 +941,7 @@ _cb_flags (enum grecs_callback_command cmd,
939 } 941 }
940 } 942 }
941 break; 943 break;
942 944
943 case GRECS_TYPE_ARRAY: 945 case GRECS_TYPE_ARRAY:
944 grecs_error (locus, 0, _("too many arguments")); 946 grecs_error (locus, 0, _("too many arguments"));
945 return 1; 947 return 1;
@@ -1228,7 +1230,7 @@ struct grecs_keyword *
1228find_component_keyword (const char *ident) 1230find_component_keyword (const char *ident)
1229{ 1231{
1230 struct grecs_keyword *kwp; 1232 struct grecs_keyword *kwp;
1231 1233
1232 for (kwp = component_keywords; kwp->ident; kwp++) 1234 for (kwp = component_keywords; kwp->ident; kwp++)
1233 if (strcmp (kwp->ident, ident) == 0) 1235 if (strcmp (kwp->ident, ident) == 0)
1234 return kwp; 1236 return kwp;
@@ -1256,7 +1258,7 @@ component_section_parser (enum grecs_callback_command cmd,
1256 comp = *(struct component **) section_data; 1258 comp = *(struct component **) section_data;
1257 component_finish (comp, locus); 1259 component_finish (comp, locus);
1258 break; 1260 break;
1259 1261
1260 case grecs_callback_set_value: 1262 case grecs_callback_set_value:
1261 grecs_error (locus, 0, _("expected block statement")); 1263 grecs_error (locus, 0, _("expected block statement"));
1262 } 1264 }
@@ -1534,7 +1536,7 @@ pies_config_parse (char const *name)
1534 1536
1535 if (!tree) 1537 if (!tree)
1536 return 1; 1538 return 1;
1537 1539
1538 for (node = tree; node; node = node->next) 1540 for (node = tree; node; node = node->next)
1539 { 1541 {
1540 node = grecs_find_node (node, "identity-provider"); 1542 node = grecs_find_node (node, "identity-provider");
@@ -1550,7 +1552,7 @@ pies_config_parse (char const *name)
1550 1552
1551 if (grecs_error_count) 1553 if (grecs_error_count)
1552 return 1; 1554 return 1;
1553 1555
1554 return 0; 1556 return 0;
1555} 1557}
1556 1558
@@ -1573,7 +1575,7 @@ pies_read_config (void)
1573 int err = 0; 1575 int err = 0;
1574 1576
1575 component_config_begin (); 1577 component_config_begin ();
1576 1578
1577 for (ep = config_list->head; ep; ep = ep->next) 1579 for (ep = config_list->head; ep; ep = ep->next)
1578 { 1580 {
1579 struct config_file *file = ep->data; 1581 struct config_file *file = ep->data;
@@ -1583,10 +1585,10 @@ pies_read_config (void)
1583 1585
1584 if (init_process) 1586 if (init_process)
1585 err = 0; 1587 err = 0;
1586 1588
1587 if (err) 1589 if (err)
1588 component_config_rollback (); 1590 component_config_rollback ();
1589 1591
1590 return err; 1592 return err;
1591} 1593}
1592 1594
@@ -1656,7 +1658,7 @@ setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc)
1656{ 1658{
1657 int i; 1659 int i;
1658 struct sigaction act; 1660 struct sigaction act;
1659 1661
1660 act.sa_flags = 0; 1662 act.sa_flags = 0;
1661 sigemptyset (&act.sa_mask); 1663 sigemptyset (&act.sa_mask);
1662 for (i = 0; i < sigc; i++) 1664 for (i = 0; i < sigc; i++)
@@ -1779,7 +1781,7 @@ request_restart_components (size_t cc, char **cv)
1779{ 1781{
1780 char **argv; 1782 char **argv;
1781 size_t i, j; 1783 size_t i, j;
1782 1784
1783 argv = grecs_calloc (5 + 3 * cc - 1, sizeof (*argv)); 1785 argv = grecs_calloc (5 + 3 * cc - 1, sizeof (*argv));
1784 argv[0] = "piesctl"; 1786 argv[0] = "piesctl";
1785 argv[1] = "--url"; 1787 argv[1] = "--url";
@@ -1803,7 +1805,7 @@ void
1803list_components (void) 1805list_components (void)
1804{ 1806{
1805 char *argv[5]; 1807 char *argv[5];
1806 1808
1807 argv[0] = "piesctl"; 1809 argv[0] = "piesctl";
1808 argv[1] = "--url"; 1810 argv[1] = "--url";
1809 argv[2] = (char*) pies_control_url (); 1811 argv[2] = (char*) pies_control_url ();
@@ -1942,7 +1944,7 @@ set_mailer_argcv (void)
1942{ 1944{
1943 int i; 1945 int i;
1944 struct wordsplit ws; 1946 struct wordsplit ws;
1945 1947
1946 if (wordsplit (mailer_command_line, &ws, WRDSF_DEFFLAGS)) 1948 if (wordsplit (mailer_command_line, &ws, WRDSF_DEFFLAGS))
1947 { 1949 {
1948 logmsg (LOG_CRIT, _("cannot parse mailer command line: %s"), 1950 logmsg (LOG_CRIT, _("cannot parse mailer command line: %s"),
@@ -2033,7 +2035,7 @@ main (int argc, char **argv)
2033 struct grecs_list_entry *ep; 2035 struct grecs_list_entry *ep;
2034 int diag_flags; 2036 int diag_flags;
2035 int i; 2037 int i;
2036 2038
2037 set_program_name (argv[0]); 2039 set_program_name (argv[0]);
2038#ifdef ENABLE_NLS 2040#ifdef ENABLE_NLS
2039 setlocale (LC_ALL, ""); 2041 setlocale (LC_ALL, "");
@@ -2043,10 +2045,10 @@ main (int argc, char **argv)
2043 mf_proctitle_init (argc, argv, environ); 2045 mf_proctitle_init (argc, argv, environ);
2044 2046
2045 grecs_print_diag_fun = pies_diag_printer; 2047 grecs_print_diag_fun = pies_diag_printer;
2046 2048
2047 pies_master_argc = argc; 2049 pies_master_argc = argc;
2048 pies_master_argv = argv; 2050 pies_master_argv = argv;
2049 2051
2050 set_quoting_style (NULL, shell_quoting_style); 2052 set_quoting_style (NULL, shell_quoting_style);
2051 2053
2052 init_process = getpid () == 1; 2054 init_process = getpid () == 1;
@@ -2058,7 +2060,7 @@ main (int argc, char **argv)
2058 break; 2060 break;
2059 } 2061 }
2060 } 2062 }
2061 2063
2062 /* Set default logging */ 2064 /* Set default logging */
2063 if (init_process) 2065 if (init_process)
2064 { 2066 {
@@ -2067,13 +2069,13 @@ main (int argc, char **argv)
2067 } 2069 }
2068 else 2070 else
2069 diag_flags = DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR); 2071 diag_flags = DIAG_TO_SYSLOG | (stderr_closed_p () ? 0 : DIAG_TO_STDERR);
2070 2072
2071 diag_setup (diag_flags); 2073 diag_setup (diag_flags);
2072 2074
2073 config_init (); 2075 config_init ();
2074 2076
2075 parse_options (&argc, &argv); 2077 parse_options (&argc, &argv);
2076 2078
2077 if (argc && !(command == COM_RESTART_COMPONENT 2079 if (argc && !(command == COM_RESTART_COMPONENT
2078 || command == COM_TRACE_DEPEND 2080 || command == COM_TRACE_DEPEND
2079 || command == COM_TRACE_PREREQ)) 2081 || command == COM_TRACE_PREREQ))
@@ -2081,7 +2083,7 @@ main (int argc, char **argv)
2081 logmsg (LOG_ERR, "extra command line arguments"); 2083 logmsg (LOG_ERR, "extra command line arguments");
2082 exit (EX_USAGE); 2084 exit (EX_USAGE);
2083 } 2085 }
2084 2086
2085 if (!instance) 2087 if (!instance)
2086 { 2088 {
2087 instance = strrchr (program_name, '/'); 2089 instance = strrchr (program_name, '/');
@@ -2119,13 +2121,13 @@ main (int argc, char **argv)
2119 2121
2120 set_state_file_names (instance); 2122 set_state_file_names (instance);
2121 set_mailer_argcv (); 2123 set_mailer_argcv ();
2122 2124
2123 if (lint_mode) 2125 if (lint_mode)
2124 exit (0); 2126 exit (0);
2125 2127
2126 /* Re-setup logging: it might have been reset in the config file */ 2128 /* Re-setup logging: it might have been reset in the config file */
2127 diag_setup (log_to_stderr_only ? DIAG_TO_STDERR : 0); 2129 diag_setup (log_to_stderr_only ? DIAG_TO_STDERR : 0);
2128 2130
2129 if (!control.url) 2131 if (!control.url)
2130 { 2132 {
2131 char const *str = default_control_url[init_process]; 2133 char const *str = default_control_url[init_process];
@@ -2137,7 +2139,7 @@ main (int argc, char **argv)
2137 exit (EX_OSERR); 2139 exit (EX_OSERR);
2138 } 2140 }
2139 } 2141 }
2140 2142
2141 switch (command) 2143 switch (command)
2142 { 2144 {
2143 case COM_RESTART_COMPONENT: 2145 case COM_RESTART_COMPONENT:
@@ -2145,7 +2147,7 @@ main (int argc, char **argv)
2145 if (pies_umask) 2147 if (pies_umask)
2146 umask (pies_umask); 2148 umask (pies_umask);
2147 exit (request_restart_components (argc, argv)); 2149 exit (request_restart_components (argc, argv));
2148 2150
2149 case COM_RELOAD: 2151 case COM_RELOAD:
2150 exit (request_reload ()); 2152 exit (request_reload ());
2151 2153
@@ -2162,11 +2164,11 @@ main (int argc, char **argv)
2162 case COM_TRACE_DEPEND: 2164 case COM_TRACE_DEPEND:
2163 components_trace (argv, depmap_row); 2165 components_trace (argv, depmap_row);
2164 exit (0); 2166 exit (0);
2165 2167
2166 case COM_TRACE_PREREQ: 2168 case COM_TRACE_PREREQ:
2167 components_trace (argv, depmap_col); 2169 components_trace (argv, depmap_col);
2168 exit (0); 2170 exit (0);
2169 2171
2170 default: 2172 default:
2171 pies_priv_setup (&pies_privs); 2173 pies_priv_setup (&pies_privs);
2172 if (pies_umask) 2174 if (pies_umask)
@@ -2193,13 +2195,13 @@ main (int argc, char **argv)
2193 exit (EX_USAGE); 2195 exit (EX_USAGE);
2194 } 2196 }
2195 break; 2197 break;
2196 2198
2197 case pies_status_running: 2199 case pies_status_running:
2198 logmsg (LOG_ERR, _("another pies instance already running (pid %lu)"), 2200 logmsg (LOG_ERR, _("another pies instance already running (pid %lu)"),
2199 (unsigned long) pid); 2201 (unsigned long) pid);
2200 exit (EX_USAGE); 2202 exit (EX_USAGE);
2201 } 2203 }
2202 2204
2203 if (!foreground) 2205 if (!foreground)
2204 { 2206 {
2205 check_pidfile (pidfile); 2207 check_pidfile (pidfile);
@@ -2212,14 +2214,14 @@ main (int argc, char **argv)
2212 } 2214 }
2213 2215
2214 logmsg (LOG_INFO, _("%s %s starting"), proginfo.package, proginfo.version); 2216 logmsg (LOG_INFO, _("%s %s starting"), proginfo.package, proginfo.version);
2215 2217
2216 if (!init_process) 2218 if (!init_process)
2217 { 2219 {
2218 if (ctl_open ()) 2220 if (ctl_open ())
2219 exit (EX_UNAVAILABLE); 2221 exit (EX_UNAVAILABLE);
2220 create_pidfile (pidfile); 2222 create_pidfile (pidfile);
2221 } 2223 }
2222 2224
2223 if (pies_master_argv[0][0] != '/') 2225 if (pies_master_argv[0][0] != '/')
2224 logmsg (LOG_NOTICE, 2226 logmsg (LOG_NOTICE,
2225 _("not started as an absolute pathname; " 2227 _("not started as an absolute pathname; "
@@ -2228,6 +2230,7 @@ main (int argc, char **argv)
2228 signal_setup (sig_handler); 2230 signal_setup (sig_handler);
2229 2231
2230 progman_create_sockets (); 2232 progman_create_sockets ();
2233 program_init_startup ();
2231 progman_start (); 2234 progman_start ();
2232 2235
2233 do 2236 do
@@ -2261,7 +2264,7 @@ main (int argc, char **argv)
2261 pies_schedule_children (PIES_CHLD_WAKEUP); 2264 pies_schedule_children (PIES_CHLD_WAKEUP);
2262 action = ACTION_CONT; 2265 action = ACTION_CONT;
2263 break; 2266 break;
2264 2267
2265 case ACTION_STOP: 2268 case ACTION_STOP:
2266 if (init_process) 2269 if (init_process)
2267 { 2270 {
@@ -2276,7 +2279,7 @@ main (int argc, char **argv)
2276 pies_schedule_children (PIES_CHLD_WAKEUP); 2279 pies_schedule_children (PIES_CHLD_WAKEUP);
2277 action = ACTION_CONT; 2280 action = ACTION_CONT;
2278 break; 2281 break;
2279 2282
2280 case ACTION_KBREQUEST: 2283 case ACTION_KBREQUEST:
2281 debug (1, ("kbrequest")); 2284 debug (1, ("kbrequest"));
2282 sysvinit_runlevel_setup (PIES_COMP_MASK (pies_comp_kbrequest)); 2285 sysvinit_runlevel_setup (PIES_COMP_MASK (pies_comp_kbrequest));
diff --git a/src/pies.h b/src/pies.h
index a7f6567..bdc406b 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -104,7 +104,7 @@ struct action
104 enum return_action act; /* Action to take when the component terminates */ 104 enum return_action act; /* Action to take when the component terminates */
105 char *addr; /* Addresses to notify about it. */ 105 char *addr; /* Addresses to notify about it. */
106 char *message; /* Notification mail. */ 106 char *message; /* Notification mail. */
107 char *command; /* Execute this command */ 107 char *command; /* Execute this command */
108}; 108};
109 109
110 110
@@ -137,14 +137,21 @@ enum pies_comp_mode
137 component via the UNIX domain socket. Corresponds to 137 component via the UNIX domain socket. Corresponds to
138 `start_action = pass' in MeTA1. */ 138 `start_action = pass' in MeTA1. */
139 pies_comp_pass_fd, 139 pies_comp_pass_fd,
140 140
141 /* Components of this type runs once on program startup. Running other
142 components is delayed until the last startup component finishes. */
143 pies_comp_startup,
144
145 /* FIXME: Runs before program termination */
146 pies_comp_shutdown,
147
141 /* 148 /*
142 ** Init-style components 149 ** Init-style components
143 */ 150 */
144 pies_mark_sysvinit, 151 pies_mark_sysvinit,
145 /* Start the process when the specified runlevel is entered and wait 152 /* Start the process when the specified runlevel is entered and wait
146 for its termination */ 153 for its termination */
147 pies_comp_wait = pies_mark_sysvinit, 154 pies_comp_wait = pies_mark_sysvinit,
148 /* Execute the component once, when the specified runlevel is entered */ 155 /* Execute the component once, when the specified runlevel is entered */
149 pies_comp_once, 156 pies_comp_once,
150 /* Execute the component during system boot. Ignore runlevel settings. */ 157 /* Execute the component during system boot. Ignore runlevel settings. */
@@ -162,7 +169,7 @@ enum pies_comp_mode
162 pies_comp_powerokwait, 169 pies_comp_powerokwait,
163 /* Execute the process when SIGINT is delivered, i.e. someone has 170 /* Execute the process when SIGINT is delivered, i.e. someone has
164 pressed the Ctrl+Alt+Del combination. */ 171 pressed the Ctrl+Alt+Del combination. */
165 pies_comp_ctrlaltdel, 172 pies_comp_ctrlaltdel,
166 /* Execute the component when a specified ondemand runlevel is called */ 173 /* Execute the component when a specified ondemand runlevel is called */
167 pies_comp_ondemand, 174 pies_comp_ondemand,
168 /* Execute the component on the system boot. */ 175 /* Execute the component on the system boot. */
@@ -184,16 +191,16 @@ enum pies_comp_mode
184 191
185#define CF_DISABLED 0x001 /* The componenet is disabled */ 192#define CF_DISABLED 0x001 /* The componenet is disabled */
186#define CF_PRECIOUS 0x002 /* The component is precious (should not 193#define CF_PRECIOUS 0x002 /* The component is precious (should not
187 be disabled) */ 194 be disabled) */
188#define CF_WAIT 0x004 /* Wait for the component instance to 195#define CF_WAIT 0x004 /* Wait for the component instance to
189 terminate. */ 196 terminate. */
190#define CF_TCPMUX 0x008 /* A plain TCPMUX service */ 197#define CF_TCPMUX 0x008 /* A plain TCPMUX service */
191#define CF_TCPMUXPLUS 0x010 /* A TCPMUX-plus service, i.e. pies 198#define CF_TCPMUXPLUS 0x010 /* A TCPMUX-plus service, i.e. pies
192 must emit a '+' response before starting 199 must emit a '+' response before starting
193 it */ 200 it */
194#define CF_INTERNAL 0x020 /* An internal inetd service */ 201#define CF_INTERNAL 0x020 /* An internal inetd service */
195#define CF_SOCKENV 0x040 /* Component wants socket information in 202#define CF_SOCKENV 0x040 /* Component wants socket information in
196 the environment */ 203 the environment */
197#define CF_RESOLVE 0x080 /* Resolve IP addresses */ 204#define CF_RESOLVE 0x080 /* Resolve IP addresses */
198#define CF_SIGGROUP 0x100 /* Send signals to the process group */ 205#define CF_SIGGROUP 0x100 /* Send signals to the process group */
199 206
@@ -210,9 +217,9 @@ struct component
210 struct component *prev, *next; /* Components form doubly-linked list. */ 217 struct component *prev, *next; /* Components form doubly-linked list. */
211 int listidx; /* Index of the list. */ 218 int listidx; /* Index of the list. */
212 size_t arridx; /* Index of this component. */ 219 size_t arridx; /* Index of this component. */
213 size_t ref_count; /* Reference count. */ 220 size_t ref_count; /* Reference count. */
214 struct prog *prog; /* Prog associated with this component. */ 221 struct prog *prog; /* Prog associated with this component. */
215 222
216 enum pies_comp_mode mode; 223 enum pies_comp_mode mode;
217 char *tag; /* Entry tag (for diagnostics purposes) */ 224 char *tag; /* Entry tag (for diagnostics purposes) */
218 char *program; /* Program name */ 225 char *program; /* Program name */
@@ -232,7 +239,7 @@ struct component
232 239
233 /* For exec (init) components */ 240 /* For exec (init) components */
234 char *runlevels; 241 char *runlevels;
235 242
236 /* For inetd components */ 243 /* For inetd components */
237 size_t max_rate; /* Maximum number of invocations per minute */ 244 size_t max_rate; /* Maximum number of invocations per minute */
238 size_t max_ip_connections; /* Max. number of connections per IP address */ 245 size_t max_ip_connections; /* Max. number of connections per IP address */
@@ -253,9 +260,9 @@ struct component
253 char *access_denied_message; 260 char *access_denied_message;
254 char *max_instances_message; 261 char *max_instances_message;
255 char *max_ip_connections_message; 262 char *max_ip_connections_message;
256 263
257 /* Redirectors: */ 264 /* Redirectors: */
258 int facility; /* Syslog facility. */ 265 int facility; /* Syslog facility. */
259 struct redirector redir[2]; /* Repeaters for stdout and stderr */ 266 struct redirector redir[2]; /* Repeaters for stdout and stderr */
260 /* Actions to execute on various exit codes: */ 267 /* Actions to execute on various exit codes: */
261 struct grecs_list *act_list; 268 struct grecs_list *act_list;
@@ -334,6 +341,7 @@ int pies_read_config (void);
334int pies_reread_config (void); 341int pies_reread_config (void);
335 342
336void register_prog (struct component *comp); 343void register_prog (struct component *comp);
344void program_init_startup (void);
337int progman_waiting_p (void); 345int progman_waiting_p (void);
338void progman_start (void); 346void progman_start (void);
339void progman_gc (void); 347void progman_gc (void);
@@ -594,7 +602,7 @@ struct sysvinit_request
594#define SYSV_ACCT_BOOT 0 602#define SYSV_ACCT_BOOT 0
595#define SYSV_ACCT_RUNLEVEL 1 603#define SYSV_ACCT_RUNLEVEL 1
596#define SYSV_ACCT_PROC_START 2 604#define SYSV_ACCT_PROC_START 2
597 #define SYSV_ACCT_PROC_STOP 3 605#define SYSV_ACCT_PROC_STOP 3
598 606
599void sysvinit_acct (int what, const char *user, const char *id, pid_t pid, 607void sysvinit_acct (int what, const char *user, const char *id, pid_t pid,
600 const char *line); 608 const char *line);
diff --git a/src/progman.c b/src/progman.c
index 1b09cd5..5bc4eb3 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -65,7 +65,7 @@ progman_lookup_component (const char *tag)
65 if (IS_COMPONENT (prog) && strcmp (prog_tag (prog), tag) == 0) 65 if (IS_COMPONENT (prog) && strcmp (prog_tag (prog), tag) == 0)
66 return prog->v.p.comp; 66 return prog->v.p.comp;
67 return NULL; 67 return NULL;
68} 68}
69 69
70struct component * 70struct component *
71progman_lookup_tcpmux (const char *service, const char *master) 71progman_lookup_tcpmux (const char *service, const char *master)
@@ -122,7 +122,7 @@ link_prog (struct prog *prog, struct prog *ref)
122 122
123 prog->prev = ref; 123 prog->prev = ref;
124 prog->next = ref->next; 124 prog->next = ref->next;
125 125
126 if ((x = ref->next)) 126 if ((x = ref->next))
127 x->prev = prog; 127 x->prev = prog;
128 else 128 else
@@ -151,21 +151,21 @@ void
151destroy_prog (struct prog **pp) 151destroy_prog (struct prog **pp)
152{ 152{
153 struct prog *p = *pp; 153 struct prog *p = *pp;
154 154
155 unlink_prog (p); 155 unlink_prog (p);
156 switch (p->type) 156 switch (p->type)
157 { 157 {
158 case TYPE_COMPONENT: 158 case TYPE_COMPONENT:
159 component_ref_decr (p->v.p.comp); 159 component_ref_decr (p->v.p.comp);
160 if (p->v.p.status == status_listener && p->v.p.socket != -1) 160 if (p->v.p.status == status_listener && p->v.p.socket != -1)
161 deregister_socket (p->v.p.socket); 161 deregister_socket (p->v.p.socket);
162 /* FIXME: Remove also all dependent progs (esp. tcpmux) */ 162 /* FIXME: Remove also all dependent progs (esp. tcpmux) */
163 if (p->v.p.redir[RETR_OUT]) 163 if (p->v.p.redir[RETR_OUT])
164 p->v.p.redir[RETR_OUT]->v.r.master = NULL; 164 p->v.p.redir[RETR_OUT]->v.r.master = NULL;
165 if (p->v.p.redir[RETR_ERR]) 165 if (p->v.p.redir[RETR_ERR])
166 p->v.p.redir[RETR_ERR]->v.r.master = NULL; 166 p->v.p.redir[RETR_ERR]->v.r.master = NULL;
167 break; 167 break;
168 168
169 case TYPE_REDIRECTOR: 169 case TYPE_REDIRECTOR:
170 { 170 {
171 struct prog *master = p->v.r.master; 171 struct prog *master = p->v.r.master;
@@ -182,7 +182,7 @@ destroy_prog (struct prog **pp)
182 free (p->v.r.tag); 182 free (p->v.r.tag);
183 } 183 }
184 break; 184 break;
185 185
186 case TYPE_COMMAND: 186 case TYPE_COMMAND:
187 free (p->v.c.tag); 187 free (p->v.c.tag);
188 free (p->v.c.command); 188 free (p->v.c.command);
@@ -256,7 +256,7 @@ find_prog_ref (struct component *comp)
256 if (!comp) 256 if (!comp)
257 return NULL; /* FIXME: Skip redirectors? */ 257 return NULL; /* FIXME: Skip redirectors? */
258 } 258 }
259 259
260 if (comp->prog) 260 if (comp->prog)
261 { 261 {
262 for (prog = comp->prog; 262 for (prog = comp->prog;
@@ -270,12 +270,12 @@ find_prog_ref (struct component *comp)
270 prog = NULL; 270 prog = NULL;
271 return prog; 271 return prog;
272} 272}
273 273
274static struct prog * 274static struct prog *
275register_prog0 (struct component *comp) 275register_prog0 (struct component *comp)
276{ 276{
277 struct prog *newp; 277 struct prog *newp;
278 278
279 newp = grecs_zalloc (sizeof (*newp)); 279 newp = grecs_zalloc (sizeof (*newp));
280 newp->type = TYPE_COMPONENT; 280 newp->type = TYPE_COMPONENT;
281 newp->pid = 0; 281 newp->pid = 0;
@@ -291,7 +291,7 @@ register_prog0 (struct component *comp)
291 newp->active = 0; 291 newp->active = 0;
292 else 292 else
293 newp->active = 1; 293 newp->active = 1;
294 294
295 if (comp->mode != pies_comp_exec) 295 if (comp->mode != pies_comp_exec)
296 comp->redir[RETR_OUT].type = redir_null; 296 comp->redir[RETR_OUT].type = redir_null;
297 297
@@ -317,14 +317,29 @@ register_command (char *tag, char *command, pid_t pid)
317 link_prog (newp, progtail); 317 link_prog (newp, progtail);
318} 318}
319 319
320static inline int
321progman_startup_phase (void)
322{
323 struct prog *prog;
324
325 for (prog = proghead; prog; prog = prog->next)
326 {
327 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
328 return 1;
329 }
330 return 0;
331}
332
320int 333int
321progman_waiting_p (void) 334progman_waiting_p (void)
322{ 335{
323 struct prog *prog; 336 struct prog *prog;
324 337
325 for (prog = proghead; prog; prog = prog->next) 338 for (prog = proghead; prog; prog = prog->next)
326 { 339 {
327 if (IS_COMPONENT (prog) && prog->wait && prog->pid > 0) 340 if (IS_COMPONENT (prog)
341 && prog->pid > 0
342 && (prog->wait || prog->v.p.comp->mode == pies_comp_startup))
328 { 343 {
329 debug (3, ("%s: waiting for %s (%lu)", 344 debug (3, ("%s: waiting for %s (%lu)",
330 __FUNCTION__, prog_tag (prog), 345 __FUNCTION__, prog_tag (prog),
@@ -406,17 +421,17 @@ open_redirector (struct prog *master, int stream)
406 421
407 case redir_file: 422 case redir_file:
408 return redirect_to_file (master, stream); 423 return redirect_to_file (master, stream);
409 424
410 case redir_syslog: 425 case redir_syslog:
411 break; 426 break;
412 } 427 }
413 428
414 if (pipe (p)) 429 if (pipe (p))
415 { 430 {
416 logmsg (LOG_CRIT, "pipe: %s", strerror (errno)); 431 logmsg (LOG_CRIT, "pipe: %s", strerror (errno));
417 return -1; 432 return -1;
418 } 433 }
419 434
420 switch (pid = fork ()) 435 switch (pid = fork ())
421 { 436 {
422 case 0: 437 case 0:
@@ -428,10 +443,10 @@ open_redirector (struct prog *master, int stream)
428 FD_ZERO (&fdset); 443 FD_ZERO (&fdset);
429 FD_SET (p[0], &fdset); 444 FD_SET (p[0], &fdset);
430 close_fds (&fdset); 445 close_fds (&fdset);
431 446
432 diag_setup (0); 447 diag_setup (0);
433 signal_setup (redir_exit); 448 signal_setup (redir_exit);
434 449
435 close (p[1]); 450 close (p[1]);
436 fp = fdopen (p[0], "r"); 451 fp = fdopen (p[0], "r");
437 if (fp == NULL) 452 if (fp == NULL)
@@ -441,7 +456,7 @@ open_redirector (struct prog *master, int stream)
441 while (getline (&buf, &size, fp) > 0) 456 while (getline (&buf, &size, fp) > 0)
442 syslog (prio, "%s", buf); 457 syslog (prio, "%s", buf);
443 _exit (0); 458 _exit (0);
444 459
445 case -1: 460 case -1:
446 logmsg (LOG_CRIT, 461 logmsg (LOG_CRIT,
447 _("cannot run redirector `%s': fork failed: %s"), 462 _("cannot run redirector `%s': fork failed: %s"),
@@ -466,7 +481,7 @@ conn_class_hasher (void *data, unsigned long n_buckets)
466 size_t value = 0; 481 size_t value = 0;
467 unsigned char ch; 482 unsigned char ch;
468 size_t len; 483 size_t len;
469 484
470 while ((ch = *tag++)) 485 while ((ch = *tag++))
471 value = (value * 31 + ch) % n_buckets; 486 value = (value * 31 + ch) % n_buckets;
472 487
@@ -530,7 +545,7 @@ conn_class_lookup (const char *tag,
530 probe->sa_storage.s.sa_family); 545 probe->sa_storage.s.sa_family);
531 break; 546 break;
532 } 547 }
533 548
534 probe->count = 0; 549 probe->count = 0;
535 if (!conn_tab) 550 if (!conn_tab)
536 { 551 {
@@ -725,7 +740,7 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
725{ 740{
726 char *res; 741 char *res;
727 size_t len; 742 size_t len;
728 743
729 if (a && b) 744 if (a && b)
730 { 745 {
731 res = grecs_malloc (namelen + 1 + strlen (a) + strlen (b) + 1); 746 res = grecs_malloc (namelen + 1 + strlen (a) + strlen (b) + 1);
@@ -753,14 +768,14 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
753 res[namelen] = '='; 768 res[namelen] = '=';
754 return res; 769 return res;
755} 770}
756 771
757static void 772static void
758environ_setup (char **hint) 773environ_setup (char **hint)
759{ 774{
760 char **old_env = environ; 775 char **old_env = environ;
761 char **new_env; 776 char **new_env;
762 size_t count, i, j, n; 777 size_t count, i, j, n;
763 778
764 if (!hint) 779 if (!hint)
765 return; 780 return;
766 781
@@ -769,22 +784,22 @@ environ_setup (char **hint)
769 old_env = NULL; 784 old_env = NULL;
770 hint++; 785 hint++;
771 } 786 }
772 787
773 /* Count new environment size */ 788 /* Count new environment size */
774 count = 0; 789 count = 0;
775 if (old_env) 790 if (old_env)
776 for (i = 0; old_env[i]; i++) 791 for (i = 0; old_env[i]; i++)
777 count++; 792 count++;
778 793
779 for (i = 0; hint[i]; i++) 794 for (i = 0; hint[i]; i++)
780 count++; 795 count++;
781 796
782 /* Allocate new environment. */ 797 /* Allocate new environment. */
783 new_env = grecs_calloc (count + 1, sizeof new_env[0]); 798 new_env = grecs_calloc (count + 1, sizeof new_env[0]);
784 799
785 /* Populate the environment. */ 800 /* Populate the environment. */
786 n = 0; 801 n = 0;
787 802
788 if (old_env) 803 if (old_env)
789 for (i = 0; old_env[i]; i++) 804 for (i = 0; old_env[i]; i++)
790 { 805 {
@@ -795,7 +810,7 @@ environ_setup (char **hint)
795 for (i = 0; hint[i]; i++) 810 for (i = 0; hint[i]; i++)
796 { 811 {
797 char *p; 812 char *p;
798 813
799 if (hint[i][0] == '-') 814 if (hint[i][0] == '-')
800 { 815 {
801 /* Skip unset directives. */ 816 /* Skip unset directives. */
@@ -806,12 +821,12 @@ environ_setup (char **hint)
806 slot if there's no such variable in new_env */ 821 slot if there's no such variable in new_env */
807 if (find_env_pos (new_env, hint[i], &j, NULL)) 822 if (find_env_pos (new_env, hint[i], &j, NULL))
808 j = n; 823 j = n;
809 824
810 if ((p = strchr (hint[i], '='))) 825 if ((p = strchr (hint[i], '=')))
811 { 826 {
812 if (p == hint[i]) 827 if (p == hint[i])
813 continue; /* Ignore erroneous entry */ 828 continue; /* Ignore erroneous entry */
814 if (p[-1] == '+') 829 if (p[-1] == '+')
815 new_env[j] = env_concat (hint[i], p - hint[i] - 1, 830 new_env[j] = env_concat (hint[i], p - hint[i] - 1,
816 find_env_ptr (environ, hint[i], 1), 831 find_env_ptr (environ, hint[i], 1),
817 p + 1); 832 p + 1);
@@ -835,7 +850,7 @@ environ_setup (char **hint)
835 850
836 if (envsize) 851 if (envsize)
837 free (environ); 852 free (environ);
838 853
839 environ = new_env; 854 environ = new_env;
840 envsize = count + 1; 855 envsize = count + 1;
841} 856}
@@ -852,14 +867,14 @@ prog_sockenv (struct prog *prog)
852 union pies_sockaddr_storage *sa_client = &prog->v.p.sa_storage; 867 union pies_sockaddr_storage *sa_client = &prog->v.p.sa_storage;
853 socklen_t cltlen = prog->v.p.sa_len; 868 socklen_t cltlen = prog->v.p.sa_len;
854 const char *proto = NULL; 869 const char *proto = NULL;
855 870
856 if (!(prog->v.p.comp->flags & CF_SOCKENV)) 871 if (!(prog->v.p.comp->flags & CF_SOCKENV))
857 return; 872 return;
858 873
859 if (socket_type_to_str (prog->v.p.comp->socket_type, &proto)) 874 if (socket_type_to_str (prog->v.p.comp->socket_type, &proto))
860 proto = umaxtostr (prog->v.p.comp->socket_type, buf); 875 proto = umaxtostr (prog->v.p.comp->socket_type, buf);
861 add_env (ENV_SOCKTYPE, proto); 876 add_env (ENV_SOCKTYPE, proto);
862 877
863 if (prog->v.p.comp->socket_url) 878 if (prog->v.p.comp->socket_url)
864 proto = prog->v.p.comp->socket_url->proto_s; 879 proto = prog->v.p.comp->socket_url->proto_s;
865 else if (prog->v.p.listener) 880 else if (prog->v.p.listener)
@@ -868,7 +883,7 @@ prog_sockenv (struct prog *prog)
868 proto = "TCP"; 883 proto = "TCP";
869 884
870 add_env (ENV_PROTO, proto); 885 add_env (ENV_PROTO, proto);
871 886
872 if (getsockname (prog->v.p.socket, 887 if (getsockname (prog->v.p.socket,
873 (struct sockaddr *) &sa_server, &len) < 0) 888 (struct sockaddr *) &sa_server, &len) < 0)
874 logmsg (LOG_WARNING, "getsockname(): %s", strerror (errno)); 889 logmsg (LOG_WARNING, "getsockname(): %s", strerror (errno));
@@ -920,7 +935,7 @@ static int
920check_rate (struct prog *prog, unsigned testtime, size_t max_count) 935check_rate (struct prog *prog, unsigned testtime, size_t max_count)
921{ 936{
922 time_t now; 937 time_t now;
923 938
924 time (&now); 939 time (&now);
925 940
926 if (prog->v.p.timestamp + testtime > now) 941 if (prog->v.p.timestamp + testtime > now)
@@ -930,7 +945,7 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
930 prog->v.p.failcount = 0; 945 prog->v.p.failcount = 0;
931 prog->v.p.timestamp = now; 946 prog->v.p.timestamp = now;
932 } 947 }
933 948
934 if (prog->v.p.failcount > max_count) 949 if (prog->v.p.failcount > max_count)
935 { 950 {
936 prog->v.p.timestamp = now; 951 prog->v.p.timestamp = now;
@@ -938,7 +953,7 @@ check_rate (struct prog *prog, unsigned testtime, size_t max_count)
938 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM); 953 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
939 return 1; 954 return 1;
940 } 955 }
941 956
942 return 0; 957 return 0;
943} 958}
944 959
@@ -961,7 +976,7 @@ static int
961check_connection_rate (struct prog *prog) 976check_connection_rate (struct prog *prog)
962{ 977{
963 size_t max_rate = prog->v.p.comp->max_rate 978 size_t max_rate = prog->v.p.comp->max_rate
964 ? prog->v.p.comp->max_rate : default_max_rate; 979 ? prog->v.p.comp->max_rate : default_max_rate;
965 if (max_rate && check_rate (prog, 60, max_rate)) 980 if (max_rate && check_rate (prog, 60, max_rate))
966 { 981 {
967 logmsg (LOG_NOTICE, 982 logmsg (LOG_NOTICE,
@@ -1009,7 +1024,7 @@ prog_start_prologue (struct prog *prog)
1009 logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"), 1024 logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"),
1010 prog_tag (prog), prog->v.p.comp->dir, strerror (errno)); 1025 prog_tag (prog), prog->v.p.comp->dir, strerror (errno));
1011 } 1026 }
1012 1027
1013 environ_setup (prog->v.p.comp->env ? 1028 environ_setup (prog->v.p.comp->env ?
1014 prog->v.p.comp->env : 1029 prog->v.p.comp->env :
1015 ((prog->v.p.comp->flags & CF_SOCKENV) ? sockenv_hint : NULL)); 1030 ((prog->v.p.comp->flags & CF_SOCKENV) ? sockenv_hint : NULL));
@@ -1020,16 +1035,16 @@ prog_start_prologue (struct prog *prog)
1020 pies_priv_setup (&prog->v.p.comp->privs); 1035 pies_priv_setup (&prog->v.p.comp->privs);
1021 if (prog->v.p.comp->umask) 1036 if (prog->v.p.comp->umask)
1022 umask (prog->v.p.comp->umask); 1037 umask (prog->v.p.comp->umask);
1023 1038
1024 set_limits (prog_tag (prog), 1039 set_limits (prog_tag (prog),
1025 prog->v.p.comp->limits ? 1040 prog->v.p.comp->limits ?
1026 prog->v.p.comp->limits : pies_limits); 1041 prog->v.p.comp->limits : pies_limits);
1027 1042
1028 if (debug_level >= 1) 1043 if (debug_level >= 1)
1029 { 1044 {
1030 int i; 1045 int i;
1031 struct component *comp = prog->v.p.comp; 1046 struct component *comp = prog->v.p.comp;
1032 1047
1033 logmsg_printf (LOG_DEBUG, "executing"); 1048 logmsg_printf (LOG_DEBUG, "executing");
1034 for (i = 0; i < comp->argc; i++) 1049 for (i = 0; i < comp->argc; i++)
1035 logmsg_printf (LOG_DEBUG, " %s", quotearg (comp->argv[i])); 1050 logmsg_printf (LOG_DEBUG, " %s", quotearg (comp->argv[i]));
@@ -1047,7 +1062,7 @@ prog_execute (struct prog *prog)
1047 prog->v.p.comp->builtin->fun (0, prog->v.p.comp); 1062 prog->v.p.comp->builtin->fun (0, prog->v.p.comp);
1048 _exit (0); 1063 _exit (0);
1049 } 1064 }
1050 1065
1051 execvp (prog->v.p.comp->program ? 1066 execvp (prog->v.p.comp->program ?
1052 prog->v.p.comp->program : prog->v.p.comp->argv[0], 1067 prog->v.p.comp->program : prog->v.p.comp->argv[0],
1053 prog->v.p.comp->argv); 1068 prog->v.p.comp->argv);
@@ -1077,7 +1092,7 @@ prog_start (struct prog *prog)
1077 pid_t pid; 1092 pid_t pid;
1078 int redir[2]; 1093 int redir[2];
1079 fd_set fdset; 1094 fd_set fdset;
1080 1095
1081 if (prog->pid > 0 || !IS_COMPONENT (prog)) 1096 if (prog->pid > 0 || !IS_COMPONENT (prog))
1082 return; 1097 return;
1083 1098
@@ -1123,7 +1138,7 @@ prog_start (struct prog *prog)
1123 if (prog_open_socket (prog)) 1138 if (prog_open_socket (prog))
1124 return; 1139 return;
1125 break; 1140 break;
1126 1141
1127 case pies_comp_accept: 1142 case pies_comp_accept:
1128 if (check_spawn_rate (prog)) 1143 if (check_spawn_rate (prog))
1129 return; 1144 return;
@@ -1139,9 +1154,9 @@ prog_start (struct prog *prog)
1139 default: 1154 default:
1140 break; 1155 break;
1141 } 1156 }
1142 1157
1143 debug (1, (_("starting %s"), prog_tag (prog))); 1158 debug (1, (_("starting %s"), prog_tag (prog)));
1144 1159
1145 if (prog->v.p.comp->rmfile) 1160 if (prog->v.p.comp->rmfile)
1146 { 1161 {
1147 debug (1, (_("unlinking %s"), prog->v.p.comp->rmfile)); 1162 debug (1, (_("unlinking %s"), prog->v.p.comp->rmfile));
@@ -1158,7 +1173,7 @@ prog_start (struct prog *prog)
1158 1173
1159 redir[RETR_OUT] = open_redirector (prog, RETR_OUT); 1174 redir[RETR_OUT] = open_redirector (prog, RETR_OUT);
1160 redir[RETR_ERR] = open_redirector (prog, RETR_ERR); 1175 redir[RETR_ERR] = open_redirector (prog, RETR_ERR);
1161 1176
1162 switch (pid = fork ()) 1177 switch (pid = fork ())
1163 { 1178 {
1164 /* The child branch. */ 1179 /* The child branch. */
@@ -1167,22 +1182,22 @@ prog_start (struct prog *prog)
1167 setsid (); 1182 setsid ();
1168 prog_start_prologue (prog); 1183 prog_start_prologue (prog);
1169 switch (prog->v.p.comp->mode) 1184 switch (prog->v.p.comp->mode)
1170 { 1185 {
1171 case pies_comp_accept: 1186 case pies_comp_accept:
1172 case pies_comp_inetd: 1187 case pies_comp_inetd:
1173 prog_sockenv (prog); 1188 prog_sockenv (prog);
1174 1189
1175 dup2 (prog->v.p.socket, 0); 1190 dup2 (prog->v.p.socket, 0);
1176 dup2 (prog->v.p.socket, 1); 1191 dup2 (prog->v.p.socket, 1);
1177 close (prog->v.p.socket); 1192 close (prog->v.p.socket);
1178 prog->v.p.socket = -1; 1193 prog->v.p.socket = -1;
1179 break; 1194 break;
1180 1195
1181 default: 1196 default:
1182 if (init_process) 1197 if (init_process)
1183 { 1198 {
1184 int fd = console_open (O_RDWR|O_NOCTTY); 1199 int fd = console_open (O_RDWR|O_NOCTTY);
1185 if (fd < 0) 1200 if (fd < 0)
1186 { 1201 {
1187 logmsg (LOG_CRIT, "open(%s): %s", 1202 logmsg (LOG_CRIT, "open(%s): %s",
1188 console_device, strerror (errno)); 1203 console_device, strerror (errno));
@@ -1218,8 +1233,8 @@ prog_start (struct prog *prog)
1218 dup2 (redir[RETR_OUT], 1); 1233 dup2 (redir[RETR_OUT], 1);
1219 } 1234 }
1220 } 1235 }
1221 break; 1236 break;
1222 } 1237 }
1223 1238
1224 if (!init_process) 1239 if (!init_process)
1225 { 1240 {
@@ -1236,7 +1251,7 @@ prog_start (struct prog *prog)
1236 dup2 (redir[RETR_ERR], 2); 1251 dup2 (redir[RETR_ERR], 2);
1237 } 1252 }
1238 } 1253 }
1239 1254
1240 /* Close unneeded descripitors */ 1255 /* Close unneeded descripitors */
1241 FD_ZERO (&fdset); 1256 FD_ZERO (&fdset);
1242 FD_SET (0, &fdset); 1257 FD_SET (0, &fdset);
@@ -1247,8 +1262,8 @@ prog_start (struct prog *prog)
1247 close_fds (&fdset); 1262 close_fds (&fdset);
1248 1263
1249 prog_execute (prog); 1264 prog_execute (prog);
1250 1265
1251 1266
1252 case -1: 1267 case -1:
1253 logmsg (LOG_CRIT, 1268 logmsg (LOG_CRIT,
1254 _("cannot run `%s': fork failed: %s"), 1269 _("cannot run `%s': fork failed: %s"),
@@ -1291,14 +1306,14 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
1291{ 1306{
1292 struct acl_input input; 1307 struct acl_input input;
1293 int rc; 1308 int rc;
1294 1309
1295 if (!acl) 1310 if (!acl)
1296 return 0; 1311 return 0;
1297 1312
1298 input.addr = s; 1313 input.addr = s;
1299 input.addrlen = salen; 1314 input.addrlen = salen;
1300 input.identity = identity; 1315 input.identity = identity;
1301 1316
1302 rc = pies_acl_check (acl, &input, 1); 1317 rc = pies_acl_check (acl, &input, 1);
1303 if (rc == 0) 1318 if (rc == 0)
1304 { 1319 {
@@ -1315,7 +1330,7 @@ void
1315fd_report (int fd, const char *msg) 1330fd_report (int fd, const char *msg)
1316{ 1331{
1317 size_t len; 1332 size_t len;
1318 1333
1319 if (!msg) 1334 if (!msg)
1320 return; 1335 return;
1321 1336
@@ -1334,7 +1349,7 @@ fd_report (int fd, const char *msg)
1334 len -= rc; 1349 len -= rc;
1335 msg += rc; 1350 msg += rc;
1336 } 1351 }
1337} 1352}
1338 1353
1339static int 1354static int
1340_prog_accept (struct prog *p) 1355_prog_accept (struct prog *p)
@@ -1344,14 +1359,14 @@ _prog_accept (struct prog *p)
1344 union pies_sockaddr_storage addr; 1359 union pies_sockaddr_storage addr;
1345 socklen_t addrlen = sizeof addr; 1360 socklen_t addrlen = sizeof addr;
1346 struct conn_class *pcclass; 1361 struct conn_class *pcclass;
1347 1362
1348 fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen); 1363 fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen);
1349 if (fd == -1) 1364 if (fd == -1)
1350 { 1365 {
1351 logfuncall ("accept", NULL, errno); 1366 logfuncall ("accept", NULL, errno);
1352 return 1; 1367 return 1;
1353 } 1368 }
1354 1369
1355 if (debug_level >= 1) 1370 if (debug_level >= 1)
1356 { 1371 {
1357 char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen); 1372 char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
@@ -1394,7 +1409,7 @@ _prog_accept (struct prog *p)
1394 close (fd); 1409 close (fd);
1395 return 1; 1410 return 1;
1396 } 1411 }
1397 1412
1398 if (check_connection_rate (p)) 1413 if (check_connection_rate (p))
1399 { 1414 {
1400 disable_socket (p->v.p.socket); 1415 disable_socket (p->v.p.socket);
@@ -1447,7 +1462,7 @@ _prog_wait (struct prog *p)
1447 p->v.p.num_instances++; 1462 p->v.p.num_instances++;
1448 return 0; 1463 return 0;
1449} 1464}
1450 1465
1451int 1466int
1452progman_accept (int socket, void *data) 1467progman_accept (int socket, void *data)
1453{ 1468{
@@ -1456,7 +1471,7 @@ progman_accept (int socket, void *data)
1456 if (p->v.p.comp->socket_type == SOCK_STREAM 1471 if (p->v.p.comp->socket_type == SOCK_STREAM
1457 && !(p->v.p.comp->flags & CF_WAIT)) 1472 && !(p->v.p.comp->flags & CF_WAIT))
1458 return _prog_accept (p); 1473 return _prog_accept (p);
1459 1474
1460 return _prog_wait (p); 1475 return _prog_wait (p);
1461} 1476}
1462 1477
@@ -1526,14 +1541,34 @@ progman_recompute_alarm (void)
1526} 1541}
1527 1542
1528void 1543void
1544program_init_startup (void)
1545{
1546 struct prog *prog;
1547
1548 for (prog = proghead; prog; prog = prog->next)
1549 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
1550 {
1551 debug (1, ("running startup components"));
1552 break;
1553 }
1554
1555 for (; prog; prog = prog->next)
1556 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
1557 {
1558 prog_start (prog);
1559 }
1560}
1561
1562void
1529progman_start (void) 1563progman_start (void)
1530{ 1564{
1531 struct prog *prog; 1565 struct prog *prog;
1532 1566
1533 if (progman_waiting_p ()) 1567 if (progman_waiting_p ())
1534 /* Noting to do if there are processes left in the previous runlevel */ 1568 /* Noting to do if there are processes left in the previous runlevel
1569 (in sysv-init mode) or startup components running. */
1535 return; 1570 return;
1536 1571
1537 debug (1, ("starting components")); 1572 debug (1, ("starting components"));
1538 for (prog = proghead; prog; prog = prog->next) 1573 for (prog = proghead; prog; prog = prog->next)
1539 if (IS_COMPONENT (prog)) 1574 if (IS_COMPONENT (prog))
@@ -1565,8 +1600,8 @@ check_stopping (struct prog *prog, time_t now)
1565 if (now - prog->v.p.timestamp >= shutdown_timeout) 1600 if (now - prog->v.p.timestamp >= shutdown_timeout)
1566 { 1601 {
1567 if (prog->pid == 0) 1602 if (prog->pid == 0)
1568 logmsg (LOG_EMERG, 1603 logmsg (LOG_EMERG,
1569 _("INTERNAL ERROR: attempting to kill unexisting process %s"), 1604 _("INTERNAL ERROR: attempting to kill unexisting process %s"),
1570 prog_tag (prog)); 1605 prog_tag (prog));
1571 else if (prog->v.p.comp->flags & CF_SIGGROUP) 1606 else if (prog->v.p.comp->flags & CF_SIGGROUP)
1572 kill (-prog->pid, SIGKILL); 1607 kill (-prog->pid, SIGKILL);
@@ -1625,7 +1660,7 @@ progman_wake_sleeping (int onalrm)
1625 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM); 1660 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
1626 } 1661 }
1627 break; 1662 break;
1628 1663
1629 case status_stopping: 1664 case status_stopping:
1630 check_stopping (prog, now); 1665 check_stopping (prog, now);
1631 break; 1666 break;
@@ -1634,7 +1669,7 @@ progman_wake_sleeping (int onalrm)
1634 if (IS_ACTIVE_COMPONENT (prog)) 1669 if (IS_ACTIVE_COMPONENT (prog))
1635 prog_start (prog); 1670 prog_start (prog);
1636 break; 1671 break;
1637 1672
1638 default: 1673 default:
1639 break; 1674 break;
1640 } 1675 }
@@ -1647,7 +1682,7 @@ prog_start_prerequisites (struct prog *prog)
1647 pies_depmap_pos_t pos; 1682 pies_depmap_pos_t pos;
1648 struct component *comp; 1683 struct component *comp;
1649 int warned = 0; 1684 int warned = 0;
1650 1685
1651 if (!prog->active) 1686 if (!prog->active)
1652 return 1; 1687 return 1;
1653 for (comp = component_depmap_first (depmap_col, prog->v.p.comp->arridx, &pos); 1688 for (comp = component_depmap_first (depmap_col, prog->v.p.comp->arridx, &pos);
@@ -1655,7 +1690,7 @@ prog_start_prerequisites (struct prog *prog)
1655 comp = component_depmap_next (pos)) 1690 comp = component_depmap_next (pos))
1656 { 1691 {
1657 struct prog *p; 1692 struct prog *p;
1658 1693
1659 if (!comp->prog || comp->flags & CF_PRECIOUS) 1694 if (!comp->prog || comp->flags & CF_PRECIOUS)
1660 continue; 1695 continue;
1661 if (!warned) 1696 if (!warned)
@@ -1669,16 +1704,16 @@ prog_start_prerequisites (struct prog *prog)
1669 prog->active = 0; 1704 prog->active = 0;
1670 return 1; 1705 return 1;
1671 } 1706 }
1672 1707
1673 p = comp->prog; 1708 p = comp->prog;
1674 switch (p->v.p.status) 1709 switch (p->v.p.status)
1675 { 1710 {
1676 case status_running: 1711 case status_running:
1677 continue; 1712 continue;
1678 1713
1679 case status_stopped: 1714 case status_stopped:
1680 break; 1715 break;
1681 1716
1682 case status_listener: 1717 case status_listener:
1683 continue; 1718 continue;
1684 1719
@@ -1700,7 +1735,7 @@ prog_start_prerequisites (struct prog *prog)
1700 ret = 1; 1735 ret = 1;
1701 } 1736 }
1702 depmap_end (pos); 1737 depmap_end (pos);
1703 1738
1704 return ret; 1739 return ret;
1705} 1740}
1706 1741
@@ -1757,7 +1792,7 @@ prog_stop (struct prog *prog, int sig)
1757 kill (-prog->pid, sig); 1792 kill (-prog->pid, sig);
1758 else 1793 else
1759 kill (prog->pid, sig); 1794 kill (prog->pid, sig);
1760} 1795}
1761 1796
1762static int 1797static int
1763mark_for_stopping (struct prog *prog, void *data) 1798mark_for_stopping (struct prog *prog, void *data)
@@ -1787,7 +1822,7 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
1787 } 1822 }
1788 else 1823 else
1789 prio = LOG_ERR; 1824 prio = LOG_ERR;
1790 1825
1791 if (WIFEXITED (status)) 1826 if (WIFEXITED (status))
1792 { 1827 {
1793 if (WEXITSTATUS (status) == 0) 1828 if (WEXITSTATUS (status) == 0)
@@ -1801,7 +1836,7 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
1801 else if (WIFSIGNALED (status)) 1836 else if (WIFSIGNALED (status))
1802 { 1837 {
1803 char const *coremsg = ""; 1838 char const *coremsg = "";
1804 1839
1805 if (expect_term && WTERMSIG (status) == SIGTERM) 1840 if (expect_term && WTERMSIG (status) == SIGTERM)
1806 prio = LOG_DEBUG; 1841 prio = LOG_DEBUG;
1807 1842
@@ -1823,7 +1858,7 @@ print_status (const char *tag, pid_t pid, int status, int expect_term)
1823} 1858}
1824 1859
1825static void propagate_child_exit (pid_t) ATTRIBUTE_NORETURN; 1860static void propagate_child_exit (pid_t) ATTRIBUTE_NORETURN;
1826 1861
1827static void 1862static void
1828propagate_child_exit (pid_t pid) 1863propagate_child_exit (pid_t pid)
1829{ 1864{
@@ -1855,7 +1890,7 @@ wordsplit_string (struct wordsplit const *ws)
1855 char **argv = grecs_calloc (count, sizeof (argv[0])); 1890 char **argv = grecs_calloc (count, sizeof (argv[0]));
1856 size_t i; 1891 size_t i;
1857 size_t len = 0; 1892 size_t len = 0;
1858 1893
1859 for (i = 0; i < count; i++) 1894 for (i = 0; i < count; i++)
1860 { 1895 {
1861 argv[i] = quotearg_n (i, ws->ws_wordv[i]); 1896 argv[i] = quotearg_n (i, ws->ws_wordv[i]);
@@ -1883,7 +1918,7 @@ send_msg (char *rcpts, const char *msg_text)
1883 struct wordsplit ws; 1918 struct wordsplit ws;
1884 int p[2]; 1919 int p[2];
1885 size_t size; 1920 size_t size;
1886 1921
1887 ws.ws_offs = mailer_argc; 1922 ws.ws_offs = mailer_argc;
1888 ws.ws_delim = ","; 1923 ws.ws_delim = ",";
1889 if (wordsplit (rcpts, &ws, 1924 if (wordsplit (rcpts, &ws,
@@ -1896,7 +1931,7 @@ send_msg (char *rcpts, const char *msg_text)
1896 } 1931 }
1897 1932
1898 debug (1, (_("sending notification to %s"), rcpts)); 1933 debug (1, (_("sending notification to %s"), rcpts));
1899 1934
1900 /* Copy mailer arguments */ 1935 /* Copy mailer arguments */
1901 for (i = 0; i < mailer_argc; i++) 1936 for (i = 0; i < mailer_argc; i++)
1902 ws.ws_wordv[i] = mailer_argv[i]; 1937 ws.ws_wordv[i] = mailer_argv[i];
@@ -1911,7 +1946,7 @@ send_msg (char *rcpts, const char *msg_text)
1911 { 1946 {
1912 char *arg = ws.ws_wordv[i]; 1947 char *arg = ws.ws_wordv[i];
1913 size_t len; 1948 size_t len;
1914 1949
1915 while (*arg && c_isblank (*arg)) 1950 while (*arg && c_isblank (*arg))
1916 arg++; 1951 arg++;
1917 len = strlen (arg); 1952 len = strlen (arg);
@@ -1934,10 +1969,10 @@ send_msg (char *rcpts, const char *msg_text)
1934 k++; 1969 k++;
1935 } 1970 }
1936 ws.ws_wordv[k] = NULL; 1971 ws.ws_wordv[k] = NULL;
1937 1972
1938 /* Fork a child: */ 1973 /* Fork a child: */
1939 child_pid = fork (); 1974 child_pid = fork ();
1940 1975
1941 if (child_pid < 0) 1976 if (child_pid < 0)
1942 { 1977 {
1943 wordsplit_free (&ws); 1978 wordsplit_free (&ws);
@@ -1955,7 +1990,7 @@ send_msg (char *rcpts, const char *msg_text)
1955 register_command (mailer_program, cmd, child_pid); 1990 register_command (mailer_program, cmd, child_pid);
1956 return; 1991 return;
1957 } 1992 }
1958 1993
1959 /* Child process */ 1994 /* Child process */
1960 /* ============= */ 1995 /* ============= */
1961 signal_setup (SIG_DFL); 1996 signal_setup (SIG_DFL);
@@ -1967,7 +2002,7 @@ send_msg (char *rcpts, const char *msg_text)
1967 wordsplit_free (&ws); 2002 wordsplit_free (&ws);
1968 exit (EX_OSERR); 2003 exit (EX_OSERR);
1969 } 2004 }
1970 2005
1971 grand_child_pid = fork (); 2006 grand_child_pid = fork ();
1972 if (grand_child_pid < 0) 2007 if (grand_child_pid < 0)
1973 { 2008 {
@@ -2030,7 +2065,7 @@ notify_get_tag (char **ret, void *data)
2030 if (!s) 2065 if (!s)
2031 return WRDSE_NOSPACE; 2066 return WRDSE_NOSPACE;
2032 *ret = s; 2067 *ret = s;
2033 return WRDSE_OK; 2068 return WRDSE_OK;
2034} 2069}
2035 2070
2036static int 2071static int
@@ -2039,7 +2074,7 @@ notify_get_termination (char **ret, void *data)
2039 struct notify_closure const *clos = data; 2074 struct notify_closure const *clos = data;
2040 char const *msg; 2075 char const *msg;
2041 char *s; 2076 char *s;
2042 2077
2043 if (WIFEXITED (clos->status)) 2078 if (WIFEXITED (clos->status))
2044 /* TRANSLATORS: The subject of this statement is 'component' */ 2079 /* TRANSLATORS: The subject of this statement is 'component' */
2045 msg = _("exited with code"); 2080 msg = _("exited with code");
@@ -2053,16 +2088,16 @@ notify_get_termination (char **ret, void *data)
2053 if (!s) 2088 if (!s)
2054 return WRDSE_NOSPACE; 2089 return WRDSE_NOSPACE;
2055 *ret = s; 2090 *ret = s;
2056 return WRDSE_OK; 2091 return WRDSE_OK;
2057} 2092}
2058 2093
2059static int 2094static int
2060notify_get_retcode (char **ret, void *data) 2095notify_get_retcode (char **ret, void *data)
2061{ 2096{
2062 struct notify_closure const *clos = data; 2097 struct notify_closure const *clos = data;
2063 char *s = NULL; 2098 char *s = NULL;
2064 size_t l = 0; 2099 size_t l = 0;
2065 2100
2066 if (WIFEXITED (clos->status)) 2101 if (WIFEXITED (clos->status))
2067 grecs_asprintf (&s, &l, "%d", WEXITSTATUS (clos->status)); 2102 grecs_asprintf (&s, &l, "%d", WEXITSTATUS (clos->status));
2068 else if (WIFSIGNALED (clos->status)) 2103 else if (WIFSIGNALED (clos->status))
@@ -2072,9 +2107,9 @@ notify_get_retcode (char **ret, void *data)
2072 if (!s) 2107 if (!s)
2073 return WRDSE_NOSPACE; 2108 return WRDSE_NOSPACE;
2074 *ret = s; 2109 *ret = s;
2075 return WRDSE_OK; 2110 return WRDSE_OK;
2076} 2111}
2077 2112
2078struct notify_variable 2113struct notify_variable
2079{ 2114{
2080 char *name; 2115 char *name;
@@ -2090,7 +2125,7 @@ static struct notify_variable notify_vartab[] = {
2090#undef S 2125#undef S
2091 { NULL } 2126 { NULL }
2092}; 2127};
2093 2128
2094static int 2129static int
2095notify_getvar (char **ret, const char *vptr, size_t vlen, void *data) 2130notify_getvar (char **ret, const char *vptr, size_t vlen, void *data)
2096{ 2131{
@@ -2100,7 +2135,7 @@ notify_getvar (char **ret, const char *vptr, size_t vlen, void *data)
2100 return var->get (ret, data); 2135 return var->get (ret, data);
2101 return WRDSE_UNDEF; 2136 return WRDSE_UNDEF;
2102} 2137}
2103 2138
2104static void 2139static void
2105notify (const char *tag, int status, struct action *act) 2140notify (const char *tag, int status, struct action *act)
2106{ 2141{
@@ -2120,7 +2155,7 @@ notify (const char *tag, int status, struct action *act)
2120 closure.tag = tag; 2155 closure.tag = tag;
2121 closure.status = status; 2156 closure.status = status;
2122 closure.act = act; 2157 closure.act = act;
2123 2158
2124 env[PROGRAM_NAME_IDX] = program_name; 2159 env[PROGRAM_NAME_IDX] = program_name;
2125 env[INSTANCE_IDX] = instance; 2160 env[INSTANCE_IDX] = instance;
2126 2161
@@ -2144,7 +2179,7 @@ static int
2144status_matches_p (struct action *act, unsigned status) 2179status_matches_p (struct action *act, unsigned status)
2145{ 2180{
2146 int i; 2181 int i;
2147 2182
2148 if (act->nstat == 0) 2183 if (act->nstat == 0)
2149 return 1; 2184 return 1;
2150 for (i = 0; i < act->nstat; i++) 2185 for (i = 0; i < act->nstat; i++)
@@ -2184,7 +2219,7 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
2184 setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1); 2219 setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1);
2185 2220
2186 close_fds (NULL); 2221 close_fds (NULL);
2187 2222
2188 argv[0] = "/bin/sh"; 2223 argv[0] = "/bin/sh";
2189 argv[1] = "-c"; 2224 argv[1] = "-c";
2190 argv[2] = act->command; 2225 argv[2] = act->command;
@@ -2208,7 +2243,7 @@ react (struct prog *prog, int status, pid_t pid)
2208 2243
2209 if (!list) 2244 if (!list)
2210 list = default_component.act_list; 2245 list = default_component.act_list;
2211 2246
2212 if (WIFEXITED (status)) 2247 if (WIFEXITED (status))
2213 { 2248 {
2214 retcode = WEXITSTATUS (status); 2249 retcode = WEXITSTATUS (status);
@@ -2233,21 +2268,21 @@ react (struct prog *prog, int status, pid_t pid)
2233 for (ep = list->head; ep; ep = ep->next) 2268 for (ep = list->head; ep; ep = ep->next)
2234 { 2269 {
2235 struct action *act = ep->data; 2270 struct action *act = ep->data;
2236 2271
2237 if (status_matches_p (act, retcode)) 2272 if (status_matches_p (act, retcode))
2238 { 2273 {
2239 if (act->command) 2274 if (act->command)
2240 { 2275 {
2241 run_command (act, prog, retcode, pid); 2276 run_command (act, prog, retcode, pid);
2242 } 2277 }
2243 2278
2244 switch (act->act) 2279 switch (act->act)
2245 { 2280 {
2246 case action_restart: 2281 case action_restart:
2247 if (prog->v.p.comp->mode != pies_comp_inetd) 2282 if (prog->v.p.comp->mode != pies_comp_inetd)
2248 prog_start (prog); 2283 prog_start (prog);
2249 break; 2284 break;
2250 2285
2251 case action_disable: 2286 case action_disable:
2252 logmsg (LOG_NOTICE, _("disabling component %s"), 2287 logmsg (LOG_NOTICE, _("disabling component %s"),
2253 prog_tag (prog)); 2288 prog_tag (prog));
@@ -2263,7 +2298,7 @@ react (struct prog *prog, int status, pid_t pid)
2263 } 2298 }
2264 } 2299 }
2265 } 2300 }
2266 2301
2267 if (!list && prog->v.p.comp->mode != pies_comp_inetd) 2302 if (!list && prog->v.p.comp->mode != pies_comp_inetd)
2268 /* Default action: */ 2303 /* Default action: */
2269 prog_start (prog); 2304 prog_start (prog);
@@ -2294,7 +2329,7 @@ progman_cleanup (int expect_term)
2294 if (prog->v.p.comp->mode == pies_comp_inetd) 2329 if (prog->v.p.comp->mode == pies_comp_inetd)
2295 { 2330 {
2296 struct prog *listener = prog->v.p.listener; 2331 struct prog *listener = prog->v.p.listener;
2297 2332
2298 listener->v.p.num_instances--; 2333 listener->v.p.num_instances--;
2299 if (prog->v.p.cclass) 2334 if (prog->v.p.cclass)
2300 { 2335 {
@@ -2307,7 +2342,7 @@ progman_cleanup (int expect_term)
2307 prog->v.p.cclass = NULL; 2342 prog->v.p.cclass = NULL;
2308 } 2343 }
2309 } 2344 }
2310 2345
2311 prog_stop_redirectors (prog); 2346 prog_stop_redirectors (prog);
2312 if (listener->v.p.num_instances == 0 2347 if (listener->v.p.num_instances == 0
2313 && !component_is_active (prog->v.p.comp)) 2348 && !component_is_active (prog->v.p.comp))
@@ -2321,6 +2356,14 @@ progman_cleanup (int expect_term)
2321 } 2356 }
2322 destroy_prog (&prog); 2357 destroy_prog (&prog);
2323 } 2358 }
2359 else if (prog->v.p.comp->mode == pies_comp_startup)
2360 {
2361 debug (1, (_("removing startup component %s, pid=%lu"),
2362 prog_tag (prog), (unsigned long)pid));
2363 destroy_prog (&prog);
2364 if (!progman_startup_phase ())
2365 pies_schedule_children (PIES_CHLD_WAKEUP);
2366 }
2324 else 2367 else
2325 { 2368 {
2326 if (prog->v.p.comp->mode >= pies_mark_sysvinit 2369 if (prog->v.p.comp->mode >= pies_mark_sysvinit
@@ -2329,7 +2372,7 @@ progman_cleanup (int expect_term)
2329 sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog_tag (prog), 2372 sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog_tag (prog),
2330 pid, ""); 2373 pid, "");
2331 prog->v.p.status = status_finished; 2374 prog->v.p.status = status_finished;
2332 2375
2333 if (prog->wait) 2376 if (prog->wait)
2334 { 2377 {
2335 pies_schedule_children (PIES_CHLD_WAKEUP); 2378 pies_schedule_children (PIES_CHLD_WAKEUP);
@@ -2351,7 +2394,7 @@ progman_cleanup (int expect_term)
2351 if (!component_is_active (prog->v.p.comp)) 2394 if (!component_is_active (prog->v.p.comp))
2352 destroy_prog (&prog); 2395 destroy_prog (&prog);
2353 } 2396 }
2354 2397
2355 break; 2398 break;
2356 2399
2357 case TYPE_REDIRECTOR: 2400 case TYPE_REDIRECTOR:
@@ -2371,7 +2414,7 @@ progman_cleanup (int expect_term)
2371 break; 2414 break;
2372 } 2415 }
2373 } 2416 }
2374 2417
2375 if (!expect_term) 2418 if (!expect_term)
2376 /* This will also recompute alarm settings, if necessary */ 2419 /* This will also recompute alarm settings, if necessary */
2377 progman_wake_sleeping (0); 2420 progman_wake_sleeping (0);
@@ -2389,7 +2432,7 @@ progman_stop_component (struct prog **progptr)
2389 logmsg (LOG_INFO, _("stopping component %s"), prog_tag (prog)); 2432 logmsg (LOG_INFO, _("stopping component %s"), prog_tag (prog));
2390 prog_stop (prog, SIGTERM); 2433 prog_stop (prog, SIGTERM);
2391 break; 2434 break;
2392 2435
2393 case status_listener: 2436 case status_listener:
2394 prog_deactivate_listener (prog); 2437 prog_deactivate_listener (prog);
2395 /* fall through */ 2438 /* fall through */
@@ -2413,7 +2456,7 @@ progman_stop_component (struct prog **progptr)
2413 2456
2414 case status_stopping: 2457 case status_stopping:
2415 break; 2458 break;
2416 2459
2417 case status_finished: 2460 case status_finished:
2418 prog->stop = 0; 2461 prog->stop = 0;
2419 if (!component_is_active (prog->v.p.comp)) 2462 if (!component_is_active (prog->v.p.comp))
@@ -2441,7 +2484,7 @@ int
2441prog_activate_listener (struct prog *prog) 2484prog_activate_listener (struct prog *prog)
2442{ 2485{
2443 struct component *comp = prog->v.p.comp; 2486 struct component *comp = prog->v.p.comp;
2444 2487
2445 logmsg (LOG_INFO, _("activating listener %s"), prog_tag (prog)); 2488 logmsg (LOG_INFO, _("activating listener %s"), prog_tag (prog));
2446 if (comp->mode == pies_comp_inetd && !ISCF_TCPMUX (comp->flags) 2489 if (comp->mode == pies_comp_inetd && !ISCF_TCPMUX (comp->flags)
2447 && prog->v.p.socket == -1) 2490 && prog->v.p.socket == -1)
@@ -2535,9 +2578,9 @@ progman_gc (void)
2535 else 2578 else
2536 break; 2579 break;
2537 } 2580 }
2538 2581
2539 /* FIXME: Report remaining programs */ 2582 /* FIXME: Report remaining programs */
2540 2583
2541} 2584}
2542 2585
2543/* EOF */ 2586/* EOF */
diff --git a/src/socket.c b/src/socket.c
index aa01543..40c7aa7 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -23,13 +23,16 @@ switch_eids (uid_t *puid, gid_t *pgid, mode_t *pumask)
23 uid_t ouid = geteuid (); 23 uid_t ouid = geteuid ();
24 gid_t ogid = getegid (); 24 gid_t ogid = getegid ();
25 mode_t omask = umask (*pumask); 25 mode_t omask = umask (*pumask);
26 26
27 if (setegid (*pgid)) 27 if ((*puid && *puid != ouid) || (*pgid && *pgid != ogid))
28 logmsg (LOG_ERR, _("cannot switch to EGID %lu: %s"), 28 {
29 (unsigned long) *pgid, strerror (errno)); 29 if (setegid (*pgid))
30 if (seteuid (*puid)) 30 logmsg (LOG_ERR, _("cannot switch to EGID %lu: %s"),
31 logmsg (LOG_ERR, _("cannot switch to EUID %lu: %s"), 31 (unsigned long) *pgid, strerror (errno));
32 (unsigned long) *puid, strerror (errno)); 32 if (seteuid (*puid))
33 logmsg (LOG_ERR, _("cannot switch to EUID %lu: %s"),
34 (unsigned long) *puid, strerror (errno));
35 }
33 *puid = ouid; 36 *puid = ouid;
34 *pgid = ogid; 37 *pgid = ogid;
35 *pumask = omask; 38 *pumask = omask;
@@ -51,14 +54,14 @@ create_socket (struct pies_url *url, int socket_type,
51 uid_t uid = 0; 54 uid_t uid = 0;
52 gid_t gid = 0; 55 gid_t gid = 0;
53 int switch_back; 56 int switch_back;
54 57
55 if (strcmp (url->scheme, "unix") == 0 58 if (strcmp (url->scheme, "unix") == 0
56 || strcmp (url->scheme, "file") == 0 59 || strcmp (url->scheme, "file") == 0
57 || strcmp (url->scheme, "socket") == 0) 60 || strcmp (url->scheme, "socket") == 0)
58 { 61 {
59 struct stat st; 62 struct stat st;
60 const char *group = NULL; 63 const char *group = NULL;
61 64
62 user = url->user; 65 user = url->user;
63 if (url->argc) 66 if (url->argc)
64 { 67 {
@@ -99,7 +102,7 @@ create_socket (struct pies_url *url, int socket_type,
99 } 102 }
100 } 103 }
101 } 104 }
102 105
103 if (user) 106 if (user)
104 { 107 {
105 struct passwd *pw = getpwnam (user); 108 struct passwd *pw = getpwnam (user);
@@ -111,7 +114,7 @@ create_socket (struct pies_url *url, int socket_type,
111 uid = pw->pw_uid; 114 uid = pw->pw_uid;
112 gid = pw->pw_gid; 115 gid = pw->pw_gid;
113 } 116 }
114 117
115 if (group) 118 if (group)
116 { 119 {
117 struct group *grp = getgrnam (group); 120 struct group *grp = getgrnam (group);
@@ -122,7 +125,7 @@ create_socket (struct pies_url *url, int socket_type,
122 } 125 }
123 gid = grp->gr_gid; 126 gid = grp->gr_gid;
124 } 127 }
125 128
126 if (strlen (url->path) > sizeof addr.s_un.sun_path) 129 if (strlen (url->path) > sizeof addr.s_un.sun_path)
127 { 130 {
128 errno = EINVAL; 131 errno = EINVAL;
@@ -159,14 +162,14 @@ create_socket (struct pies_url *url, int socket_type,
159 { 162 {
160 const char *host = url->host; 163 const char *host = url->host;
161 short port = url->port; 164 short port = url->port;
162 165
163 uid = 0; 166 uid = 0;
164 gid = 0; 167 gid = 0;
165 umaskval = 0; 168 umaskval = 0;
166 169
167 addr.sa.sa_family = PF_INET; 170 addr.sa.sa_family = PF_INET;
168 socklen = sizeof (addr.s_in); 171 socklen = sizeof (addr.s_in);
169 172
170 if (!host) 173 if (!host)
171 addr.s_in.sin_addr.s_addr = INADDR_ANY; 174 addr.s_in.sin_addr.s_addr = INADDR_ANY;
172 else 175 else
@@ -185,7 +188,7 @@ create_socket (struct pies_url *url, int socket_type,
185 memmove (&addr.s_in.sin_addr, hp->h_addr, 4); 188 memmove (&addr.s_in.sin_addr, hp->h_addr, 4);
186 addr.s_in.sin_port = htons (port); 189 addr.s_in.sin_port = htons (port);
187 break; 190 break;
188 191
189 default: 192 default:
190 logmsg (LOG_ERR, _("%s: unsupported address family"), 193 logmsg (LOG_ERR, _("%s: unsupported address family"),
191 url->string); 194 url->string);
@@ -198,7 +201,7 @@ create_socket (struct pies_url *url, int socket_type,
198 logmsg (LOG_ERR, "%s: unknown scheme", url->string); 201 logmsg (LOG_ERR, "%s: unknown scheme", url->string);
199 return -1; 202 return -1;
200 } 203 }
201 204
202 fd = socket (addr.sa.sa_family, socket_type, url->proto); 205 fd = socket (addr.sa.sa_family, socket_type, url->proto);
203 if (fd == -1) 206 if (fd == -1)
204 { 207 {
@@ -250,7 +253,7 @@ pass_fd0 (int fd, int payload)
250# ifndef CMSG_SPACE 253# ifndef CMSG_SPACE
251# define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size)) 254# define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
252# endif /* ! CMSG_SPACE */ 255# endif /* ! CMSG_SPACE */
253 256
254 char control[CMSG_SPACE (sizeof (int))]; 257 char control[CMSG_SPACE (sizeof (int))];
255 struct cmsghdr *cmptr; 258 struct cmsghdr *cmptr;
256 259
@@ -290,7 +293,7 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
290 int sockfd = -1; 293 int sockfd = -1;
291 int res = -1; 294 int res = -1;
292 struct sockaddr_un addr; 295 struct sockaddr_un addr;
293 296
294 if (strlen (socket_name) > sizeof addr.sun_path) 297 if (strlen (socket_name) > sizeof addr.sun_path)
295 { 298 {
296 logmsg (LOG_ERR, _("%s: UNIX socket name too long"), socket_name); 299 logmsg (LOG_ERR, _("%s: UNIX socket name too long"), socket_name);
@@ -298,7 +301,7 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
298 } 301 }
299 addr.sun_family = AF_UNIX; 302 addr.sun_family = AF_UNIX;
300 strcpy (addr.sun_path, socket_name); 303 strcpy (addr.sun_path, socket_name);
301 304
302 for (;;) 305 for (;;)
303 { 306 {
304 time_t now = time (NULL); 307 time_t now = time (NULL);
@@ -362,7 +365,7 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
362 int rc; 365 int rc;
363 fd_set fds; 366 fd_set fds;
364 struct timeval tv; 367 struct timeval tv;
365 368
366 FD_ZERO (&fds); 369 FD_ZERO (&fds);
367 FD_SET (sockfd, &fds); 370 FD_SET (sockfd, &fds);
368 tv.tv_usec = 0; 371 tv.tv_usec = 0;
@@ -430,7 +433,7 @@ calc_fd_max (void)
430} 433}
431 434
432void * 435void *
433register_socket (int fd, 436register_socket (int fd,
434 socket_handler_t rd, 437 socket_handler_t rd,
435 socket_handler_t wr, 438 socket_handler_t wr,
436 socket_handler_t ex, 439 socket_handler_t ex,
@@ -454,7 +457,7 @@ register_socket (int fd,
454 FD_ZERO (&fdset[PIES_EVT_EX]); 457 FD_ZERO (&fdset[PIES_EVT_EX]);
455 si_head = sip; 458 si_head = sip;
456 } 459 }
457 460
458 si_tail = sip; 461 si_tail = sip;
459 if (rd) 462 if (rd)
460 FD_SET (fd, &fdset[PIES_EVT_RD]); 463 FD_SET (fd, &fdset[PIES_EVT_RD]);
@@ -493,7 +496,7 @@ delete_sockinst (struct sockinst *sp)
493 if (sp->handler[PIES_EVT_EX]) 496 if (sp->handler[PIES_EVT_EX])
494 FD_CLR (sp->fd, &fdset[PIES_EVT_EX]); 497 FD_CLR (sp->fd, &fdset[PIES_EVT_EX]);
495 fd_max = -1; 498 fd_max = -1;
496 499
497 if (sp->prev) 500 if (sp->prev)
498 sp->prev->next = sp->next; 501 sp->prev->next = sp->next;
499 else 502 else
@@ -572,7 +575,7 @@ pies_pause (void)
572{ 575{
573 if (pies_pause_hook && pies_pause_hook ()) 576 if (pies_pause_hook && pies_pause_hook ())
574 return; 577 return;
575 578
576 if (fd_max == -1) 579 if (fd_max == -1)
577 calc_fd_max (); 580 calc_fd_max ();
578 581
@@ -581,7 +584,7 @@ pies_pause (void)
581 fd_set rdset = fdset[PIES_EVT_RD]; 584 fd_set rdset = fdset[PIES_EVT_RD];
582 fd_set wrset = fdset[PIES_EVT_WR]; 585 fd_set wrset = fdset[PIES_EVT_WR];
583 fd_set exset = fdset[PIES_EVT_EX]; 586 fd_set exset = fdset[PIES_EVT_EX];
584 587
585 int rc = select (fd_max + 1, &rdset, &wrset, &exset, NULL); 588 int rc = select (fd_max + 1, &rdset, &wrset, &exset, NULL);
586 if (rc > 0) 589 if (rc > 0)
587 { 590 {
@@ -637,4 +640,3 @@ pies_pause (void)
637 } 640 }
638 } 641 }
639} 642}
640
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 447104b..b2f2719 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -14,7 +14,13 @@
14# You should have received a copy of the GNU General Public License 14# You should have received a copy of the GNU General Public License
15# along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. 15# along with GNU Pies. If not, see <http://www.gnu.org/licenses/>.
16 16
17EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 respawn retcode mailer 17AUXTOOLS = \
18 aux/respawn\
19 aux/retcode\
20 aux/mailer\
21 aux/startup
22
23EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 $(AUXTOOLS)
18DISTCLEANFILES = atconfig $(check_SCRIPTS) 24DISTCLEANFILES = atconfig $(check_SCRIPTS)
19MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) 25MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
20 26
@@ -46,6 +52,7 @@ TESTSUITE_AT = \
46 redirect.at\ 52 redirect.at\
47 ret-exec.at\ 53 ret-exec.at\
48 ret-notify.at\ 54 ret-notify.at\
55 startup.at\
49 version.at 56 version.at
50 57
51TESTSUITE = $(srcdir)/testsuite 58TESTSUITE = $(srcdir)/testsuite
diff --git a/tests/atlocal.in b/tests/atlocal.in
index 9069bbd..1992b80 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -4,7 +4,7 @@
4 4
5PATH=@abs_builddir@:@abs_top_builddir@/src:$srcdir:$PATH 5PATH=@abs_builddir@:@abs_top_builddir@/src:$srcdir:$PATH
6XFAILFILE=$abs_builddir/.badversion 6XFAILFILE=$abs_builddir/.badversion
7 7auxdir="$abs_srcdir/aux"
8trimws() { 8trimws() {
9 sed 's/[ ][ ]*$//' 9 sed 's/[ ][ ]*$//'
10} 10}
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 @@
1#!/bin/sh
2dir=${1:?}
3time=${2:?}
4tag=${3:?}
5
6touch $dir/$tag
7sleep $time
diff --git a/tests/redirect.at b/tests/redirect.at
index 9e53ba2..3a8cca7 100644
--- a/tests/redirect.at
+++ b/tests/redirect.at
@@ -24,7 +24,7 @@ outfile=$PWD/out
24cat > pies.conf <<_EOT 24cat > pies.conf <<_EOT
25component test { 25component test {
26 mode respawn; 26 mode respawn;
27 command "$abs_srcdir/respawn -tag respawn -append -pid $comp_pid_file"; 27 command "$auxdir/respawn -tag respawn -append -pid $comp_pid_file";
28 stdout file "$outfile"; 28 stdout file "$outfile";
29} 29}
30_EOT 30_EOT
diff --git a/tests/respawn.at b/tests/respawn.at
index 8d72c40..4a8e3a7 100644
--- a/tests/respawn.at
+++ b/tests/respawn.at
@@ -23,7 +23,7 @@ comp_pid_file=$PWD/comp.pid
23cat > pies.conf <<_EOT 23cat > pies.conf <<_EOT
24component test { 24component test {
25 mode respawn; 25 mode respawn;
26 command "$abs_srcdir/respawn -append -pid $comp_pid_file"; 26 command "$auxdir/respawn -append -pid $comp_pid_file";
27} 27}
28_EOT 28_EOT
29 29
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
@@ -26,10 +26,10 @@ cat > pies.conf <<_EOT
26component test { 26component test {
27 mode respawn; 27 mode respawn;
28 return-code 10 { 28 return-code 10 {
29 exec "$abs_srcdir/retcode $report_file"; 29 exec "$auxdir/retcode $report_file";
30 action disable; 30 action disable;
31 } 31 }
32 command "$abs_srcdir/respawn -sleep 2 -pid $comp_pid_file -exit 10"; 32 command "$auxdir/respawn -sleep 2 -pid $comp_pid_file -exit 10";
33} 33}
34_EOT 34_EOT
35 35
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
@@ -22,15 +22,15 @@ PIES_XFAIL_CHECK
22PIES_CONTROL_INIT 22PIES_CONTROL_INIT
23report_file=$PWD/report 23report_file=$PWD/report
24cat > pies.conf <<_EOT 24cat > pies.conf <<_EOT
25mailer-program "$abs_srcdir/mailer"; 25mailer-program "$auxdir/mailer";
26mailer-command-line "$abs_srcdir/mailer $report_file"; 26mailer-command-line "$auxdir/mailer $report_file";
27component test { 27component test {
28 mode respawn; 28 mode respawn;
29 return-code 10 { 29 return-code 10 {
30 notify root; 30 notify root;
31 action disable; 31 action disable;
32 } 32 }
33 command "$abs_srcdir/respawn -sleep 2 -exit 10"; 33 command "$auxdir/respawn -sleep 2 -exit 10";
34} 34}
35_EOT 35_EOT
36 36
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 @@
1# This file is part of GNU pies testsuite. -*- Autotest -*-
2# Copyright (C) 2019 Sergey Poznyakoff
3#
4# GNU pies is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3, or (at your option)
7# any later version.
8#
9# GNU pies is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with GNU pies. If not, see <http://www.gnu.org/licenses/>.
16
17AT_SETUP([Startup components])
18
19AT_CHECK([
20PIES_XFAIL_CHECK
21PIES_CONTROL_INIT
22comp_pid_file=$PWD/comp.pid
23
24cat > pies.conf <<_EOT
25component b1 {
26 mode startup;
27 command "$auxdir/startup $PWD 1 b1";
28}
29
30component b2 {
31 mode startup;
32 command "$auxdir/startup $PWD 2 b2";
33}
34
35component test {
36 mode respawn;
37 command "$auxdir/respawn -append -pid $comp_pid_file";
38}
39_EOT
40
41pies --config-file control.conf --config-file pies.conf
42
43n=0
44res=
45b1=
46b2=
47while :
48do
49 echo "n=$n" >> tracefile
50 if test -z "$b1" && test -f b1; then
51 res="${res}b1"
52 b1=1
53 echo "got b1" >> tracefile
54 fi
55 if test -z "$b2" && test -f b2; then
56 res="${res}b2"
57 b2=1
58 echo "got b2" >> tracefile
59 fi
60 if test -f $comp_pid_file; then
61 echo "got pidfile" >> tracefile
62 res="${res}pid"
63 break
64 fi
65 sleep 1
66 n=$(($n + 1))
67 if test $n -gt 10; then
68 echo >&2 "timed out"
69 break
70 fi
71done
72
73PIES_STOP
74case $res in
75b1b2pid|b2b1pid) echo b1b2pid;;
76*) echo $res
77esac
78],
79[0],
80[b1b2pid
81])
82
83AT_CLEANUP
84
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 03ddd50..2a1167d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -65,3 +65,4 @@ m4_include([respawn.at])
65m4_include([redirect.at]) 65m4_include([redirect.at])
66m4_include([ret-exec.at]) 66m4_include([ret-exec.at])
67m4_include([ret-notify.at]) 67m4_include([ret-notify.at])
68m4_include([startup.at])

Return to:

Send suggestions and report system problems to the System administrator.