1 /* This file is part of GNU Pies.
2 Copyright (C) 2007-2020 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
17 #include "pies.h"
18 #include "prog.h"
19
20 static struct prog *proghead, *progtail;
21 static struct grecs_symtab *conn_tab;
22
23 struct prog *
progman_locate(const char * name)24 progman_locate (const char *name)
25 {
26 struct prog *prog;
27
28 for (prog = proghead; prog; prog = prog->next)
29 if (strcmp (prog_tag (prog), name) == 0)
30 break;
31 return prog;
32 }
33
34 int
progman_foreach(int (* filter)(struct prog *,void * data),void * data)35 progman_foreach (int (*filter) (struct prog *, void *data), void *data)
36 {
37 struct prog *prog;
38 int rc = 0;
39 for (prog = proghead; prog; )
40 {
41 struct prog *next = prog->next;
42 if ((rc = filter (prog, data)) != 0)
43 break;
44 prog = next;
45 }
46 return rc;
47 }
48
49 static struct prog *
prog_lookup_by_pid(pid_t pid)50 prog_lookup_by_pid (pid_t pid)
51 {
52 struct prog *prog;
53
54 for (prog = proghead; prog; prog = prog->next)
55 if (prog->pid == pid)
56 break;
57 return prog;
58 }
59
60 struct component *
progman_lookup_component(const char * tag)61 progman_lookup_component (const char *tag)
62 {
63 struct prog *prog;
64 for (prog = proghead; prog; prog = prog->next)
65 if (IS_COMPONENT (prog) && strcmp (prog_tag (prog), tag) == 0)
66 return prog->v.p.comp;
67 return NULL;
68 }
69
70 struct component *
progman_lookup_tcpmux(const char * service,const char * master)71 progman_lookup_tcpmux (const char *service, const char *master)
72 {
73 struct prog *prog;
74 for (prog = proghead; prog; prog = prog->next)
75 if (IS_COMPONENT (prog)
76 && ISCF_TCPMUX (prog->v.p.comp->flags)
77 && prog->active
78 && prog->v.p.comp->service
79 && strcasecmp (prog->v.p.comp->service, service) == 0
80 && prog->v.p.comp->tcpmux
81 && strcmp (prog->v.p.comp->tcpmux, master) == 0)
82 return prog->v.p.comp;
83 return NULL;
84 }
85
86 void prog_stop (struct prog *prog, int sig);
87 static int prog_start_prerequisites (struct prog *prog);
88
89 char const *
prog_tag(struct prog const * prog)90 prog_tag (struct prog const *prog)
91 {
92 switch (prog->type)
93 {
94 case TYPE_COMPONENT:
95 return prog->v.p.comp->tag;
96
97 case TYPE_COMMAND:
98 return prog->v.c.tag;
99 }
100 abort ();
101 }
102
103 void
link_prog(struct prog * prog,struct prog * ref)104 link_prog (struct prog *prog, struct prog *ref)
105 {
106 if (!ref)
107 {
108 prog->prev = NULL;
109 prog->next = proghead;
110 if (proghead)
111 proghead->prev = prog;
112 else
113 progtail = prog;
114 proghead = prog;
115 }
116 else
117 {
118 struct prog *x;
119
120 prog->prev = ref;
121 prog->next = ref->next;
122
123 if ((x = ref->next))
124 x->prev = prog;
125 else
126 progtail = prog;
127
128 ref->next = prog;
129 }
130 }
131
132 void
unlink_prog(struct prog * pp)133 unlink_prog (struct prog *pp)
134 {
135 struct prog *x;
136
137 if ((x = pp->prev))
138 x->next = pp->next;
139 else
140 proghead = pp->next;
141 if ((x = pp->next))
142 x->prev = pp->prev;
143 else
144 progtail = pp->prev;
145 }
146
147 static inline void
prog_stop_redirectors(struct prog * p)148 prog_stop_redirectors (struct prog *p)
149 {
150 if (p->v.p.redir[RETR_OUT] != -1)
151 {
152 deregister_socket (p->v.p.redir[RETR_OUT]);
153 p->v.p.redir[RETR_OUT] = -1;
154 }
155 if (p->v.p.redir[RETR_ERR] != -1)
156 {
157 deregister_socket (p->v.p.redir[RETR_ERR]);
158 p->v.p.redir[RETR_ERR] = -1;
159 }
160 }
161
162 void
destroy_prog(struct prog ** pp)163 destroy_prog (struct prog **pp)
164 {
165 struct prog *p = *pp;
166
167 unlink_prog (p);
168 switch (p->type)
169 {
170 case TYPE_COMPONENT:
171 environ_free (p->v.p.env);
172 if (p->v.p.comp->flags & CF_EXPANDENV)
173 argv_free (p->v.p.argv);
174 component_ref_decr (p->v.p.comp);
175 if (p->v.p.status == status_listener && p->v.p.socket != -1)
176 deregister_socket (p->v.p.socket);
177 /* FIXME: Remove also all dependent progs (esp. tcpmux) */
178 prog_stop_redirectors (p);
179 break;
180
181 case TYPE_COMMAND:
182 free (p->v.c.tag);
183 free (p->v.c.command);
184 }
185 free (p);
186 *pp = NULL;
187 }
188
189 /* Given the component COMP find the element of the program list
190 after which to link in the new prog associated with that COMP.
191 The progs in the resulting list must be arranged exactly in the
192 same order as the corresponding components. Points to note:
193 1. If comp->prog is already present, follow progs in its next
194 chain until the last one that points to the same COMP is found.
195 2. Otherwise, if that component is not the first one, step back
196 to the previous component and do the same for its comp->prog chain.
197 3. Return the prog found.
198 */
199 static struct prog *
find_prog_ref(struct component * comp)200 find_prog_ref (struct component *comp)
201 {
202 struct prog *prog;
203
204 if (!comp->prog)
205 {
206 comp = comp->prev;
207 if (!comp)
208 return NULL;
209 }
210
211 if (comp->prog)
212 {
213 for (prog = comp->prog;
214 prog->next
215 && IS_COMPONENT (prog->next)
216 && prog->next->v.p.comp == comp;
217 prog = prog->next)
218 ;
219 }
220 else
221 prog = NULL;
222 return prog;
223 }
224
225 static struct prog *
register_prog0(struct component * comp)226 register_prog0 (struct component *comp)
227 {
228 struct prog *newp;
229
230 newp = grecs_zalloc (sizeof (*newp));
231 newp->type = TYPE_COMPONENT;
232 newp->pid = 0;
233 newp->v.p.comp = comp;
234 newp->v.p.socket = -1;
235
236 if (comp->mode == pies_comp_inetd)
237 newp->v.p.status = status_listener;
238 else
239 newp->v.p.status = status_stopped;
240
241 if ((comp->flags & CF_DISABLED)
242 || comp->mode == pies_comp_ondemand
243 || comp->mode == pies_comp_shutdown)
244 newp->active = 0;
245 else
246 newp->active = 1;
247
248 switch (comp->mode)
249 {
250 case pies_comp_exec:
251 case pies_comp_startup:
252 case pies_comp_shutdown:
253 break;
254
255 default:
256 comp->redir[RETR_OUT].type = redir_null;
257 }
258
259 link_prog (newp, find_prog_ref (comp));
260 component_ref_incr (comp);
261 return newp;
262 }
263
264 void
register_prog(struct component * comp)265 register_prog (struct component *comp)
266 {
267 comp->prog = register_prog0 (comp);
268 }
269
270 void
register_command(char * tag,char * command,pid_t pid)271 register_command (char *tag, char *command, pid_t pid)
272 {
273 struct prog *newp = grecs_zalloc (sizeof (*newp));
274 newp->type = TYPE_COMMAND;
275 newp->pid = pid;
276 newp->v.c.tag = grecs_strdup (tag);
277 newp->v.c.command = command;
278 link_prog (newp, progtail);
279 }
280
281 static inline int
progman_startup_phase(void)282 progman_startup_phase (void)
283 {
284 struct prog *prog;
285
286 for (prog = proghead; prog; prog = prog->next)
287 {
288 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup
289 && prog->v.p.status == status_running)
290 return 1;
291 }
292 return 0;
293 }
294
295 int
progman_waiting_p(void)296 progman_waiting_p (void)
297 {
298 struct prog *prog;
299
300 for (prog = proghead; prog; prog = prog->next)
301 {
302 if (IS_COMPONENT (prog)
303 && prog->v.p.status == status_running
304 && (prog->wait || prog->v.p.comp->mode == pies_comp_startup))
305 {
306 debug (3, ("%s: waiting for %s (%lu)",
307 __FUNCTION__, prog_tag (prog),
308 (unsigned long) prog->pid));
309 return 1;
310 }
311 }
312 return 0;
313 }
314
315 int
redirect_to_file(struct prog * master,int stream)316 redirect_to_file (struct prog *master, int stream)
317 {
318 struct passwd *pw;
319 int fd = open (master->v.p.comp->redir[stream].v.file, O_RDWR|O_CREAT,
320 0644 & ~master->v.p.comp->umask);
321 if (fd == -1)
322 {
323 logmsg (LOG_ERR, _("cannot open output file %s: %s"),
324 master->v.p.comp->redir[stream].v.file,
325 strerror (errno));
326 return -1;
327 }
328 /* Fix file ownership */
329 if (master->v.p.comp->privs.user
330 && (pw = getpwnam (master->v.p.comp->privs.user)) != NULL)
331 {
332 if (chown (master->v.p.comp->redir[stream].v.file,
333 pw->pw_uid, pw->pw_gid))
334 logmsg (LOG_ERR, "chown %s: %s",
335 master->v.p.comp->redir[stream].v.file,
336 strerror (errno));
337 }
338 /* Position to the end of file */
339 if (lseek (fd, 0, SEEK_END) == -1)
340 {
341 if (errno != ESPIPE)
342 logmsg (LOG_ERR, "lseek(%s): %s",
343 master->v.p.comp->redir[stream].v.file,
344 strerror (errno));
345 }
346 return fd;
347 }
348
349 struct read_buffer
350 {
351 struct prog *master;
352 int stream;
353 char text[PIES_LOG_BUF_SIZE];
354 size_t len;
355 int overflow;
356 };
357
358 static int
redirect_read(int fd,void * data)359 redirect_read (int fd, void *data)
360 {
361 struct read_buffer *rb = data;
362 int n;
363 int prio = rb->master->v.p.comp->redir[rb->stream].v.prio;
364 char const *tag = prog_tag (rb->master);
365 pid_t pid = rb->master->pid;
366 char *p;
367 static char *retr_stream_name[] = {
368 [RETR_OUT] = "stdout",
369 [RETR_ERR] = "stderr"
370 };
371
372 n = read (fd, rb->text + rb->len, sizeof (rb->text) - rb->len);
373 if (n == -1)
374 {
375 if (errno != EINTR)
376 {
377 logmsg (LOG_INFO, _("%s: %s while reading %s"),
378 tag, strerror (errno), retr_stream_name[rb->stream]);
379 rb->master->v.p.redir[rb->stream] = -1;
380 close (fd);
381 deregister_socket (fd);
382 return -1;
383 }
384 }
385 else if (n == 0)
386 {
387 logmsg (LOG_INFO, _("%s: EOF on %s"),
388 tag, retr_stream_name[rb->stream]);
389 rb->master->v.p.redir[rb->stream] = -1;
390 close (fd);
391 deregister_socket (fd);
392 }
393 else
394 {
395 rb->len += n;
396
397 while (rb->len)
398 {
399 p = memchr (rb->text, '\n', rb->len);
400 if (p)
401 {
402 *p++ = 0;
403 if (rb->overflow)
404 rb->overflow = 0;
405 else
406 pies_syslog_message (prio, rb->text, tag, pid);
407 n = rb->len - (p - rb->text);
408 if (n > 0)
409 memmove (rb->text, p, n);
410 rb->len = n;
411 }
412 else if (rb->len == sizeof (rb->text))
413 {
414 rb->text[sizeof (rb->text) - 1] = 0;
415 pies_syslog_message (prio, rb->text, tag, pid);
416 rb->len = 0;
417 rb->overflow = 1;
418 }
419 else
420 break;
421 }
422 }
423 return 0;
424 }
425
426 static void
read_buffer_free(void * p)427 read_buffer_free (void *p)
428 {
429 free (p);
430 }
431
432 int
redirect_to_syslog(struct prog * master,int stream,int * fd)433 redirect_to_syslog (struct prog *master, int stream, int *fd)
434 {
435 struct read_buffer *rb;
436 int p[2];
437
438 if (pipe (p))
439 {
440 logmsg (LOG_CRIT, "pipe: %s", strerror (errno));
441 return -1;
442 }
443
444 rb = grecs_zalloc (sizeof (*rb));
445 rb->master = master;
446 rb->stream = stream;
447 rb->len = 0;
448 rb->overflow = 0;
449
450 register_socket (p[0], redirect_read, NULL, NULL, rb, read_buffer_free);
451 *fd = p[0];
452 return p[1];
453 }
454
455 void
free_redirector(struct redirector * rp)456 free_redirector (struct redirector *rp)
457 {
458 if (rp->type == redir_file)
459 free (rp->v.file);
460 }
461
462 int
open_redirector(struct prog * master,int stream,int * fd)463 open_redirector (struct prog *master, int stream, int *fd)
464 {
465 switch (master->v.p.comp->redir[stream].type)
466 {
467 case redir_null:
468 *fd = -1;
469 break;
470
471 case redir_file:
472 *fd = -1;
473 return redirect_to_file (master, stream);
474
475 case redir_syslog:
476 return redirect_to_syslog (master, stream, fd);
477 }
478 return -1;
479 }
480
481
482 static unsigned
conn_class_hasher(void * data,unsigned long n_buckets)483 conn_class_hasher (void *data, unsigned long n_buckets)
484 {
485 struct conn_class *pcclass = data;
486 unsigned char const *tag = (unsigned char const *)pcclass->tag;
487 size_t value = 0;
488 unsigned char ch;
489 size_t len;
490
491 while ((ch = *tag++))
492 value = (value * 31 + ch) % n_buckets;
493
494 for (tag = (const unsigned char *)&pcclass->sa_storage,
495 len = pcclass->sa_len;
496 len;
497 tag++, len--)
498 value = (value * 31 + *tag) % n_buckets;
499 return value;
500 }
501
502 /* Compare two strings for equality. */
503 static int
conn_class_compare(void const * data1,void const * data2)504 conn_class_compare (void const *data1, void const *data2)
505 {
506 struct conn_class const *p1 = data1;
507 struct conn_class const *p2 = data2;
508
509 return !(p1->sa_len == p2->sa_len &&
510 memcmp (&p1->sa_storage, &p2->sa_storage, p1->sa_len) == 0 &&
511 strcmp (p1->tag, p2->tag) == 0);
512 }
513
514 static void
conn_class_free(void * data)515 conn_class_free (void *data)
516 {
517 free (data);
518 }
519
520 static int
conn_class_copy(void * a,void * b)521 conn_class_copy(void *a, void *b)
522 {
523 memcpy (a, b, sizeof(struct conn_class));
524 memset (b, 0, sizeof(struct conn_class));
525 return 0;
526 }
527
528 static struct conn_class *
conn_class_lookup(const char * tag,union pies_sockaddr_storage const * sa_storage_ptr,size_t sa_len)529 conn_class_lookup (const char *tag,
530 union pies_sockaddr_storage const *sa_storage_ptr,
531 size_t sa_len)
532 {
533 int install = 1;
534 struct conn_class *probe, *ret;
535
536 probe = grecs_malloc (sizeof (probe[0]));
537 probe->tag = tag;
538 probe->sa_storage = *sa_storage_ptr;
539 probe->sa_len = sa_len;
540 switch (probe->sa_storage.s.sa_family)
541 {
542 case AF_INET:
543 probe->sa_storage.s_in.sin_port = 0;
544 break;
545
546 case AF_UNIX:
547 break;
548
549 default:
550 logmsg (LOG_ERR, _("unexpected address family: %d"),
551 probe->sa_storage.s.sa_family);
552 break;
553 }
554
555 probe->count = 0;
556 if (!conn_tab)
557 {
558 conn_tab = grecs_symtab_create(sizeof (struct conn_class),
559 conn_class_hasher,
560 conn_class_compare,
561 conn_class_copy,
562 NULL,
563 conn_class_free);
564 if (!conn_tab)
565 grecs_alloc_die ();
566 }
567
568 ret = grecs_symtab_lookup_or_install (conn_tab, probe, &install);
569 if (!ret)
570 {
571 logmsg (LOG_CRIT, "cannot allocate conn_class: %s",
572 strerror (errno));
573 abort ();
574 }
575 free (probe);
576 return ret;
577 }
578
579 static void
conn_class_report(int prio,struct conn_class * pcclass)580 conn_class_report (int prio, struct conn_class *pcclass)
581 {
582 char *s = sockaddr_to_astr ((struct sockaddr *)&pcclass->sa_storage,
583 pcclass->sa_len);
584 logmsg (prio, _("connections in class %s/%s: %lu"),
585 pcclass->tag, s, (unsigned long)pcclass->count);
586 free (s);
587 }
588
589 static void
conn_class_remove(struct conn_class * pcclass)590 conn_class_remove (struct conn_class *pcclass)
591 {
592 if (!conn_tab)
593 {
594 logmsg (LOG_CRIT, "attempt to free unexisting conn_class %p", pcclass);
595 conn_class_report (LOG_CRIT, pcclass);
596 abort ();
597 }
598 grecs_symtab_remove (conn_tab, pcclass);
599 }
600
601
602 #define ENV_PROTO "PROTO"
603 #define ENV_SOCKTYPE "SOCKTYPE"
604 #define ENV_LOCALIP "LOCALIP"
605 #define ENV_LOCALPORT "LOCALPORT"
606 #define ENV_LOCALHOST "LOCALHOST"
607 #define ENV_REMOTEIP "REMOTEIP"
608 #define ENV_REMOTEPORT "REMOTEPORT"
609 #define ENV_REMOTEHOST "REMOTEHOST"
610 static char *sockenv_var[] = {
611 ENV_PROTO,
612 ENV_SOCKTYPE,
613 ENV_LOCALIP,
614 ENV_LOCALPORT,
615 ENV_LOCALHOST,
616 ENV_REMOTEIP,
617 ENV_REMOTEPORT,
618 ENV_REMOTEHOST,
619 NULL
620 };
621
622 static inline void
debug_environ(struct prog * prog,int l)623 debug_environ (struct prog *prog, int l)
624 {
625 if (debug_level >= l)
626 {
627 int i;
628 char **env = environ_ptr (prog->v.p.env);
629 logmsg_printf (LOG_DEBUG, "environment: ");
630 for (i = 0; env[i]; i++)
631 logmsg_printf (LOG_DEBUG, "%s ", env[i]);
632 logmsg_printf (LOG_DEBUG, "\n");
633 }
634 }
635
636 /* Pass socket information in environment variables. */
637 void
prog_sockenv(struct prog * prog)638 prog_sockenv (struct prog *prog)
639 {
640 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
641 char *p;
642 struct hostent *host;
643 union pies_sockaddr_storage sa_server;
644 socklen_t len = sizeof (sa_server);
645 union pies_sockaddr_storage *sa_client = &prog->v.p.sa_storage;
646 socklen_t cltlen = prog->v.p.sa_len;
647 const char *proto = NULL;
648
649 if (!(prog->v.p.comp->flags & CF_SOCKENV))
650 return;
651
652 if (socket_type_to_str (prog->v.p.comp->socket_type, &proto))
653 proto = umaxtostr (prog->v.p.comp->socket_type, buf);
654 environ_set (prog->v.p.env, ENV_SOCKTYPE, proto);
655
656 if (prog->v.p.comp->socket_url)
657 proto = prog->v.p.comp->socket_url->proto_s;
658 else if (prog->v.p.listener)
659 proto = prog->v.p.listener->v.p.comp->socket_url->proto_s;
660 else if (ISCF_TCPMUX (prog->v.p.comp->flags))
661 proto = "TCP";
662
663 environ_set (prog->v.p.env, ENV_PROTO, proto);
664
665 if (getsockname (prog->v.p.socket,
666 (struct sockaddr *) &sa_server, &len) < 0)
667 logmsg (LOG_WARNING, "getsockname(): %s", strerror (errno));
668 else if (sa_server.s.sa_family == AF_INET)
669 {
670 p = inet_ntoa (sa_server.s_in.sin_addr);
671 if (p)
672 environ_set (prog->v.p.env, ENV_LOCALIP, p);
673
674 p = umaxtostr (ntohs (sa_server.s_in.sin_port), buf);
675 environ_set (prog->v.p.env, ENV_LOCALPORT, p);
676
677 if (prog->v.p.comp->flags & CF_RESOLVE)
678 {
679 if ((host = gethostbyaddr ((char *) &sa_server.s_in.sin_addr,
680 sizeof (sa_server.s_in.sin_addr),
681 AF_INET)) == NULL)
682 logmsg (LOG_WARNING, "gethostbyaddr: %s", strerror (errno));
683 else
684 environ_set (prog->v.p.env, ENV_LOCALHOST, host->h_name);
685 }
686 }
687
688 if (cltlen > 0 && sa_client->s.sa_family == AF_INET)
689 {
690 p = inet_ntoa (sa_client->s_in.sin_addr);
691 if (p)
692 environ_set (prog->v.p.env, ENV_REMOTEIP, p);
693
694 p = umaxtostr (ntohs (sa_client->s_in.sin_port), buf);
695 environ_set (prog->v.p.env, ENV_REMOTEPORT, p);
696
697 if (prog->v.p.comp->flags & CF_RESOLVE)
698 {
699 if ((host = gethostbyaddr ((char *) &sa_client->s_in.sin_addr,
700 sizeof (sa_client->s_in.sin_addr),
701 AF_INET)) == NULL)
702 logmsg (LOG_WARNING, "gethostbyaddr: %s",
703 strerror (errno));
704 else
705 environ_set (prog->v.p.env, ENV_REMOTEHOST, host->h_name);
706 }
707 }
708 /* FIXME: $REMOTEINFO ? */
709 debug_environ (prog, 4);
710 }
711
712 static int
check_rate(struct prog * prog,unsigned testtime,size_t max_count)713 check_rate (struct prog *prog, unsigned testtime, size_t max_count)
714 {
715 time_t now;
716
717 time (&now);
718
719 if (prog->v.p.timestamp + testtime > now)
720 prog->v.p.failcount++;
721 else
722 {
723 prog->v.p.failcount = 0;
724 prog->v.p.timestamp = now;
725 }
726
727 if (prog->v.p.failcount > max_count)
728 {
729 prog->v.p.timestamp = now;
730 prog->v.p.status = status_sleeping;
731 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
732 return 1;
733 }
734
735 return 0;
736 }
737
738 static int
check_spawn_rate(struct prog * prog)739 check_spawn_rate (struct prog *prog)
740 {
741 if (check_rate (prog, TESTTIME, MAXSPAWN))
742 {
743 logmsg (LOG_NOTICE,
744 ngettext ("%s is respawning too fast, disabled for %d minute",
745 "%s is respawning too fast, disabled for %d minutes",
746 SLEEPTIME / 60),
747 prog_tag (prog), SLEEPTIME / 60);
748 return 1;
749 }
750 return 0;
751 }
752
753 static int
check_connection_rate(struct prog * prog)754 check_connection_rate (struct prog *prog)
755 {
756 size_t max_rate = prog->v.p.comp->max_rate
757 ? prog->v.p.comp->max_rate : default_max_rate;
758 if (max_rate && check_rate (prog, 60, max_rate))
759 {
760 logmsg (LOG_NOTICE,
761 ngettext ("%s is starting too often, disabled for %d minute",
762 "%s is starting too often, disabled for %d minutes",
763 SLEEPTIME / 60),
764 prog_tag (prog), SLEEPTIME / 60);
765 return 1;
766 }
767 return 0;
768 }
769
770 static int
prog_open_socket(struct prog * prog)771 prog_open_socket (struct prog *prog)
772 {
773 prog->v.p.socket = create_socket (prog->v.p.comp->socket_url,
774 prog->v.p.comp->socket_type,
775 prog->v.p.comp->privs.user,
776 prog->v.p.comp->umask);
777 if (prog->v.p.socket == -1)
778 {
779 prog->v.p.status = status_stopped;
780 prog->active = 0;
781 return 1;
782 }
783 if (listen (prog->v.p.socket, 8))
784 {
785 logmsg (LOG_ERR, "listen: %s", strerror (errno));
786 close (prog->v.p.socket);
787 prog->v.p.socket = -1;
788 prog->v.p.status = status_stopped;
789 prog->active = 0;
790 return 1;
791 }
792 return 0;
793 }
794
795 static void
progman_ws_error(const char * fmt,...)796 progman_ws_error (const char *fmt, ...)
797 {
798 va_list ap;
799
800 va_start (ap, fmt);
801 vlogmsg (LOG_ERR, fmt, ap);
802 va_end (ap);
803 }
804
805 /*
806 * Initialization of the environment and argc/argv members of
807 * struct prog. For regular components this is done in the main
808 * process, so that argv can be reported correctly via the ctl
809 * interface. For tcpmux components, which are run from the
810 * listener child, this is not so. That does little harm as
811 * these components are not visible from the ctl interface anyway.
812 */
813 static int
prog_init(struct prog * prog)814 prog_init (struct prog *prog)
815 {
816 if ((prog->v.p.env = environ_create (environ)) == NULL)
817 {
818 logmsg (LOG_CRIT, "environ_create: %s", strerror (errno));
819 return -1;
820 }
821
822 if (prog->v.p.comp->flags & CF_SOCKENV)
823 {
824 size_t i;
825 for (i = 0; sockenv_var[i]; i++)
826 environ_unset (prog->v.p.env, sockenv_var[i], NULL);
827 }
828
829 if (envop_exec (prog->v.p.comp->envop, prog->v.p.env))
830 {
831 logmsg (LOG_CRIT, "environ_exec: %s", strerror (errno));
832 return -1;
833 }
834
835 if (SYSVINIT_ACTIVE)
836 {
837 size_t i;
838 for (i = 0; sysvinit_environ_hint[i]; i++)
839 {
840 if (environ_add (prog->v.p.env, sysvinit_environ_hint[i]))
841 {
842 logmsg (LOG_CRIT, "environ_add: %s", strerror (errno));
843 return -1;
844 }
845 }
846 }
847 debug_environ (prog, 4);
848
849 if (prog->v.p.comp->flags & CF_EXPANDENV)
850 {
851 struct wordsplit ws;
852
853 ws.ws_env = (const char **) environ_ptr (prog->v.p.env);
854 ws.ws_error = progman_ws_error;
855 if (wordsplit (prog->v.p.comp->command, &ws,
856 WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_NOCMD | WRDSF_ENV | WRDSF_ERROR))
857 {
858 logmsg (LOG_ERR, _("%s: can't split command line: %s"),
859 prog_tag (prog), wordsplit_strerror (&ws));
860 return -1;
861 }
862 wordsplit_get_words (&ws, &prog->v.p.argc, &prog->v.p.argv);
863 wordsplit_free (&ws);
864 }
865 else
866 {
867 prog->v.p.argc = prog->v.p.comp->argc;
868 prog->v.p.argv = prog->v.p.comp->argv;
869 }
870
871 if (debug_level >= 1 && prog->v.p.argv)
872 {
873 int i;
874 logmsg_printf (LOG_DEBUG, "executing");
875 for (i = 0; i < prog->v.p.argc; i++)
876 logmsg_printf (LOG_DEBUG, " %s", quotearg (prog->v.p.argv[i]));
877 logmsg_printf (LOG_DEBUG, "\n");
878 }
879 return 0;
880 }
881
882 static void
prog_start_prologue(struct prog * prog)883 prog_start_prologue (struct prog *prog)
884 {
885 if (prog->v.p.comp->dir)
886 {
887 debug (1, (_("chdir %s"), prog->v.p.comp->dir));
888 if (chdir (prog->v.p.comp->dir))
889 logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"),
890 prog_tag (prog), prog->v.p.comp->dir, strerror (errno));
891 }
892
893 pies_priv_setup (&prog->v.p.comp->privs);
894 if (prog->v.p.comp->umask)
895 umask (prog->v.p.comp->umask);
896
897 set_limits (prog_tag (prog),
898 prog->v.p.comp->limits ?
899 prog->v.p.comp->limits : pies_limits);
900 }
901
902 static void
prog_execute(struct prog * prog)903 prog_execute (struct prog *prog)
904 {
905 environ = environ_ptr (prog->v.p.env);
906 if (prog->v.p.comp->builtin)
907 {
908 mf_proctitle_format ("inetd %s",
909 prog->v.p.comp->builtin->service);
910 prog->v.p.comp->builtin->fun (0, prog->v.p.comp);
911 _exit (0);
912 }
913
914 execvp (prog->v.p.comp->program ?
915 prog->v.p.comp->program : prog->v.p.argv[0],
916 prog->v.p.argv);
917 //FIXME: pies_syslog?
918 syslog (LOG_CRIT, _("cannot start `%s': %s"), prog_tag (prog),
919 strerror (errno));
920 _exit (EX_SOFTWARE);
921 }
922
923 /*
924 * Run a TCPMUX component. This function is invoked from a child
925 * process.
926 */
927 void
progman_run_comp(struct component * comp,int fd,union pies_sockaddr_storage * sa,socklen_t salen)928 progman_run_comp (struct component *comp, int fd,
929 union pies_sockaddr_storage *sa, socklen_t salen)
930 {
931 struct prog *prog = register_prog0 (comp);
932 prog->v.p.socket = fd;
933 prog->v.p.sa_storage = *sa;
934 prog->v.p.sa_len = salen;
935 prog->v.p.cclass = conn_class_lookup (comp->tag, sa, salen);
936 if (prog_init (prog))
937 _exit (127);
938 prog_start_prologue (prog);
939 prog_sockenv (prog);
940 prog_execute (prog);
941 }
942
943 static void
prog_start(struct prog * prog)944 prog_start (struct prog *prog)
945 {
946 pid_t pid;
947 int redir[2];
948
949 if (prog->pid > 0 || !IS_COMPONENT (prog))
950 return;
951
952 if (is_sysvinit (prog->v.p.comp))
953 {
954 if (!SYSVINIT_ACTIVE)
955 {
956 if (prog->active)
957 {
958 logmsg (LOG_NOTICE, "disabling sysvinit component %s",
959 prog_tag (prog));
960 prog->v.p.status = status_stopped;
961 prog->active = 0;
962 }
963 return;
964 }
965 }
966
967 /* This call returns 1 in two cases: Either prog is marked as disabled,
968 in which case there's nothing more to do, or one or more of its
969 prerequisites are in status_stopping. In the latter case either the
970 components in question will exit or a SIGALRM will get delivered. In
971 both cases, it will cause further processing of `prog'. */
972 if (prog_start_prerequisites (prog))
973 return;
974
975 switch (prog->v.p.comp->mode)
976 {
977 case pies_comp_exec:
978 if (check_spawn_rate (prog))
979 return;
980 break;
981
982 case pies_comp_pass_fd:
983 if (check_spawn_rate (prog))
984 return;
985 debug (1, (_("unlinking %s"), prog->v.p.comp->pass_fd_socket));
986 if (unlink (prog->v.p.comp->pass_fd_socket) && errno != ENOENT)
987 {
988 logfuncall ("unlink", prog->v.p.comp->pass_fd_socket, errno);
989 return;
990 }
991 if (prog_open_socket (prog))
992 return;
993 break;
994
995 case pies_comp_accept:
996 if (check_spawn_rate (prog))
997 return;
998 if (prog_open_socket (prog))
999 return;
1000 break;
1001
1002 case pies_comp_inetd:
1003 /* Wait until an incoming connection is requested */
1004 if (prog->v.p.socket == -1)
1005 return;
1006
1007 default:
1008 break;
1009 }
1010
1011 debug (1, (_("starting %s"), prog_tag (prog)));
1012
1013 if (prog->v.p.comp->rmfile)
1014 {
1015 debug (1, (_("unlinking %s"), prog->v.p.comp->rmfile));
1016 if (unlink (prog->v.p.comp->rmfile) && errno != ENOENT)
1017 logmsg (LOG_ERR, _("%s: cannot remove file `%s': %s"),
1018 prog_tag (prog), prog->v.p.comp->rmfile, strerror (errno));
1019 }
1020
1021 if (prog->v.p.comp->builtin && prog->v.p.comp->builtin->single_process)
1022 {
1023 prog->v.p.comp->builtin->fun (prog->v.p.socket, prog->v.p.comp);
1024 return;
1025 }
1026
1027 if (prog_init (prog))
1028 return; //FIXME
1029
1030 redir[RETR_OUT] = open_redirector (prog, RETR_OUT,
1031 &prog->v.p.redir[RETR_OUT]);
1032 redir[RETR_ERR] = open_redirector (prog, RETR_ERR,
1033 &prog->v.p.redir[RETR_ERR]);
1034
1035 switch (pid = fork ())
1036 {
1037 /* The child branch. */
1038 case 0:
1039 signal_setup (SIG_DFL);
1040 setsid ();
1041 prog_start_prologue (prog);
1042 switch (prog->v.p.comp->mode)
1043 {
1044 case pies_comp_accept:
1045 case pies_comp_inetd:
1046 prog_sockenv (prog);
1047
1048 dup2 (prog->v.p.socket, 0);
1049 dup2 (prog->v.p.socket, 1);
1050 close (prog->v.p.socket);
1051 prog->v.p.socket = -1;
1052 break;
1053
1054 default:
1055 if (SYSVINIT_ACTIVE)
1056 {
1057 int fd = console_open (O_RDWR|O_NOCTTY);
1058 if (fd < 0)
1059 {
1060 logmsg (LOG_CRIT, "open(%s): %s",
1061 console_device, strerror (errno));
1062 fd = open ("/dev/null", O_RDWR);
1063 }
1064 if (fd != 0)
1065 dup2 (fd, 0);
1066 if (fd != 1)
1067 dup2 (fd, 1);
1068 if (fd != 2)
1069 dup2 (fd, 2);
1070 }
1071 else
1072 {
1073 if (prog->v.p.comp->flags & CF_NULLINPUT)
1074 {
1075 close(0);
1076 if (open("/dev/null", O_RDONLY) != 0)
1077 {
1078 logmsg (LOG_CRIT, "can't open /dev/null: %s",
1079 strerror(errno));
1080 _exit(127);
1081 }
1082 }
1083
1084 if (redir[RETR_OUT] == -1)
1085 {
1086 close (1);
1087 open ("/dev/null", O_WRONLY);
1088 }
1089 else if (redir[RETR_OUT] != 1)
1090 {
1091 dup2 (redir[RETR_OUT], 1);
1092 }
1093 }
1094 break;
1095 }
1096
1097 if (!SYSVINIT_ACTIVE)
1098 {
1099 if (redir[RETR_ERR] == -1)
1100 {
1101 if (!DIAG_OUTPUT (DIAG_TO_STDERR))
1102 {
1103 close (2);
1104 open ("/dev/null", O_WRONLY);
1105 }
1106 }
1107 else if (redir[RETR_ERR] != 1)
1108 {
1109 dup2 (redir[RETR_ERR], 2);
1110 }
1111 }
1112
1113 /* Close unneeded descripitors */
1114 pies_close_fds ((prog->v.p.comp->mode == pies_comp_pass_fd
1115 ? prog->v.p.socket : 2) + 1);
1116
1117 prog_execute (prog);
1118
1119
1120 case -1:
1121 logmsg (LOG_CRIT,
1122 _("cannot run `%s': fork failed: %s"),
1123 prog_tag (prog), strerror (errno));
1124 break;
1125
1126 default:
1127 if (prog->v.p.comp->mode == pies_comp_pass_fd)
1128 {
1129 pass_fd (prog->v.p.comp->pass_fd_socket, prog->v.p.socket,
1130 prog->v.p.comp->pass_fd_timeout ?
1131 prog->v.p.comp->pass_fd_timeout : DEFAULT_PASS_FD_TIMEOUT);
1132 /* FIXME: Error code */;
1133 }
1134 if (prog->v.p.comp->flags & CF_WAIT)
1135 {
1136 disable_socket (prog->v.p.socket);
1137 }
1138 else if (prog->v.p.comp->mode == pies_comp_accept ||
1139 prog->v.p.comp->mode == pies_comp_inetd ||
1140 prog->v.p.comp->mode == pies_comp_pass_fd)
1141 close (prog->v.p.socket);
1142 else if (is_sysvinit (prog->v.p.comp))
1143 sysvinit_acct (SYSV_ACCT_PROC_START, "", prog_tag (prog), pid, "");
1144
1145 if (redir[RETR_OUT] != -1)
1146 close (redir[RETR_OUT]);
1147 if (redir[RETR_ERR])
1148 close (redir[RETR_ERR]);
1149 prog->pid = pid;
1150 prog->v.p.status = status_running;
1151 debug (1, (_("%s started, pid=%lu"), prog_tag (prog),
1152 (unsigned long) pid));
1153 }
1154 }
1155
1156 int
check_acl(pies_acl_t acl,struct sockaddr * s,socklen_t salen,pies_identity_t identity)1157 check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
1158 pies_identity_t identity)
1159 {
1160 struct acl_input input;
1161 int rc;
1162
1163 if (!acl)
1164 return 0;
1165
1166 input.addr = s;
1167 input.addrlen = salen;
1168 input.identity = identity;
1169
1170 rc = pies_acl_check (acl, &input, 1);
1171 if (rc == 0)
1172 {
1173 char *p = sockaddr_to_astr (s, salen);
1174 logmsg (LOG_ERR, _("access from %s blocked"), p);
1175 free (p);
1176 return 1;
1177 }
1178
1179 return 0;
1180 }
1181
1182 void
fd_report(int fd,const char * msg)1183 fd_report (int fd, const char *msg)
1184 {
1185 size_t len;
1186
1187 if (!msg)
1188 return;
1189
1190 for (len = strlen (msg); len; )
1191 {
1192 ssize_t rc = write (fd, msg, len);
1193 if (rc == -1)
1194 {
1195 logmsg (LOG_ERR,
1196 _("error writing to socket: %s"),
1197 strerror (errno));
1198 break;
1199 }
1200 else if (rc == 0)
1201 break;
1202 len -= rc;
1203 msg += rc;
1204 }
1205 }
1206
1207 static int
_prog_accept(struct prog * p)1208 _prog_accept (struct prog *p)
1209 {
1210 int fd;
1211 struct prog *pinst;
1212 union pies_sockaddr_storage addr;
1213 socklen_t addrlen = sizeof addr;
1214 struct conn_class *pcclass;
1215
1216 fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen);
1217 if (fd == -1)
1218 {
1219 logfuncall ("accept", NULL, errno);
1220 return 1;
1221 }
1222
1223 if (debug_level >= 1)
1224 {
1225 char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
1226 logmsg (LOG_DEBUG, _("%s wants %s"), s, prog_tag (p));
1227 free (s);
1228 }
1229
1230 if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen, NULL)
1231 || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen, NULL))
1232 {
1233 fd_report (fd, p->v.p.comp->access_denied_message);
1234 close (fd);
1235 return 1;
1236 }
1237
1238 if (p->v.p.comp->max_instances &&
1239 p->v.p.num_instances >= p->v.p.comp->max_instances)
1240 {
1241 char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
1242 logmsg (LOG_ERR,
1243 _("%s: access from %s denied: too many instances running"),
1244 prog_tag (p), s);
1245 free (s);
1246 fd_report (fd, p->v.p.comp->max_instances_message);
1247 close (fd);
1248 return 1;
1249 }
1250
1251 pcclass = conn_class_lookup (prog_tag (p), &addr, addrlen);
1252 if (p->v.p.comp->max_ip_connections &&
1253 pcclass->count >= p->v.p.comp->max_ip_connections)
1254 {
1255 char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
1256 logmsg (LOG_ERR,
1257 _("%s: access from %s denied: "
1258 "too many connections from that ip"),
1259 prog_tag (p), s);
1260 free (s);
1261 fd_report (fd, p->v.p.comp->max_ip_connections_message);
1262 close (fd);
1263 return 1;
1264 }
1265
1266 if (check_connection_rate (p))
1267 {
1268 disable_socket (p->v.p.socket);
1269 close (fd);
1270 return 1;
1271 }
1272
1273 pcclass->count++;
1274
1275 if (debug_level > 1)
1276 conn_class_report (LOG_DEBUG, pcclass);
1277
1278 pinst = register_prog0 (p->v.p.comp);
1279 pinst->v.p.socket = fd;
1280 pinst->v.p.listener = p;
1281 pinst->v.p.sa_storage = addr;
1282 pinst->v.p.sa_len = addrlen;
1283 pinst->v.p.cclass = pcclass;
1284 prog_start (pinst);
1285 close (fd);
1286 pinst->v.p.socket = -1;
1287
1288 p->v.p.num_instances++;
1289 return 0;
1290 }
1291
1292 static int
_prog_wait(struct prog * p)1293 _prog_wait (struct prog *p)
1294 {
1295 struct prog *pinst;
1296
1297 debug (1, (_("someone wants %s"), prog_tag (p)));
1298
1299 if (p->v.p.comp->max_instances
1300 && p->v.p.num_instances >= p->v.p.comp->max_instances)
1301 {
1302 logmsg (LOG_ERR,
1303 _("%s: too many instances running, dropping connection"),
1304 prog_tag (p));
1305 return 1;
1306 }
1307
1308 pinst = register_prog0 (p->v.p.comp);
1309 pinst->v.p.socket = p->v.p.socket;
1310 pinst->v.p.listener = p;
1311 prog_start (pinst);
1312
1313 pinst->v.p.socket = -1;
1314
1315 p->v.p.num_instances++;
1316 return 0;
1317 }
1318
1319 int
progman_accept(int socket,void * data)1320 progman_accept (int socket, void *data)
1321 {
1322 struct prog *p = data;
1323
1324 if (p->v.p.comp->socket_type == SOCK_STREAM
1325 && !(p->v.p.comp->flags & CF_WAIT))
1326 return _prog_accept (p);
1327
1328 return _prog_wait (p);
1329 }
1330
1331 static int
prog_create_socket(struct prog * prog,void * data)1332 prog_create_socket (struct prog *prog, void *data)
1333 {
1334 if (IS_COMPONENT (prog) && prog->v.p.status == status_listener)
1335 {
1336 struct component *comp = prog->v.p.comp;
1337 if (!ISCF_TCPMUX (comp->flags) && prog->v.p.socket == -1)
1338 {
1339 int fd = create_socket (comp->socket_url,
1340 comp->socket_type,
1341 comp->privs.user, comp->umask);
1342 if (fd == -1)
1343 destroy_prog (&prog);
1344 else if (register_program_socket (comp->socket_type, fd, prog, NULL))
1345 {
1346 close (fd);
1347 destroy_prog (&prog);
1348 }
1349 else
1350 prog->v.p.socket = fd;
1351 }
1352 }
1353 return 0;
1354 }
1355
1356 void
progman_create_sockets(void)1357 progman_create_sockets (void)
1358 {
1359 progman_foreach (prog_create_socket, NULL);
1360 }
1361
1362 void
progman_recompute_alarm(void)1363 progman_recompute_alarm (void)
1364 {
1365 struct prog *prog;
1366 time_t now = time (NULL);
1367 time_t alarm_time = 0, x;
1368
1369 debug (2, ("Recomputing alarm settings"));
1370 for (prog = proghead; prog; prog = prog->next)
1371 if (IS_COMPONENT (prog))
1372 {
1373 switch (prog->v.p.status)
1374 {
1375 case status_sleeping:
1376 x = SLEEPTIME - (now - prog->v.p.timestamp);
1377 if (alarm_time == 0 || x < alarm_time)
1378 alarm_time = x;
1379 break;
1380
1381 case status_stopping:
1382 x = shutdown_timeout - (now - prog->v.p.timestamp);
1383 if (alarm_time == 0 || x < alarm_time)
1384 alarm_time = x;
1385 break;
1386
1387 default:
1388 break;
1389 }
1390 }
1391 debug (2, ("alarm=%lu", (unsigned long)alarm_time));
1392 if (alarm_time)
1393 alarm (alarm_time);
1394 }
1395
1396 void
program_init_startup(void)1397 program_init_startup (void)
1398 {
1399 struct prog *prog;
1400
1401 for (prog = proghead; prog; prog = prog->next)
1402 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
1403 {
1404 debug (1, ("running startup components"));
1405 break;
1406 }
1407
1408 for (; prog; prog = prog->next)
1409 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup)
1410 {
1411 prog_start (prog);
1412 }
1413 }
1414
1415 void
progman_start(void)1416 progman_start (void)
1417 {
1418 struct prog *prog;
1419
1420 if (progman_waiting_p ())
1421 /* Noting to do if there are processes left in the previous runlevel
1422 (in sysv-init mode) or startup components running. */
1423 return;
1424
1425 debug (1, ("starting components"));
1426 for (prog = proghead; prog; prog = prog->next)
1427 if (IS_COMPONENT (prog))
1428 {
1429 switch (prog->v.p.status)
1430 {
1431 case status_stopped:
1432 case status_sleeping:
1433 prog_start (prog);
1434 break;
1435
1436 case status_running:
1437 case status_stopping:
1438 case status_finished:
1439 break;
1440
1441 case status_listener:
1442 if (!prog->active)
1443 disable_socket (prog->v.p.socket);
1444 else
1445 enable_socket (prog->v.p.socket);
1446 }
1447 }
1448 }
1449
1450 static void
check_stopping(struct prog * prog,time_t now)1451 check_stopping (struct prog *prog, time_t now)
1452 {
1453 if (now - prog->v.p.timestamp >= shutdown_timeout)
1454 {
1455 if (prog->pid == 0)
1456 logmsg (LOG_EMERG,
1457 _("INTERNAL ERROR: attempting to kill nonexistent process %s"),
1458 prog_tag (prog));
1459 else if (prog->v.p.comp->flags & CF_SIGGROUP)
1460 kill (-prog->pid, SIGKILL);
1461 else
1462 kill (prog->pid, SIGKILL);
1463 }
1464 else
1465 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
1466 }
1467
1468 void
progman_wake_sleeping(int onalrm)1469 progman_wake_sleeping (int onalrm)
1470 {
1471 struct prog *prog;
1472 time_t now = time (NULL);
1473
1474 debug (1, (_("checking for components to start")));
1475
1476 for (prog = proghead; prog; prog = prog->next)
1477 {
1478 if (IS_ACTIVE_COMPONENT (prog) && prog->wait)
1479 {
1480 /* The following works on the assumption that prog->wait is
1481 set when enabling the component and gets cleared right after
1482 it has finished. */
1483 if (prog->v.p.status != status_running)
1484 prog_start (prog);
1485 return;
1486 }
1487 }
1488
1489 for (prog = proghead; prog; prog = prog->next)
1490 switch (prog->v.p.status)
1491 {
1492 case status_sleeping:
1493 if (IS_ACTIVE_COMPONENT (prog))
1494 {
1495 if (now - prog->v.p.timestamp >= SLEEPTIME)
1496 {
1497 if (prog->v.p.comp->mode == pies_comp_inetd)
1498 {
1499 prog->v.p.status = status_listener;
1500 enable_socket (prog->v.p.socket);
1501 }
1502 else
1503 {
1504 prog->v.p.status = status_running;
1505 prog->v.p.failcount = 0;
1506 prog->v.p.timestamp = 0;
1507 prog_start (prog);
1508 }
1509 }
1510 /* If there is no alarm pending, recompute next alarm.
1511 This allows to cope with eventual clock inaccuracies. */
1512 if (onalrm)
1513 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
1514 }
1515 break;
1516
1517 case status_stopping:
1518 check_stopping (prog, now);
1519 break;
1520
1521 case status_stopped:
1522 if (IS_ACTIVE_COMPONENT (prog))
1523 prog_start (prog);
1524 break;
1525
1526 default:
1527 break;
1528 }
1529 }
1530
1531 static int
prog_start_prerequisites(struct prog * prog)1532 prog_start_prerequisites (struct prog *prog)
1533 {
1534 int ret = 0;
1535 pies_depmap_pos_t pos;
1536 struct component *comp;
1537 int warned = 0;
1538
1539 if (!prog->active)
1540 return 1;
1541 for (comp = component_depmap_first (depmap_col, prog->v.p.comp->arridx, &pos);
1542 comp;
1543 comp = component_depmap_next (pos))
1544 {
1545 struct prog *p;
1546
1547 if (!comp->prog || comp->flags & CF_PRECIOUS)
1548 continue;
1549 if (!warned)
1550 {
1551 debug (1, ("starting prerequisites of %s", prog_tag (prog)));
1552 warned = 1;
1553 }
1554
1555 if (!prog->active)
1556 return 1;
1557
1558 p = comp->prog;
1559 switch (p->v.p.status)
1560 {
1561 case status_running:
1562 continue;
1563
1564 case status_stopped:
1565 break;
1566
1567 case status_listener:
1568 continue;
1569
1570 case status_sleeping:
1571 /* FIXME: What to do in this case? */
1572 break;
1573
1574 case status_stopping:
1575 check_stopping (p, time (NULL));
1576 ret = 1;
1577 continue;
1578
1579 case status_finished:
1580 continue;
1581 }
1582 prog_start (p);
1583 if (p->v.p.comp->mode == pies_comp_once
1584 || p->v.p.status != status_running)//FIXME
1585 ret = 1;
1586 }
1587 depmap_end (pos);
1588
1589 return ret;
1590 }
1591
1592 void
prog_stop_dependents(struct prog * prog)1593 prog_stop_dependents (struct prog *prog)
1594 {
1595 struct component *comp;
1596 pies_depmap_pos_t pos;
1597 int warned = 0;
1598
1599 prog_stop_redirectors (prog);
1600 for (comp = component_depmap_first (depmap_row, prog->v.p.comp->arridx, &pos);
1601 comp;
1602 comp = component_depmap_next (pos))
1603 {
1604 struct prog *dp = comp->prog;
1605 if (!dp) /* should not happen */
1606 continue;
1607 if (!warned && dp->pid)
1608 {
1609 debug (1, ("stopping dependencies of %s", prog_tag (prog)));
1610 warned = 1;
1611 }
1612 prog_stop (dp, SIGTERM);
1613 }
1614 depmap_end (pos);
1615 }
1616
1617 void
prog_stop(struct prog * prog,int sig)1618 prog_stop (struct prog *prog, int sig)
1619 {
1620 if (prog->pid == 0)
1621 return;
1622 if (prog->type == TYPE_COMPONENT)
1623 {
1624 if (prog->v.p.status == status_running)
1625 {
1626 prog->v.p.status = status_stopping;
1627 prog->v.p.timestamp = time (NULL);
1628 pies_schedule_children (PIES_CHLD_RESCHEDULE_ALARM);
1629 }
1630 }
1631 debug (1, ("stopping %s (%lu)", prog_tag (prog), (unsigned long) prog->pid));
1632 if (prog->type == TYPE_COMPONENT && prog->v.p.comp->flags & CF_SIGGROUP)
1633 kill (-prog->pid, sig);
1634 else
1635 kill (prog->pid, sig);
1636 }
1637
1638 static void
print_status(const char * tag,pid_t pid,int status,int expect_term)1639 print_status (const char *tag, pid_t pid, int status, int expect_term)
1640 {
1641 int prio;
1642
1643 if (SYSVINIT_ACTIVE)
1644 {
1645 if (debug_level <= 1)
1646 return;
1647 prio = LOG_DEBUG;
1648 }
1649 else
1650 prio = LOG_ERR;
1651
1652 if (WIFEXITED (status))
1653 {
1654 if (WEXITSTATUS (status) == 0)
1655 debug (1, (_("%s (%lu) exited successfully"),
1656 tag, (unsigned long) pid));
1657 else
1658 logmsg (prio, _("%s (%lu) exited with status %d"),
1659 tag, (unsigned long) pid,
1660 WEXITSTATUS (status));
1661 }
1662 else if (WIFSIGNALED (status))
1663 {
1664 char const *coremsg = "";
1665
1666 if (expect_term && WTERMSIG (status) == SIGTERM)
1667 prio = LOG_DEBUG;
1668
1669 #ifdef WCOREDUMP
1670 if (WCOREDUMP (status))
1671 coremsg = _(" (core dumped)");
1672 #endif
1673 logmsg (prio, _("%s (%lu) terminated on signal %d%s"),
1674 tag, (unsigned long) pid,
1675 WTERMSIG (status), coremsg);
1676 }
1677 else if (WIFSTOPPED (status))
1678 logmsg (prio, _("%s (%lu) stopped on signal %d"),
1679 tag, (unsigned long) pid,
1680 WSTOPSIG (status));
1681 else
1682 logmsg (prio, _("%s (%lu) terminated with unrecognized status: %d"),
1683 tag, (unsigned long) pid, status);
1684 }
1685
1686 static void propagate_child_exit (pid_t) ATTRIBUTE_NORETURN;
1687
1688 static void
propagate_child_exit(pid_t pid)1689 propagate_child_exit (pid_t pid)
1690 {
1691 int wait_status;
1692
1693 while (waitpid (pid, &wait_status, 0) == -1)
1694 if (errno != EINTR)
1695 {
1696 logfuncall ("waitpid", NULL, errno);
1697 exit (EX_OSERR);
1698 }
1699
1700 if (WIFSIGNALED (wait_status))
1701 {
1702 int sig = WTERMSIG (wait_status);
1703 signal (sig, SIG_DFL);
1704 raise (sig);
1705 }
1706 else if (WIFEXITED (wait_status))
1707 exit (WEXITSTATUS (wait_status));
1708 exit (127);
1709 }
1710
1711 char *
wordsplit_string(struct wordsplit const * ws)1712 wordsplit_string (struct wordsplit const *ws)
1713 {
1714 char *ret, *p;
1715 size_t count = ws->ws_wordc + ws->ws_offs;
1716 char **argv = grecs_calloc (count, sizeof (argv[0]));
1717 size_t i;
1718 size_t len = 0;
1719
1720 for (i = 0; i < count; i++)
1721 {
1722 argv[i] = quotearg_n (i, ws->ws_wordv[i]);
1723 len += strlen (argv[i]);
1724 }
1725 len += count;
1726 ret = grecs_malloc (len);
1727
1728 for (i = 0, p = ret; i < count; i++)
1729 {
1730 strcpy (p, argv[i]);
1731 p += strlen (argv[i]);
1732 *p++ = ' ';
1733 }
1734 p[-1] = 0;
1735 free (argv);
1736 return ret;
1737 }
1738
1739 void
send_msg(char * rcpts,const char * msg_text)1740 send_msg (char *rcpts, const char *msg_text)
1741 {
1742 int i, j, k;
1743 pid_t child_pid, grand_child_pid;
1744 struct wordsplit ws;
1745 int p[2];
1746 size_t size;
1747
1748 ws.ws_offs = mailer_argc;
1749 ws.ws_delim = ",";
1750 if (wordsplit (rcpts, &ws,
1751 WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | WRDSF_DOOFFS))
1752 {
1753 logmsg (LOG_ERR,
1754 _("cannot parse recipient address list (%s)"),
1755 rcpts);
1756 return;
1757 }
1758
1759 debug (1, (_("sending notification to %s"), rcpts));
1760
1761 /* Copy mailer arguments */
1762 for (i = 0; i < mailer_argc; i++)
1763 ws.ws_wordv[i] = mailer_argv[i];
1764 /* j - number of the recipient;
1765 i - index of the ws_wordv being converted;
1766 k - index of the ws_wordv to store the converted value to.
1767
1768 Normally i == k, unless there are some invalid ws_wordv's,
1769 in which case i > k.
1770 */
1771 for (j = 0, k = i; j < ws.ws_wordc; j++, i++)
1772 {
1773 char *arg = ws.ws_wordv[i];
1774 size_t len;
1775
1776 while (*arg && c_isblank (*arg))
1777 arg++;
1778 len = strlen (arg);
1779 if (len > 0)
1780 {
1781 while (len > 0 && c_isblank (arg[len - 1]))
1782 len--;
1783 }
1784 if (len == 0)
1785 continue;
1786 if (arg[0] == '<' && arg[len-1] == '>')
1787 {
1788 arg++;
1789 len -= 2;
1790 }
1791 if (len == 0)
1792 continue;
1793 memmove (ws.ws_wordv[k], arg, len);
1794 ws.ws_wordv[k][len] = 0;
1795 k++;
1796 }
1797 ws.ws_wordv[k] = NULL;
1798
1799 /* Fork a child: */
1800 child_pid = fork ();
1801
1802 if (child_pid < 0)
1803 {
1804 wordsplit_free (&ws);
1805 logmsg (LOG_ERR,
1806 _("cannot send mail: fork failed: %s"), strerror (errno));
1807 return;
1808 }
1809
1810 if (child_pid)
1811 {
1812 char *cmd = wordsplit_string (&ws);
1813 wordsplit_free (&ws);
1814 debug (1, (_("started mailer: %s, pid=%lu"),
1815 cmd, (unsigned long) child_pid));
1816 register_command (mailer_program, cmd, child_pid);
1817 return;
1818 }
1819
1820 /* Child process */
1821 /* ============= */
1822 signal_setup (SIG_DFL);
1823 setsid ();
1824 if (pipe (p))
1825 {
1826 logmsg (LOG_ERR, _("cannot send mail: pipe failed: %s"),
1827 strerror (errno));
1828 wordsplit_free (&ws);
1829 exit (EX_OSERR);
1830 }
1831
1832 grand_child_pid = fork ();
1833 if (grand_child_pid < 0)
1834 {
1835 logmsg (LOG_ERR,
1836 _("cannot send mail: fork failed: %s"), strerror (errno));
1837 return;
1838 }
1839
1840 if (grand_child_pid == 0)
1841 {
1842 /* Grand-child */
1843 /* =========== */
1844 if (p[0] != 0 && p[1] != 0)
1845 close (0);
1846 close (p[1]);
1847 dup2 (p[0], 0);
1848 execv (mailer_program, ws.ws_wordv);
1849 exit (127);
1850 }
1851
1852 /* Child again */
1853 close (p[0]);
1854
1855 size = strlen (msg_text);
1856 while (size)
1857 {
1858 ssize_t rc = write (p[1], msg_text, size);
1859 if (rc <= 0)
1860 {
1861 logmsg (LOG_ERR, _("cannot write to pipe: %s"),
1862 rc == 0 ? "EOF" : strerror (errno));
1863 break;
1864 }
1865 size -= rc;
1866 msg_text += rc;
1867 }
1868 close (p[1]);
1869
1870 propagate_child_exit (grand_child_pid);
1871 }
1872
1873 static const char default_termination_message[] =
1874 "From: <>\n"
1875 "X-Agent: ${canonical_program_name} (${package} ${version})\n"
1876 "Subject: Component ${component} ${termination} ${retcode}.\n"
1877 "\n";
1878
1879 struct notify_closure
1880 {
1881 const char *tag;
1882 int status;
1883 struct action *act;
1884 };
1885
1886 static int
notify_get_tag(char ** ret,void * data)1887 notify_get_tag (char **ret, void *data)
1888 {
1889 struct notify_closure const *clos = data;
1890 char *s = strdup (clos->tag);
1891 if (!s)
1892 return WRDSE_NOSPACE;
1893 *ret = s;
1894 return WRDSE_OK;
1895 }
1896
1897 static int
notify_get_termination(char ** ret,void * data)1898 notify_get_termination (char **ret, void *data)
1899 {
1900 struct notify_closure const *clos = data;
1901 char const *msg;
1902 char *s;
1903
1904 if (WIFEXITED (clos->status))
1905 /* TRANSLATORS: The subject of this statement is 'component' */
1906 msg = _("exited with code");
1907 else if (WIFSIGNALED (clos->status))
1908 /* TRANSLATORS: The subject of this statement is 'component' */
1909 msg = _("terminated on signal");
1910 else
1911 msg = "UNKNOWN";
1912
1913 s = strdup (msg);
1914 if (!s)
1915 return WRDSE_NOSPACE;
1916 *ret = s;
1917 return WRDSE_OK;
1918 }
1919
1920 static int
notify_get_retcode(char ** ret,void * data)1921 notify_get_retcode (char **ret, void *data)
1922 {
1923 struct notify_closure const *clos = data;
1924 char *s = NULL;
1925 size_t l = 0;
1926
1927 if (WIFEXITED (clos->status))
1928 grecs_asprintf (&s, &l, "%d", WEXITSTATUS (clos->status));
1929 else if (WIFSIGNALED (clos->status))
1930 grecs_asprintf (&s, &l, "%d", WTERMSIG (clos->status));
1931 else
1932 s = strdup ("UNKNOWN");
1933 if (!s)
1934 return WRDSE_NOSPACE;
1935 *ret = s;
1936 return WRDSE_OK;
1937 }
1938
1939 struct notify_variable
1940 {
1941 char *name;
1942 size_t name_length;
1943 int (*get) (char **ret, void *data);
1944 };
1945
1946 static struct notify_variable notify_vartab[] = {
1947 #define S(s) #s, sizeof(#s)-1
1948 { S(component), notify_get_tag },
1949 { S(termination), notify_get_termination },
1950 { S(retcode), notify_get_retcode },
1951 #undef S
1952 { NULL }
1953 };
1954
1955 static int
notify_getvar(char ** ret,const char * vptr,size_t vlen,void * data)1956 notify_getvar (char **ret, const char *vptr, size_t vlen, void *data)
1957 {
1958 struct notify_variable *var;
1959 for (var = notify_vartab; var->name; var++)
1960 if (var->name_length == vlen && memcmp (var->name, vptr, vlen) == 0)
1961 return var->get (ret, data);
1962 return WRDSE_UNDEF;
1963 }
1964
1965 static void
notify(const char * tag,int status,struct action * act)1966 notify (const char *tag, int status, struct action *act)
1967 {
1968 const char *env[] = {
1969 #define PROGRAM_NAME_IDX 1
1970 "program_name", NULL,
1971 #define INSTANCE_IDX 3
1972 "instance", NULL,
1973 "canonical_program_name", "pies",
1974 "package", PACKAGE_NAME,
1975 "version", PACKAGE_VERSION,
1976 NULL
1977 };
1978 struct wordsplit ws;
1979 struct notify_closure closure;
1980
1981 closure.tag = tag;
1982 closure.status = status;
1983 closure.act = act;
1984
1985 env[PROGRAM_NAME_IDX] = program_name;
1986 env[INSTANCE_IDX] = instance;
1987
1988 ws.ws_env = env;
1989 ws.ws_getvar = notify_getvar;
1990 ws.ws_closure = &closure;
1991 if (wordsplit (act->message ? act->message : default_termination_message,
1992 &ws,
1993 WRDSF_NOSPLIT | WRDSF_NOCMD | WRDSF_QUOTE |
1994 WRDSF_ENV | WRDSF_ENV_KV |
1995 WRDSF_GETVAR | WRDSF_CLOSURE))
1996 {
1997 logmsg (LOG_ERR, "wordsplit: %s", wordsplit_strerror (&ws));
1998 return;
1999 }
2000 send_msg (act->addr, ws.ws_wordv[0]);
2001 wordsplit_free (&ws);
2002 }
2003
2004 static int
status_matches_p(struct action * act,unsigned status)2005 status_matches_p (struct action *act, unsigned status)
2006 {
2007 int i;
2008
2009 if (act->nstat == 0)
2010 return 1;
2011 for (i = 0; i < act->nstat; i++)
2012 if (act->status[i] == status)
2013 return 1;
2014 return 0;
2015 }
2016
2017 static void
run_command(struct action * act,struct prog * prog,unsigned retcode,pid_t child_pid)2018 run_command (struct action *act, struct prog *prog, unsigned retcode,
2019 pid_t child_pid)
2020 {
2021 pid_t pid, master_pid;
2022 char *argv[4];
2023 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
2024
2025 master_pid = getpid ();
2026
2027 /* FIXME: optionally set output redirectors for this command? */
2028 pid = fork ();
2029
2030 if (pid == (pid_t) -1)
2031 {
2032 logmsg (LOG_ERR, "fork: %s", strerror (errno));
2033 return;
2034 }
2035
2036 if (pid == 0)
2037 {
2038 debug (1, (_("executing %s"), act->command));
2039 /* Child */
2040 setsid ();
2041 setenv ("PIES_VERSION", PACKAGE_VERSION, 1);
2042 setenv ("PIES_COMPONENT", prog_tag (prog), 1);
2043 setenv ("PIES_MASTER_PID", umaxtostr (master_pid, buf), 1);
2044 setenv ("PIES_PID", umaxtostr (child_pid, buf), 1);
2045 if (retcode & STATUS_SIG_BIT)
2046 setenv ("PIES_SIGNAL", umaxtostr (STATUS_CODE (retcode), buf), 1);
2047 else
2048 setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1);
2049
2050 pies_close_fds (3);
2051
2052 argv[0] = "/bin/sh";
2053 argv[1] = "-c";
2054 argv[2] = act->command;
2055 argv[3] = NULL;
2056
2057 execv (argv[0], argv);
2058 exit (127);
2059 }
2060
2061 /* Master */
2062 debug (1, (_("started command: %s, pid=%lu"),
2063 act->command, (unsigned long) pid));
2064 register_command ((char*) _("[action]"), grecs_strdup (act->command), pid);
2065 }
2066
2067 static void
react(struct prog * prog,int status,pid_t pid)2068 react (struct prog *prog, int status, pid_t pid)
2069 {
2070 unsigned retcode;
2071 struct grecs_list *list = prog->v.p.comp->act_list;
2072
2073 if (!list)
2074 list = default_component.act_list;
2075
2076 if (WIFEXITED (status))
2077 {
2078 retcode = WEXITSTATUS (status);
2079 debug (1, (_("%s: terminated with code %d"), prog_tag (prog), retcode));
2080 }
2081 else if (WIFSIGNALED (status))
2082 {
2083 retcode = WTERMSIG (status);
2084 debug (1, (_("%s: terminated on signal %d"), prog_tag (prog), retcode));
2085 retcode |= STATUS_SIG_BIT;
2086 }
2087 else
2088 {
2089 debug (1, (_("%s: unrecognized termination status"), prog_tag (prog)));
2090 /* Enforce default action: */
2091 list = NULL;
2092 }
2093
2094 if (list)
2095 {
2096 struct grecs_list_entry *ep;
2097 for (ep = list->head; ep; ep = ep->next)
2098 {
2099 struct action *act = ep->data;
2100
2101 if (status_matches_p (act, retcode))
2102 {
2103 if (act->command)
2104 {
2105 run_command (act, prog, retcode, pid);
2106 }
2107
2108 switch (act->act)
2109 {
2110 case action_restart:
2111 if (prog->v.p.comp->mode != pies_comp_inetd)
2112 prog_start (prog);
2113 break;
2114
2115 case action_disable:
2116 logmsg (LOG_NOTICE, _("disabling component %s"),
2117 prog_tag (prog));
2118 prog->active = 0;
2119 /* FIXME:
2120 if (prog->v.p.comp->mode == pies_comp_inetd)
2121 disable_socket (prog->v.p.socket);
2122 */
2123 }
2124 if (act->addr)
2125 notify (prog_tag (prog), status, act);
2126 break;
2127 }
2128 }
2129 }
2130
2131 if (!list && prog->v.p.comp->mode != pies_comp_inetd)
2132 /* Default action: */
2133 prog_start (prog);
2134 }
2135
2136 void
progman_cleanup(int expect_term)2137 progman_cleanup (int expect_term)
2138 {
2139 pid_t pid;
2140 int status;
2141
2142 if (!expect_term)
2143 expect_term = progman_waiting_p ();
2144 while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
2145 {
2146 struct prog *prog = prog_lookup_by_pid (pid);
2147 if (!prog)
2148 {
2149 print_status (_("unknown child"), pid, status, expect_term);
2150 continue;
2151 }
2152 prog->pid = 0;
2153 switch (prog->type)
2154 {
2155 case TYPE_COMPONENT:
2156 print_status (prog_tag (prog), pid, status, expect_term);
2157 prog->stop = 0;
2158 if (prog->v.p.comp->mode == pies_comp_inetd)
2159 {
2160 struct prog *listener = prog->v.p.listener;
2161
2162 listener->v.p.num_instances--;
2163 if (prog->v.p.cclass)
2164 {
2165 prog->v.p.cclass->count--;
2166 if (debug_level > 1)
2167 conn_class_report (LOG_DEBUG, prog->v.p.cclass);
2168 if (prog->v.p.cclass->count == 0)
2169 {
2170 conn_class_remove (prog->v.p.cclass);
2171 prog->v.p.cclass = NULL;
2172 }
2173 }
2174
2175 prog_stop_redirectors (prog);
2176 if (listener->v.p.num_instances == 0
2177 && !component_is_active (prog->v.p.comp))
2178 destroy_prog (&listener);
2179 else
2180 {
2181 if (!expect_term)
2182 react (listener, status, pid);
2183 if (listener->v.p.comp->flags & CF_WAIT)
2184 enable_socket (listener->v.p.socket);
2185 }
2186 destroy_prog (&prog);
2187 }
2188 else
2189 {
2190 if (PIES_SYSVINIT_ENABLED
2191 && prog->v.p.comp->mode >= pies_mark_sysvinit
2192 && prog->v.p.comp->mode != pies_comp_ondemand)
2193 {
2194 sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog_tag (prog),
2195 pid, "");
2196 prog->v.p.status = status_finished;
2197
2198 if (prog->wait)
2199 {
2200 pies_schedule_children (PIES_CHLD_WAKEUP);
2201 prog->wait = 0;
2202 }
2203 }
2204 else if (prog->v.p.comp->mode == pies_comp_startup)
2205 {
2206 prog->v.p.status = status_finished;
2207 if (!progman_startup_phase ())
2208 pies_schedule_children (PIES_CHLD_WAKEUP);
2209 }
2210 else
2211 {
2212 if (is_sysvinit (prog->v.p.comp))
2213 sysvinit_acct (SYSV_ACCT_PROC_STOP, "",
2214 prog_tag (prog), pid, "");
2215
2216 prog->v.p.status = status_stopped;
2217 prog_stop_dependents (prog);
2218 if (!expect_term)
2219 react (prog, status, pid);
2220 }
2221
2222 if (!component_is_active (prog->v.p.comp))
2223 destroy_prog (&prog);
2224 }
2225
2226 break;
2227
2228 case TYPE_COMMAND:
2229 print_status (prog_tag (prog), pid, status, expect_term);
2230 destroy_prog (&prog);
2231 break;
2232 }
2233 }
2234
2235 if (!expect_term)
2236 /* This will also recompute alarm settings, if necessary */
2237 progman_wake_sleeping (0);
2238 }
2239
2240 void
progman_stop_component(struct prog ** progptr)2241 progman_stop_component (struct prog **progptr)
2242 {
2243 struct prog *prog = *progptr;
2244 if (prog && IS_COMPONENT (prog))
2245 {
2246 switch (prog->v.p.status)
2247 {
2248 case status_running:
2249 logmsg (LOG_INFO, _("stopping component %s"), prog_tag (prog));
2250 prog_stop (prog, SIGTERM);
2251 break;
2252
2253 case status_listener:
2254 prog_deactivate_listener (prog);
2255 /* fall through */
2256 case status_stopped:
2257 prog->stop = 0;
2258 if (!component_is_active (prog->v.p.comp))
2259 destroy_prog (progptr);
2260 break;
2261
2262 case status_sleeping:
2263 if (!component_is_active (prog->v.p.comp))
2264 destroy_prog (progptr);
2265 else if (prog->stop)
2266 prog->stop = 0;
2267 else
2268 {
2269 logmsg (LOG_INFO, _("waking up component %s"), prog_tag (prog));
2270 prog->v.p.failcount = 0;
2271 }
2272 break;
2273
2274 case status_stopping:
2275 break;
2276
2277 case status_finished:
2278 prog->stop = 0;
2279 if (!component_is_active (prog->v.p.comp))
2280 destroy_prog (progptr);
2281 else
2282 logmsg (LOG_INFO,
2283 _("stopping component %s: component not started"),
2284 prog_tag (prog));
2285 }
2286 }
2287 }
2288
2289 void
prog_deactivate_listener(struct prog * prog)2290 prog_deactivate_listener (struct prog *prog)
2291 {
2292 logmsg (LOG_INFO, _("deactivating listener %s"), prog_tag (prog));
2293 if (prog->v.p.socket != -1)
2294 {
2295 deregister_socket (prog->v.p.socket);
2296 prog->v.p.socket = -1;
2297 }
2298 }
2299
2300 int
prog_activate_listener(struct prog * prog)2301 prog_activate_listener (struct prog *prog)
2302 {
2303 struct component *comp = prog->v.p.comp;
2304
2305 logmsg (LOG_INFO, _("activating listener %s"), prog_tag (prog));
2306 if (comp->mode == pies_comp_inetd && !ISCF_TCPMUX (comp->flags)
2307 && prog->v.p.socket == -1)
2308 {
2309 int fd = create_socket (comp->socket_url,
2310 comp->socket_type,
2311 comp->privs.user, comp->umask);
2312 if (fd == -1)
2313 return -1;
2314 else if (register_program_socket (comp->socket_type, fd, prog, NULL))
2315 {
2316 close (fd);
2317 return -1;
2318 }
2319 else
2320 prog->v.p.socket = fd;
2321 }
2322 return 0;
2323 }
2324
2325 /* Starting at PROG, find first program component marked for termination. */
2326 static struct prog *
prog_to_stop(struct prog * prog)2327 prog_to_stop (struct prog *prog)
2328 {
2329 for (; prog; prog = prog->next)
2330 if (IS_COMPONENT (prog) && prog->stop)
2331 break;
2332 return prog;
2333 }
2334
2335 #define DIAG_CON \
2336 (SYSVINIT_ACTIVE ? (DIAG_TO_STDERR|DIAG_REOPEN_LOG) : diag_output)
2337
2338 /* Stop all program components marked for termination. Wait at most
2339 2*shutdown_timeout seconds. */
2340 void
progman_gc(void)2341 progman_gc (void)
2342 {
2343 time_t start;
2344 struct prog *prog, *next;
2345
2346 /* Find first marked prog */
2347 prog = prog_to_stop (proghead);
2348 if (!prog)
2349 return;
2350
2351 /* First round: */
2352 /* Gracefully stop it and all marked programs that follow */
2353 diagmsg (DIAG_CON, LOG_INFO, "Sending processes the TERM signal");
2354 start = time (NULL);
2355 do
2356 {
2357 next = prog->next;
2358 progman_stop_component (&prog);
2359 }
2360 while ((prog = prog_to_stop (next)));
2361
2362 /* Wait for them to terminate */
2363 while (1)
2364 {
2365 progman_cleanup (1);
2366 prog = prog_to_stop (proghead);
2367 if (!prog)
2368 return;
2369 if (time (NULL) - start < shutdown_timeout)
2370 sleep (1);
2371 else
2372 break;
2373 }
2374
2375 /* Second round: */
2376 /* Kill the remaining programs with SIGKILL */
2377 diagmsg (DIAG_CON, LOG_INFO, "Sending processes the KILL signal");
2378 start = time (NULL);
2379 do
2380 {
2381 next = prog->next;
2382 prog_stop (prog, SIGKILL);
2383 }
2384 while ((prog = prog_to_stop (next)));
2385
2386 /* Wait for them to terminate */
2387 while (1)
2388 {
2389 progman_cleanup (1);
2390 prog = prog_to_stop (proghead);
2391 if (!prog)
2392 return;
2393 if (time (NULL) - start < shutdown_timeout)
2394 sleep (1);
2395 else
2396 break;
2397 }
2398
2399 /* FIXME: Report remaining programs */
2400
2401 }
2402
2403 static int
start_shutdown(struct prog * prog,void * data)2404 start_shutdown (struct prog *prog, void *data)
2405 {
2406 if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_shutdown)
2407 {
2408 int *p = data;
2409 if (!*p)
2410 {
2411 diagmsg (DIAG_CON, LOG_INFO, "Starting shutdown components");
2412 *p = 1;
2413 }
2414 prog->active = 1;
2415 prog_start (prog);
2416 prog->stop = 1;
2417 }
2418 return 0;
2419 }
2420
2421 void
program_shutdown(void)2422 program_shutdown (void)
2423 {
2424 time_t start = time (NULL);
2425 int sd = 0;
2426
2427 /* Activate shutdown components. */
2428 progman_foreach (start_shutdown, &sd);
2429 while (prog_to_stop (proghead))
2430 {
2431 progman_cleanup (1);
2432 if (time (NULL) - start < shutdown_timeout)
2433 sleep (1);
2434 else
2435 {
2436 progman_gc ();
2437 break;
2438 }
2439 }
2440 }
2441
2442 static int
mark_for_stopping(struct prog * prog,void * data)2443 mark_for_stopping (struct prog *prog, void *data)
2444 {
2445 if (IS_COMPONENT (prog))
2446 prog->stop = 1;
2447 return 0;
2448 }
2449
2450 void
progman_stop(void)2451 progman_stop (void)
2452 {
2453 progman_foreach (mark_for_stopping, NULL);
2454 progman_gc ();
2455 program_shutdown ();
2456 }
2457
2458 /* EOF */
2459