summaryrefslogtreecommitdiffabout
Unidiff
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.