1 /* This file is part of Mailfromd.
2    Copyright (C) 2005-2021 Sergey Poznyakoff
3 
4    This program 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    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <syslog.h>
29 #include <signal.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netdb.h>
35 
36 #include <mailutils/mailutils.h>
37 #include <mailutils/alloc.h>
38 
39 #include "libmf.h"
40 #include "srvman.h"
41 
42 struct mfd_server {
43 	struct mfd_server *prev;    /* Link to the previous server */
44 	struct mfd_server *next;    /* Link to the next server */
45 	char *id;                   /* Server ID */
46 	struct sockaddr *sa;        /* Socket address */
47 	socklen_t salen;            /* Length of the sa */
48 	int backlog;                /* Backlog value for listen(2) */
49 	int fd;                     /* Socket descriptor */
50 	int flags;                  /* SRV_* flags */
51 	mfd_server_prefork_hook_t prefork_hook;  /* Pre-fork function */
52 	mfd_server_func_t conn;     /* Connection handler */
53 	mfd_srvman_hook_t free_hook;
54 	void *data;            /* Server-specific data */
55 	mu_acl_t acl;          /* Access Control List */
56 	size_t max_children;   /* Maximum number of sub-processes to run. */
57 	size_t num_children;   /* Current number of running sub-processes. */
58 	pid_t *pidtab;         /* Array of child PIDs */
59 	size_t pidtab_size;    /* Number of elements in pidtab */
60 };
61 
62 
63 struct srvman_param srvman_param;
64 
65 
66 typedef RETSIGTYPE (*sig_handler_t) (int);
67 
68 union srvman_sockaddr {
69 	struct sockaddr sa;
70 	struct sockaddr_in s_in;
71 	struct sockaddr_un s_un;
72 };
73 
74 struct srvman {
75 	struct mfd_server *head, *tail; /* List of servers */
76 	size_t num_children;        /* Current number of running
77 				       sub-processes. */
78 	sigset_t sigmask;           /* A set of signals to handle by the
79 				       manager.  */
80 	sig_handler_t sigtab[NSIG]; /* Keeps old signal handlers. */
81 };
82 
83 static struct srvman srvman;
84 static mu_debug_handle_t debug_handle;
85 
86 static sig_handler_t
set_signal(int sig,sig_handler_t handler)87 set_signal(int sig, sig_handler_t handler)
88 {
89 #ifdef HAVE_SIGACTION
90 	struct sigaction act, oldact;
91 	act.sa_handler = handler;
92 	sigemptyset(&act.sa_mask);
93 	act.sa_flags = 0;
94 	sigaction(sig, &act, &oldact);
95 	return oldact.sa_handler;
96 #else
97 	return signal(sig, handler);
98 #endif
99 }
100 
101 static int volatile need_cleanup;
102 static int volatile stop;
103 
104 void
mfd_srvman_stop()105 mfd_srvman_stop()
106 {
107 	stop = 1;
108 }
109 
110 static RETSIGTYPE
srvman_signal(int signo)111 srvman_signal (int signo)
112 {
113 	switch (signo) {
114 	case SIGCHLD:
115 		need_cleanup = 1;
116 		break;
117 
118 	default:
119 		/* FIXME: */
120 		stop = 1;
121 		break;
122 	}
123 #ifndef HAVE_SIGACTION
124 	signal(signo, srvman_signal);
125 #endif
126 }
127 
128 static void
set_signal_handlers()129 set_signal_handlers()
130 {
131 	int i;
132 
133 	for (i = 0; i < NSIG; i++)
134 		if (sigismember (&srvman.sigmask, i))
135 			srvman.sigtab[i] = set_signal(i, srvman_signal);
136 }
137 
138 static void
restore_signal_handlers()139 restore_signal_handlers()
140 {
141 	int i;
142 
143 	for (i = 0; i < NSIG; i++)
144 		if (sigismember (&srvman.sigmask, i))
145 			set_signal(i, srvman.sigtab[i]);
146 }
147 
148 
149 struct sockaddr *
srvman_url_to_sockaddr(mu_url_t url,socklen_t * psalen)150 srvman_url_to_sockaddr(mu_url_t url, socklen_t *psalen)
151 {
152 	int rc;
153 	const char *sval;
154 	struct sockaddr *sa;
155 	socklen_t socklen;
156 
157 	if (rc = mu_url_sget_scheme(url, &sval)) {
158 		mu_error(_("cannot get URL scheme: %s"), mu_strerror(rc));
159 		return NULL;
160 	}
161 
162 	if (strcmp(sval, "unix") == 0
163 	    || strcmp(sval, "local") == 0) {
164 		struct sockaddr_un *s_un;
165 		size_t slen;
166 
167 		rc = mu_url_sget_path(url, &sval);
168 		if (rc) {
169 			if (rc == MU_ERR_NOENT)
170 				rc = mu_url_sget_host(url, &sval);
171 			if (rc) {
172 				mu_error(_("cannot get URL path: %s"),
173 					 mu_strerror(rc));
174 				return NULL;
175 			}
176 		}
177 		slen = strlen(sval);
178 		if (slen >= sizeof s_un->sun_path) {
179 			mu_error(_("socket path name too long: %s"),
180 				 sval);
181 			return NULL;
182 		}
183 		socklen = sizeof (s_un[0]);
184 		sa = mu_alloc (socklen);
185 		s_un = (struct sockaddr_un *)sa;
186 		s_un->sun_family = AF_UNIX;
187 		strcpy(s_un->sun_path, sval);
188 	} else if (strcmp(sval, "inet") == 0) {
189 		struct sockaddr_in *s_in;
190 		unsigned n;
191 		short port;
192 		struct hostent *hp;
193 
194 		if (rc = mu_url_get_port(url, &n)) {
195 			mu_error(_("cannot get URL port: %s"),
196 				 mu_strerror(rc));
197 			return NULL;
198 		}
199 
200 		if (n == 0 || (port = n) != n) {
201 			mu_error(_("port out of range: %u"), n);
202 			return NULL;
203 		}
204 
205 		if (rc = mu_url_sget_host(url, &sval)) {
206 			mu_error(_("cannot get URL host: %s"),
207 				 mu_strerror(rc));
208 			return NULL;
209 		}
210 
211 		hp = gethostbyname(sval);
212 		if (!hp) {
213 			mu_error(_("unknown host name: %s"), sval);
214 			return NULL;
215 		}
216 
217 		if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
218 			mu_error(_("unsupported address family"));
219 			return NULL;
220 		}
221 
222 		socklen = sizeof s_in[0];
223 		sa = mu_alloc(socklen);
224 		s_in = (struct sockaddr_in *)sa;
225 		s_in->sin_family = AF_INET;
226 		memcpy(&s_in->sin_addr, hp->h_addr, 4);
227 		s_in->sin_port = htons(port);
228 #ifdef GACOPYZ_IPV6
229 	} else if (strcmp(sval, "inet6") == 0) {
230 		struct addrinfo hints;
231 		struct addrinfo *res;
232 		const char *host = NULL;
233 		const char *port;
234 
235 		memset(&hints, 0, sizeof(hints));
236 		hints.ai_family = AF_INET6;
237 		hints.ai_socktype = SOCK_STREAM;
238 
239 		rc = mu_url_sget_host(url, &host);
240 		if (rc == MU_ERR_NOENT)
241 			hints.ai_flags |= AI_PASSIVE;
242 		else if (rc) {
243 			mu_error(_("cannot get URL host: %s"),
244 				 mu_strerror(rc));
245 			return NULL;
246 		}
247 
248 		if (mu_url_sget_portstr(url, &port)) {
249 			mu_error(_("cannot get URL port: %s"),
250 				 mu_strerror(rc));
251 			return NULL;
252 		}
253 
254 		rc = getaddrinfo(host, port, &hints, &res);
255 
256 		switch (rc) {
257 		case 0:
258 			break;
259 		case EAI_SYSTEM:
260 			mu_error(_("%s:%s: cannot parse address: %s"),
261 				 host ? host : "NULL", port, strerror(errno));
262 			return NULL;
263 
264 		case EAI_BADFLAGS:
265 		case EAI_SOCKTYPE:
266 			mu_error(_("%s:%d: internal error converting %s:%s"),
267 				 __FILE__, __LINE__,
268 				 host ? host : "NULL", port);
269 			return NULL;
270 
271 		case EAI_MEMORY:
272 			mu_alloc_die();
273 
274 		default:
275 			mu_error("%s:%s: %s",
276 				 host ? host : "NULL", port,
277 				 gai_strerror(rc));
278 			return NULL;
279 		}
280 
281 		if (res->ai_next) {
282 			char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
283 			rc = getnameinfo(res->ai_addr, res->ai_addrlen,
284 					 hostbuf, sizeof hostbuf,
285 					 servbuf, sizeof servbuf,
286 					 NI_NUMERICHOST|NI_NUMERICSERV);
287 
288 			mu_diag_output(MU_DIAG_WARNING,
289 				    _("%s:%s resolves to several addresses; "
290 				      "using %s:%s"),
291 				       host, port, hostbuf, servbuf);
292 		}
293 
294 		socklen = res->ai_addrlen;
295 		sa = mu_alloc(socklen);
296 		memcpy(sa, res->ai_addr, res->ai_addrlen);
297 		freeaddrinfo(res);
298 #endif
299 	} else {
300 		mu_error(_("unsupported protocol: %s"), sval);
301 		return NULL;
302 	}
303 
304 	if (psalen)
305 		*psalen = socklen;
306 	return sa;
307 }
308 
309 
310 
311 /* Yield 1 if SRV has run out of the children limit */
312 #define SERVER_BUSY(srv)			\
313 	((srv)->max_children && (srv)->num_children >= (srv)->max_children)
314 
315 static void
register_child(struct mfd_server * srv,pid_t pid)316 register_child(struct mfd_server *srv, pid_t pid)
317 {
318 	size_t i;
319 
320 	mu_debug(debug_handle, MU_DEBUG_TRACE5,
321 		 ("registering child %lu", (unsigned long)pid));
322 	for (i = 0; i < srv->pidtab_size; i++)
323 		if (srv->pidtab[i] == 0)
324 			break;
325 	if (i == srv->pidtab_size) {
326 		int j;
327 		if (srv->pidtab_size == 0)
328 			srv->pidtab_size = DEFAULT_PIDTAB_SIZE;
329 		srv->pidtab = mu_2nrealloc(srv->pidtab,
330 					 &srv->pidtab_size,
331 					 sizeof(srv->pidtab[0]));
332 		for (j = i; j < srv->pidtab_size; j++)
333 			srv->pidtab[j] = 0;
334 
335 	}
336 	srv->pidtab[i] = pid;
337 	srv->num_children++;
338 	srvman.num_children++;
339 }
340 
341 static void
report_exit_status(const char * tag,pid_t pid,int status,int expect_term)342 report_exit_status(const char *tag, pid_t pid, int status, int expect_term)
343 {
344 	if (WIFEXITED(status)) {
345 		if (WEXITSTATUS(status) == 0)
346 			mu_debug(debug_handle, MU_DEBUG_TRACE0,
347                               ("%s [%lu] exited successfully",
348 			       tag, (unsigned long) pid));
349 		else
350 			mu_error(_("%s [%lu] failed with status %d"),
351 				 tag, (unsigned long) pid,
352 				 WEXITSTATUS(status));
353 	} else if (WIFSIGNALED (status)) {
354 		if (expect_term && WTERMSIG(status) == SIGTERM)
355 			mu_debug(debug_handle, MU_DEBUG_TRACE0,
356 				 ("%s [%lu] terminated on signal %d",
357 				  tag, (unsigned long) pid,
358 				  WTERMSIG(status)));
359 		else
360 			mu_error(_("%s [%lu] terminated on signal %d"),
361 				 tag, (unsigned long) pid,
362 				 WTERMSIG(status));
363 	} else if (WIFSTOPPED(status))
364 		mu_error(_("%s [%lu] stopped on signal %d"),
365 			 tag, (unsigned long) pid,
366 			 WSTOPSIG(status));
367 	else
368 		mu_error(_("%s [%lu] terminated with unrecognized status"),
369 			 tag, (unsigned long) pid);
370 }
371 
372 /* Remove (unregister) PID from the list of running instances and
373    log its exit STATUS.
374    Return 1 to command main loop to recompute the set of active
375    descriptors. */
376 static int
unregister_child(pid_t pid,int status)377 unregister_child(pid_t pid, int status)
378 {
379 	struct mfd_server *srv;
380 
381 	mu_debug(debug_handle, MU_DEBUG_TRACE5,
382 		 ("unregistering child %lu (status %x)",
383 		  (unsigned long)pid, status));
384 	for (srv = srvman.head; srv; srv = srv->next) {
385 		size_t i;
386 
387 		for (i = 0; i < srv->pidtab_size; i++)
388 			if (srv->pidtab[i] == pid) {
389 				int rc = SERVER_BUSY(srv);
390 				srv->pidtab[i] = 0;
391 				srv->num_children--;
392 				srvman.num_children--;
393 				/* FIXME: expect_term? */
394 				report_exit_status(srv->id, pid, status, 0);
395 				return rc;
396 			}
397 	}
398 	/* FIXME */
399 	return 0;
400 }
401 
402 static int
children_cleanup()403 children_cleanup()
404 {
405 	int rc = 0;
406 	pid_t pid;
407 	int status;
408 
409 	mu_debug(debug_handle, MU_DEBUG_TRACE1, ("cleaning up subprocesses"));
410 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
411 		rc |= unregister_child(pid, status);
412 	return rc;
413 }
414 
415 
416 static void
server_remove(struct mfd_server * srv)417 server_remove(struct mfd_server *srv)
418 {
419 	struct mfd_server *p;
420 
421 	mu_debug(debug_handle, MU_DEBUG_TRACE4,
422 		 ("removing server %s", srv->id));
423 	if ((p = srv->prev) != NULL)
424 		p->next = srv->next;
425 	else
426 		srvman.head = srv->next;
427 
428 	if ((p = srv->next) != NULL)
429 		p->prev = srv->prev;
430 	else
431 		srvman.tail = srv->prev;
432 }
433 
434 static void
server_signal_children(struct mfd_server * srv,int sig)435 server_signal_children(struct mfd_server *srv, int sig)
436 {
437 	int i;
438 
439 	mu_debug(debug_handle, MU_DEBUG_TRACE4,
440 		 ("server %s: sending children signal %d", srv->id, sig));
441 	for (i = 0; i < srv->pidtab_size; i++)
442 		if (srv->pidtab[i])
443 			kill(srv->pidtab[i], sig);
444 }
445 
446 void
mfd_server_shutdown(struct mfd_server * srv)447 mfd_server_shutdown(struct mfd_server *srv)
448 {
449 	if (srv->fd == -1)
450 		return;
451 
452 	mu_debug(debug_handle, MU_DEBUG_TRACE1,
453 		 ("shutting down %s", srv->id));
454 	close(srv->fd);
455 	srv->fd = -1;
456 }
457 
458 struct mfd_server *
mfd_server_new(const char * id,mu_url_t url,mfd_server_func_t conn,int flags)459 mfd_server_new(const char *id, mu_url_t url, mfd_server_func_t conn, int flags)
460 {
461 	struct mfd_server *srv;
462 	struct sockaddr *sa;
463 	socklen_t salen;
464 
465 	sa = srvman_url_to_sockaddr(url, &salen);
466 	if (!sa)
467 		return NULL;
468 
469 	srv = mu_zalloc(sizeof(*srv));
470 	srv->id = mu_strdup(id);
471 	srv->sa = sa;
472 	srv->salen = salen;
473 	srv->backlog = 8;
474 	srv->conn = conn;
475 	srv->flags = flags;
476 	return srv;
477 }
478 
479 void
mfd_server_free(struct mfd_server * srv)480 mfd_server_free(struct mfd_server *srv)
481 {
482 	server_remove(srv);
483 	if (srv->free_hook)
484 		srv->free_hook(srv->data);
485 	free(srv->id);
486 	free(srv->sa);
487 	mu_acl_destroy(&srv->acl);
488 	free(srv->pidtab);
489 	free(srv);
490 }
491 
492 void
mfd_server_set_prefork_hook(struct mfd_server * srv,mfd_server_prefork_hook_t hook)493 mfd_server_set_prefork_hook(struct mfd_server *srv,
494 			    mfd_server_prefork_hook_t hook)
495 {
496 	srv->prefork_hook = hook;
497 }
498 
499 void
mfd_server_set_data(struct mfd_server * srv,void * data,mfd_srvman_hook_t free_hook)500 mfd_server_set_data(struct mfd_server *srv,
501 		    void *data,
502 		    mfd_srvman_hook_t free_hook)
503 {
504 	srv->data = data;
505 	srv->free_hook = free_hook;
506 }
507 
508 void
mfd_server_set_max_children(struct mfd_server * srv,size_t n)509 mfd_server_set_max_children(struct mfd_server *srv, size_t n)
510 {
511 	srv->max_children = n;
512 }
513 
514 void
mfd_server_set_acl(struct mfd_server * srv,mu_acl_t acl)515 mfd_server_set_acl(struct mfd_server *srv, mu_acl_t acl)
516 {
517 	srv->acl = acl;
518 }
519 
520 void
mfd_server_set_backlog(struct mfd_server * srv,int value)521 mfd_server_set_backlog(struct mfd_server *srv, int value)
522 {
523 	srv->backlog = value;
524 }
525 
526 void
mfd_srvman_attach_server(struct mfd_server * srv)527 mfd_srvman_attach_server(struct mfd_server *srv)
528 {
529 	srv->next = NULL;
530 	srv->prev = srvman.tail;
531 	if (srvman.tail)
532 		srvman.tail->next = srv;
533 	else
534 		srvman.head = srv;
535 	srvman.tail = srv;
536 }
537 
538 
539 static int
check_acl(const char * id,mu_acl_t acl,struct sockaddr * sa,socklen_t salen)540 check_acl(const char *id, mu_acl_t acl, struct sockaddr *sa, socklen_t salen)
541 {
542 	mu_acl_result_t res;
543 	int rc = mu_acl_check_sockaddr(acl, sa, salen, &res);
544 	char *p = mu_sys_sockaddr_to_astr(sa, salen);
545 
546 	if (rc) {
547 		mu_error(_("server %s: access from %s blocked: "
548 			   "cannot check ACLs: %s"),
549 			 id, p, mu_strerror(rc));
550 	} else {
551 		switch (res) {
552 		case mu_acl_result_undefined:
553 			mu_diag_output(MU_DIAG_INFO,
554 				       _("server %s: undefined ACL result; "
555 					 "access from %s allowed"),
556 				       id, p);
557 			break;
558 
559 		case mu_acl_result_accept:
560 			mu_debug(debug_handle, MU_DEBUG_TRACE0,
561                               ("server %s: allowed access from %s", id, p));
562 			break;
563 
564 		case mu_acl_result_deny:
565 			mu_error(_("server %s: access from %s blocked"),
566 				 id, p);
567 			rc = 1;
568 		}
569 	}
570 	free(p);
571 	return rc;
572 }
573 
574 static void
server_run(int connfd,struct mfd_server * srv,struct sockaddr * sa,socklen_t salen)575 server_run(int connfd, struct mfd_server *srv,
576 	   struct sockaddr *sa, socklen_t salen)
577 {
578 	if (srvman_param.acl && check_acl(srv->id, srvman_param.acl,
579 					  sa, salen))
580 		return;
581 	if (srv->acl && check_acl(srv->id, srv->acl, sa, salen))
582 		return;
583 
584 	if (((srvman_param.flags | srv->flags) & SRV_SINGLE_PROCESS)) {
585 		if ((!srvman_param.prefork_hook
586 		     || srvman_param.prefork_hook(sa, salen,
587 						  srvman_param.data) == 0)
588 		    && (!srv->prefork_hook
589 			|| srv->prefork_hook(srv->id,
590 					     sa, salen,
591 					     srv->data,
592 					     srvman_param.data) == 0))
593 			srv->conn(srv->id,
594 				  connfd, sa, salen,
595 				  srv->data,
596 				  srvman_param.data);
597 	} else {
598 		pid_t pid;
599 
600 		if (srv->prefork_hook
601 		    && srv->prefork_hook(srv->id,
602 					 sa, salen,
603 					 srv->data, srvman_param.data))
604 			return;
605 
606 		pid = fork();
607 		if (pid == -1)
608 			mu_error("fork: %s", strerror(errno));
609 		else if (pid == 0) {
610 			/* Child.  */
611 			FD_SET(connfd, &srvman_param.keepfds);
612 			close_fds_except(&srvman_param.keepfds);
613 			restore_signal_handlers();
614 			exit(srv->conn(srv->id,
615 				       connfd,
616 				       sa, salen,
617 				       srv->data, srvman_param.data));
618 		} else
619 			register_child(srv, pid);
620 	}
621 }
622 
623 /* Accept incoming connection for server SRV.
624    Return 1 to command main loop to recompute the set of active
625    descriptors. */
626 static int
server_accept(struct mfd_server * srv)627 server_accept(struct mfd_server *srv)
628 {
629 	int connfd;
630 	union srvman_sockaddr client;
631 	socklen_t size = sizeof(client);
632 
633 	if (srv->fd == -1) {
634 		mu_error(_("removing shut down server %s"),
635 			 srv->id);
636 		mfd_server_free(srv);
637 		return 1;
638 	}
639 
640 	if (SERVER_BUSY(srv)) {
641 		mu_error(_("server %s: too many children (%lu)"),
642 			 srv->id, (unsigned long) srv->num_children);
643 		return 1;
644 	}
645 
646 	connfd = accept(srv->fd, &client.sa, &size);
647 	if (connfd == -1) {
648 		if (errno != EINTR) {
649 			mu_error(_("server %s: accept failed: %s"),
650 				 srv->id, mu_strerror(errno));
651 			mfd_server_shutdown(srv);
652 			mfd_server_free(srv);
653 			return 1;
654 		} /* FIXME: Call srv->intr otherwise? */
655 	} else {
656 		server_run(connfd, srv, &client.sa, size);
657 		close(connfd);
658 	}
659 	return 0;
660 }
661 
662 static int
connection_loop(fd_set * fdset)663 connection_loop(fd_set *fdset)
664 {
665 	struct mfd_server *srv;
666 	int rc = 0;
667 	for (srv = srvman.head; srv; ) {
668 		struct mfd_server *next = srv->next;
669 		if (FD_ISSET(srv->fd, fdset))
670 			rc |= server_accept(srv);
671 		srv = next;
672 	}
673 	return rc;
674 }
675 
676 int
compute_fdset(fd_set * fdset)677 compute_fdset(fd_set *fdset)
678 {
679 	struct mfd_server *p;
680 	int maxfd = 0;
681 	FD_ZERO(fdset);
682 	for (p = srvman.head; p; p = p->next) {
683 		if (SERVER_BUSY(p))
684 			continue;
685 		FD_SET(p->fd, fdset);
686 		if (p->fd > maxfd)
687 			maxfd = p->fd;
688 	}
689 	mu_debug(debug_handle, MU_DEBUG_TRACE3,
690 		 ("recomputed fdset: %d fds", maxfd));
691 	return maxfd;
692 }
693 
694 void
mfd_srvman_run(sigset_t * set)695 mfd_srvman_run(sigset_t *set)
696 {
697 	int recompute_fd = 1;
698 	int maxfd;
699 	fd_set fdset;
700 
701 	if (!srvman.head)
702 		return;
703 
704 	mu_debug(debug_handle, MU_DEBUG_TRACE1, ("server manager starting"));
705 	if (set)
706 		srvman.sigmask = *set;
707 	else
708 		sigemptyset(&srvman.sigmask);
709 	sigaddset(&srvman.sigmask, SIGCHLD);
710 	set_signal_handlers();
711 	if (srvman_param.shutdown_timeout == 0)
712 		srvman_param.shutdown_timeout = DEFAULT_SHUTDOWN_TIMEOUT;
713 
714 	for (stop = 0; srvman.head && !stop;) {
715 		int rc;
716 		struct timeval *to;
717 		fd_set rdset;
718 
719 		if (need_cleanup) {
720 			need_cleanup = 0;
721 			recompute_fd = children_cleanup();
722 		}
723 
724 		if (recompute_fd) {
725 			maxfd = compute_fdset(&fdset);
726 			recompute_fd = 0;
727 		}
728 
729 		if (!maxfd) {
730 			mu_debug(debug_handle,
731 				 MU_DEBUG_TRACE1, ("no active fds, pausing"));
732 			pause();
733 			recompute_fd = 1;
734 			continue;
735 		}
736 
737 		if (srvman_param.max_children
738 		    && srvman.num_children >= srvman_param.max_children) {
739 			mu_error(_("too many children (%lu)"),
740 				 (unsigned long) srvman.num_children);
741 			pause();
742 			continue;
743 		}
744 
745 		if (srvman_param.idle_hook
746 		    && srvman_param.idle_hook(srvman_param.data)) {
747 			mu_debug(debug_handle, MU_DEBUG_TRACE1,
748 				 ("break requested by idle hook"));
749 			break;
750 		}
751 
752 		if (stop)
753 			break;
754 
755 		rdset = fdset;
756 		to = NULL; /* FIXME */
757 		rc = select(maxfd + 1, &rdset, NULL, NULL, to);
758 		if (rc == -1 && errno == EINTR)
759 			continue;
760 		if (rc < 0) {
761 			mu_error(_("select failed: %s"),
762 				 mu_strerror(errno));
763 			break;
764 		}
765 		recompute_fd = connection_loop(&rdset);
766 	}
767 
768 	restore_signal_handlers();
769 	mu_debug(debug_handle, MU_DEBUG_TRACE1, ("server manager finishing"));
770 }
771 
772 static int
server_prep(struct mfd_server * srv,int fd)773 server_prep(struct mfd_server *srv, int fd)
774 {
775 	struct stat st;
776 	struct sockaddr_un *s_un;
777 	int t;
778 
779 	switch (srv->sa->sa_family) {
780 	case AF_UNIX:
781 		s_un = (struct sockaddr_un *) srv->sa;
782 
783 		if (stat(s_un->sun_path, &st)) {
784 			if (errno != ENOENT) {
785 				mu_error(_("%s: file %s exists but cannot be stat'd: %s"),
786 					 srv->id,
787 					 s_un->sun_path,
788 					 mu_strerror(errno));
789 				return 1;
790 			}
791 		} else if (!S_ISSOCK(st.st_mode)) {
792 			mu_error(_("%s: file %s is not a socket"),
793 				 srv->id, s_un->sun_path);
794 			return 1;
795 		} else if (!(srvman_param.flags & SRV_KEEP_EXISTING)
796 			   && !(srv->flags & SRV_KEEP_EXISTING)) {
797 			if (unlink(s_un->sun_path)) {
798 				mu_error(_("%s: cannot unlink file %s: %s"),
799 					 srv->id, s_un->sun_path,
800 					 mu_strerror(errno));
801 				return 1;
802 			}
803 		} else {
804 			mu_error(_("socket `%s' already exists"),
805 				 s_un->sun_path);
806 			return 1;
807 		}
808 		break;
809 
810 	case AF_INET:
811 		if (!(srvman_param.flags & SRV_KEEP_EXISTING)
812 		    && !(srv->flags & SRV_KEEP_EXISTING)) {
813 			t = 1;
814 			setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
815 				   &t, sizeof(t));
816 		}
817 	}
818 
819 	if (bind(fd, srv->sa, srv->salen) == -1) {
820 		char *p = mu_sys_sockaddr_to_astr(srv->sa, srv->salen);
821 		mu_error(_("%s: cannot bind to %s: %s"),
822 			   srv->id, p, mu_strerror(errno));
823 		free(p);
824 		return 1;
825 	}
826 
827 	if (listen(fd, srv->backlog) == -1) {
828 		char *p = mu_sys_sockaddr_to_astr(srv->sa, srv->salen);
829 		mu_error(_("%s: listen on %s failed: %s"),
830 			   srv->id, p, mu_strerror(errno));
831 		free(p);
832 		return 1;
833 	}
834 	return 0;
835 }
836 
837 static int
server_open(struct mfd_server * srv)838 server_open(struct mfd_server *srv)
839 {
840 	int fd = socket(srv->sa->sa_family, SOCK_STREAM, 0);
841 	if (fd == -1) {
842 		mu_error("%s: socket: %s", srv->id, mu_strerror(errno));
843 		return 1;
844 	}
845 
846 	if (server_prep(srv, fd)) {
847 		close(fd);
848 		return 1;
849 	}
850 	srv->fd = fd;
851 	return 0;
852 }
853 
854 
855 int
mfd_srvman_open()856 mfd_srvman_open()
857 {
858 	struct mfd_server *p;
859 
860 	mu_debug(debug_handle, MU_DEBUG_TRACE1, ("opening servers"));
861 	if (!srvman.head)
862 		mu_error(_("no servers configured"));
863 	for (p = srvman.head; p; ) {
864 		struct mfd_server *next = p->next;
865 		if (server_open(p))
866 			server_remove(p);
867 		p = next;
868 	}
869 	return srvman.head == NULL;
870 }
871 
872 void
mfd_srvman_shutdown()873 mfd_srvman_shutdown()
874 {
875 	struct mfd_server *p;
876 	time_t start = time(NULL);
877 
878 	for (p = srvman.head; p; p = p->next)
879 		server_signal_children(p, SIGTERM);
880 
881 	do {
882 		children_cleanup();
883 		if (srvman.num_children == 0)
884 			break;
885 		sleep(1);
886 	} while (time(NULL) - start < srvman_param.shutdown_timeout);
887 
888 	mu_debug(debug_handle, MU_DEBUG_TRACE1, ("shutting down servers"));
889 	for (p = srvman.head; p; p = p->next) {
890 		server_signal_children(p, SIGKILL);
891 		mfd_server_shutdown(p);
892 	}
893 }
894 
895 void
mfd_srvman_free()896 mfd_srvman_free()
897 {
898 	struct mfd_server *p;
899 
900 	for (p = srvman.head; p; ) {
901 		struct mfd_server *next = p->next;
902 		mfd_server_free(p);
903 		p = next;
904 	}
905 	if (srvman_param.free_hook)
906 		srvman_param.free_hook(srvman_param.data);
907 	mu_acl_destroy(&srvman_param.acl);
908 }
909 
910 size_t
mfd_srvman_count_servers()911 mfd_srvman_count_servers()
912 {
913 	size_t count = 0;
914 	struct mfd_server *p;
915 
916 	for (p = srvman.head; p; p = p->next)
917 		count++;
918 	return count;
919 }
920 
921 void
srvman_init()922 srvman_init()
923 {
924 	debug_handle = mu_debug_register_category("srvman");
925 }
926