kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

kore.c (20246B)



      1 /*
      2  * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/types.h>
     18 #include <sys/stat.h>
     19 #include <sys/un.h>
     20 
     21 #include <sys/socket.h>
     22 #include <sys/resource.h>
     23 
     24 #include <libgen.h>
     25 #include <fcntl.h>
     26 #include <stdio.h>
     27 #include <netdb.h>
     28 #include <signal.h>
     29 
     30 #include "kore.h"
     31 #include "hooks.h"
     32 
     33 #if !defined(KORE_NO_HTTP)
     34 #include "http.h"
     35 #endif
     36 
     37 #if defined(KORE_USE_CURL)
     38 #include "curl.h"
     39 #endif
     40 
     41 #if defined(KORE_USE_PGSQL)
     42 #include "pgsql.h"
     43 #endif
     44 
     45 #if defined(KORE_USE_PYTHON)
     46 #include "python_api.h"
     47 #endif
     48 
     49 #if defined(KORE_USE_ACME)
     50 #include "acme.h"
     51 #endif
     52 
     53 volatile sig_atomic_t	sig_recv;
     54 struct kore_server_list	kore_servers;
     55 u_int8_t		nlisteners;
     56 int			kore_argc = 0;
     57 int			kore_quit = 0;
     58 pid_t			kore_pid = -1;
     59 u_int16_t		cpu_count = 1;
     60 int			kore_debug = 0;
     61 int			kore_quiet = 0;
     62 int			skip_runas = 0;
     63 int			skip_chroot = 0;
     64 u_int8_t		worker_count = 0;
     65 char			**kore_argv = NULL;
     66 int			kore_foreground = 0;
     67 char			*kore_progname = NULL;
     68 u_int32_t		kore_socket_backlog = 5000;
     69 char			*kore_pidfile = KORE_PIDFILE_DEFAULT;
     70 
     71 struct kore_privsep	worker_privsep;
     72 
     73 extern char		**environ;
     74 extern char		*__progname;
     75 static size_t		proctitle_maxlen = 0;
     76 
     77 static void	usage(void);
     78 static void	version(void);
     79 
     80 static void	kore_write_kore_pid(void);
     81 static void	kore_proctitle_setup(void);
     82 static void	kore_server_shutdown(void);
     83 static void	kore_server_start(int, char *[]);
     84 static void	kore_call_parent_configure(int, char **);
     85 
     86 #if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
     87 static const char	*parent_config_hook = KORE_PYTHON_CONFIG_HOOK;
     88 static const char	*parent_teardown_hook = KORE_PYTHON_TEARDOWN_HOOK;
     89 #else
     90 static const char	*parent_config_hook = KORE_CONFIG_HOOK;
     91 static const char	*parent_teardown_hook = KORE_TEARDOWN_HOOK;
     92 #if defined(KORE_SINGLE_BINARY)
     93 static const char	*parent_daemonized_hook = KORE_DAEMONIZED_HOOK;
     94 #endif
     95 #endif
     96 
     97 static void
     98 usage(void)
     99 {
    100 #if defined(KORE_USE_PYTHON)
    101 	printf("Usage: %s [options] [app | app.py]\n", __progname);
    102 #else
    103 	printf("Usage: %s [options]\n", __progname);
    104 #endif
    105 
    106 	printf("\n");
    107 	printf("Available options:\n");
    108 #if !defined(KORE_SINGLE_BINARY)
    109 	printf("\t-c\tconfiguration to use\n");
    110 #endif
    111 #if defined(KORE_DEBUG)
    112 	printf("\t-d\trun with debug on\n");
    113 #endif
    114 	printf("\t-f\tstart in foreground\n");
    115 	printf("\t-h\tthis help text\n");
    116 	printf("\t-n\tdo not chroot on any worker\n");
    117 	printf("\t-q\tonly log errors\n");
    118 	printf("\t-r\tdo not change user on any worker\n");
    119 	printf("\t-v\tdisplay %s build information\n", __progname);
    120 
    121 	printf("\nFind more information on https://kore.io\n");
    122 
    123 	exit(1);
    124 }
    125 
    126 static void
    127 version(void)
    128 {
    129 	printf("%s ", kore_version);
    130 #if defined(KORE_NO_HTTP)
    131 	printf("no-http ");
    132 #endif
    133 #if defined(KORE_USE_CURL)
    134 	printf("curl-%s ", LIBCURL_VERSION);
    135 #endif
    136 #if defined(KORE_USE_PGSQL)
    137 	printf("pgsql ");
    138 #endif
    139 #if defined(KORE_USE_TASKS)
    140 	printf("tasks ");
    141 #endif
    142 #if defined(KORE_DEBUG)
    143 	printf("debug ");
    144 #endif
    145 #if defined(KORE_USE_PYTHON)
    146 	printf("python-%s ", PY_VERSION);
    147 #endif
    148 #if defined(KORE_USE_ACME)
    149 	printf("acme ");
    150 #endif
    151 	if (!kore_tls_supported())
    152 		printf("notls ");
    153 	printf("\n");
    154 	exit(0);
    155 }
    156 
    157 int
    158 main(int argc, char *argv[])
    159 {
    160 	struct kore_runtime_call	*rcall;
    161 #if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
    162 	struct stat			st;
    163 #endif
    164 
    165 	kore_argc = argc;
    166 	kore_argv = argv;
    167 
    168 #if !defined(KORE_SINGLE_BINARY)
    169 	kore_default_getopt(argc, argv);
    170 #endif
    171 
    172 	kore_mem_init();
    173 	kore_msg_init();
    174 	kore_log_init();
    175 
    176 	kore_progname = kore_strdup(argv[0]);
    177 	kore_proctitle_setup();
    178 
    179 #if !defined(KORE_SINGLE_BINARY)
    180 	argc -= optind;
    181 	argv += optind;
    182 #endif
    183 
    184 #if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON)
    185 	if (argc > 0) {
    186 		kore_pymodule = argv[0];
    187 		argc--;
    188 		argv++;
    189 	} else {
    190 		kore_pymodule = NULL;
    191 	}
    192 
    193 	if (kore_pymodule) {
    194 		if (lstat(kore_pymodule, &st) == -1) {
    195 			fatal("failed to stat '%s': %s",
    196 			    kore_pymodule, errno_s);
    197 		}
    198 
    199 		if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
    200 			fatal("%s: not a directory or file", kore_pymodule);
    201 	}
    202 #endif
    203 
    204 	kore_pid = getpid();
    205 	nlisteners = 0;
    206 	LIST_INIT(&kore_servers);
    207 
    208 	kore_platform_init();
    209 #if !defined(KORE_NO_HTTP)
    210 	http_parent_init();
    211 #if defined(KORE_USE_CURL)
    212 	kore_curl_sysinit();
    213 #endif
    214 #if defined(KORE_USE_PGSQL)
    215 	kore_pgsql_sys_init();
    216 #endif
    217 	kore_auth_init();
    218 	kore_validator_init();
    219 	kore_filemap_init();
    220 #endif
    221 #if defined(KORE_USE_ACME)
    222 	kore_acme_init();
    223 #endif
    224 	kore_domain_init();
    225 	kore_module_init();
    226 	kore_tls_init();
    227 
    228 #if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
    229 	if (config_file == NULL)
    230 		usage();
    231 #endif
    232 	kore_module_load(NULL, NULL, KORE_MODULE_NATIVE);
    233 
    234 #if defined(KORE_USE_PYTHON)
    235 	kore_python_init();
    236 #if !defined(KORE_SINGLE_BINARY)
    237 	if (kore_pymodule) {
    238 		kore_module_load(kore_pymodule, NULL, KORE_MODULE_PYTHON);
    239 		if (S_ISDIR(st.st_mode) && chdir(kore_pymodule) == -1)
    240 			fatal("chdir(%s): %s", kore_pymodule, errno_s);
    241 	} else {
    242 		/* swap back to non-python hooks. */
    243 		parent_config_hook = KORE_CONFIG_HOOK;
    244 		parent_teardown_hook = KORE_TEARDOWN_HOOK;
    245 	}
    246 #endif
    247 #endif
    248 
    249 #if defined(KORE_SINGLE_BINARY)
    250 	kore_call_parent_configure(argc, argv);
    251 #endif
    252 
    253 #if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY)
    254 	if (kore_pymodule)
    255 		kore_call_parent_configure(argc, argv);
    256 #endif
    257 
    258 	kore_parse_config();
    259 
    260 #if !defined(KORE_SINGLE_BINARY)
    261 	free(config_file);
    262 #endif
    263 
    264 #if !defined(KORE_NO_HTTP)
    265 	if (http_body_disk_offload > 0) {
    266 		if (mkdir(http_body_disk_path, 0700) == -1 && errno != EEXIST) {
    267 			printf("can't create http_body_disk_path '%s': %s\n",
    268 			    http_body_disk_path, errno_s);
    269 			return (KORE_RESULT_ERROR);
    270 		}
    271 	}
    272 #endif
    273 
    274 	kore_signal_setup();
    275 	kore_server_start(argc, argv);
    276 	kore_server_shutdown();
    277 
    278 	rcall = kore_runtime_getcall(parent_teardown_hook);
    279 	if (rcall != NULL) {
    280 		kore_runtime_execute(rcall);
    281 		kore_free(rcall);
    282 	}
    283 
    284 	if (unlink(kore_pidfile) == -1 && errno != ENOENT)
    285 		kore_log(LOG_NOTICE, "failed to remove pidfile (%s)", errno_s);
    286 
    287 	kore_server_cleanup();
    288 
    289 	if (!kore_quiet)
    290 		kore_log(LOG_INFO, "goodbye");
    291 
    292 #if defined(KORE_USE_PYTHON)
    293 	kore_python_cleanup();
    294 #endif
    295 
    296 	kore_mem_cleanup();
    297 
    298 	return (0);
    299 }
    300 
    301 void
    302 kore_default_getopt(int argc, char **argv)
    303 {
    304 	int		ch;
    305 
    306 #if !defined(KORE_SINGLE_BINARY)
    307 	while ((ch = getopt(argc, argv, "c:dfhnqrv")) != -1) {
    308 #else
    309 	while ((ch = getopt(argc, argv, "dfhnqrv")) != -1) {
    310 #endif
    311 		switch (ch) {
    312 #if !defined(KORE_SINGLE_BINARY)
    313 		case 'c':
    314 			free(config_file);
    315 			if ((config_file = strdup(optarg)) == NULL)
    316 				fatal("strdup");
    317 			break;
    318 #endif
    319 #if defined(KORE_DEBUG)
    320 		case 'd':
    321 			kore_debug = 1;
    322 			break;
    323 #endif
    324 		case 'f':
    325 			kore_foreground = 1;
    326 			break;
    327 		case 'h':
    328 			usage();
    329 			break;
    330 		case 'n':
    331 			skip_chroot = 1;
    332 			break;
    333 		case 'q':
    334 			kore_quiet = 1;
    335 			break;
    336 		case 'r':
    337 			skip_runas = 1;
    338 			break;
    339 		case 'v':
    340 			version();
    341 			break;
    342 		default:
    343 			usage();
    344 		}
    345 	}
    346 }
    347 
    348 int
    349 kore_server_bind(struct kore_server *srv, const char *ip, const char *port,
    350     const char *ccb)
    351 {
    352 	int			r;
    353 	struct listener		*l;
    354 	struct addrinfo		hints, *results;
    355 
    356 	kore_debug("kore_server_bind(%s, %s, %s)", srv->name, ip, port);
    357 
    358 	memset(&hints, 0, sizeof(hints));
    359 	hints.ai_family = AF_UNSPEC;
    360 	hints.ai_socktype = SOCK_STREAM;
    361 	hints.ai_protocol = IPPROTO_TCP;
    362 	hints.ai_flags = 0;
    363 
    364 	r = getaddrinfo(ip, port, &hints, &results);
    365 	if (r != 0)
    366 		fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
    367 
    368 	l = kore_listener_create(srv);
    369 	l->host = kore_strdup(ip);
    370 	l->port = kore_strdup(port);
    371 
    372 	if (!kore_listener_init(l, results->ai_family, ccb)) {
    373 		freeaddrinfo(results);
    374 		return (KORE_RESULT_ERROR);
    375 	}
    376 
    377 	if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
    378 		kore_listener_free(l);
    379 		freeaddrinfo(results);
    380 		kore_log(LOG_ERR, "bind(): %s", errno_s);
    381 		return (KORE_RESULT_ERROR);
    382 	}
    383 
    384 	freeaddrinfo(results);
    385 
    386 	if (listen(l->fd, kore_socket_backlog) == -1) {
    387 		kore_listener_free(l);
    388 		kore_log(LOG_ERR, "listen(): %s", errno_s);
    389 		return (KORE_RESULT_ERROR);
    390 	}
    391 
    392 	return (KORE_RESULT_OK);
    393 }
    394 
    395 int
    396 kore_server_bind_unix(struct kore_server *srv, const char *path,
    397     const char *ccb)
    398 {
    399 	struct listener		*l;
    400 	int			len;
    401 	struct sockaddr_un	sun;
    402 	socklen_t		socklen;
    403 
    404 	memset(&sun, 0, sizeof(sun));
    405 	sun.sun_family = AF_UNIX;
    406 
    407 	len = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path);
    408 	if (len == -1 || (size_t)len >= sizeof(sun.sun_path)) {
    409 		kore_log(LOG_ERR, "unix socket path '%s' too long", path);
    410 		return (KORE_RESULT_ERROR);
    411 	}
    412 
    413 #if defined(__linux__)
    414 	if (sun.sun_path[0] == '@')
    415 		sun.sun_path[0] = '\0';
    416 	socklen = sizeof(sun.sun_family) + len;
    417 #else
    418 	socklen = sizeof(sun);
    419 #endif
    420 
    421 	l = kore_listener_create(srv);
    422 	l->host = kore_strdup(path);
    423 
    424 	if (!kore_listener_init(l, AF_UNIX, ccb))
    425 		return (KORE_RESULT_ERROR);
    426 
    427 	if (sun.sun_path[0] != '\0') {
    428 		if (unlink(sun.sun_path) == -1 && errno != ENOENT) {
    429 			kore_log(LOG_ERR, "unlink: %s: %s",
    430 			    sun.sun_path, errno_s);
    431 			kore_listener_free(l);
    432 			return (KORE_RESULT_ERROR);
    433 		}
    434 	}
    435 
    436 	if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) {
    437 		kore_log(LOG_ERR, "bind: %s", errno_s);
    438 		kore_listener_free(l);
    439 		return (KORE_RESULT_ERROR);
    440 	}
    441 
    442 	if (listen(l->fd, kore_socket_backlog) == -1) {
    443 		kore_log(LOG_ERR, "listen(): %s", errno_s);
    444 		kore_listener_free(l);
    445 		return (KORE_RESULT_ERROR);
    446 	}
    447 
    448 	return (KORE_RESULT_OK);
    449 }
    450 
    451 struct kore_server *
    452 kore_server_create(const char *name)
    453 {
    454 	struct kore_server	*srv;
    455 
    456 	srv = kore_calloc(1, sizeof(struct kore_server));
    457 	srv->name = kore_strdup(name);
    458 
    459 	if (kore_tls_supported())
    460 		srv->tls = 1;
    461 	else
    462 		srv->tls = 0;
    463 
    464 	TAILQ_INIT(&srv->domains);
    465 	LIST_INIT(&srv->listeners);
    466 
    467 	LIST_INSERT_HEAD(&kore_servers, srv, list);
    468 
    469 	return (srv);
    470 }
    471 
    472 void
    473 kore_server_finalize(struct kore_server *srv)
    474 {
    475 	struct listener		*l;
    476 	const char		*proto;
    477 
    478 	if (kore_quiet)
    479 		return;
    480 
    481 	LIST_FOREACH(l, &srv->listeners, list) {
    482 		if (srv->tls)
    483 			proto = "https";
    484 		else
    485 			proto = "http";
    486 
    487 		if (l->family == AF_UNIX) {
    488 			kore_log(LOG_INFO, "%s serving %s on %s",
    489 			    srv->name, proto, l->host);
    490 		} else {
    491 			kore_log(LOG_INFO, "%s serving %s on %s:%s",
    492 			    srv->name, proto, l->host, l->port);
    493 		}
    494 	}
    495 }
    496 
    497 struct listener *
    498 kore_listener_create(struct kore_server *server)
    499 {
    500 	struct listener		*l;
    501 
    502 	l = kore_calloc(1, sizeof(struct listener));
    503 
    504 	nlisteners++;
    505 	LIST_INSERT_HEAD(&server->listeners, l, list);
    506 
    507 	l->server = server;
    508 
    509 	l->fd = -1;
    510 	l->evt.type = KORE_TYPE_LISTENER;
    511 	l->evt.handle = kore_listener_accept;
    512 
    513 	return (l);
    514 }
    515 
    516 struct kore_server *
    517 kore_server_lookup(const char *name)
    518 {
    519 	struct kore_server	*srv;
    520 
    521 	LIST_FOREACH(srv, &kore_servers, list) {
    522 		if (!strcmp(srv->name, name))
    523 			return (srv);
    524 	}
    525 
    526 	return (NULL);
    527 }
    528 
    529 int
    530 kore_listener_init(struct listener *l, int family, const char *ccb)
    531 {
    532 	switch (family) {
    533 	case AF_INET:
    534 	case AF_INET6:
    535 	case AF_UNIX:
    536 		break;
    537 	default:
    538 		fatal("unknown address family %d", family);
    539 	}
    540 
    541 	l->family = family;
    542 
    543 	if ((l->fd = socket(family, SOCK_STREAM, 0)) == -1) {
    544 		kore_listener_free(l);
    545 		kore_log(LOG_ERR, "socket(): %s", errno_s);
    546 		return (KORE_RESULT_ERROR);
    547 	}
    548 
    549 	if (fcntl(l->fd, F_SETFD, FD_CLOEXEC) == -1) {
    550 		kore_listener_free(l);
    551 		kore_log(LOG_ERR, "fcntl(): %s", errno_s);
    552 		return (KORE_RESULT_ERROR);
    553 	}
    554 
    555 	if (!kore_connection_nonblock(l->fd, family != AF_UNIX)) {
    556 		kore_listener_free(l);
    557 		kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s);
    558 		return (KORE_RESULT_ERROR);
    559 	}
    560 
    561 	if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) {
    562 		kore_listener_free(l);
    563 		return (KORE_RESULT_ERROR);
    564 	}
    565 
    566 	if (ccb != NULL) {
    567 		if ((l->connect = kore_runtime_getcall(ccb)) == NULL) {
    568 			kore_log(LOG_ERR, "no such callback: '%s'", ccb);
    569 			kore_listener_free(l);
    570 			return (KORE_RESULT_ERROR);
    571 		}
    572 	} else {
    573 		l->connect = NULL;
    574 	}
    575 
    576 	return (KORE_RESULT_OK);
    577 }
    578 
    579 void
    580 kore_server_free(struct kore_server *srv)
    581 {
    582 	struct listener		*l;
    583 	struct kore_domain	*dom;
    584 
    585 	LIST_REMOVE(srv, list);
    586 
    587 	while ((dom = TAILQ_FIRST(&srv->domains)) != NULL)
    588 		kore_domain_free(dom);
    589 
    590 	while ((l = LIST_FIRST(&srv->listeners)) != NULL)
    591 		kore_listener_free(l);
    592 
    593 	kore_free(srv->name);
    594 	kore_free(srv);
    595 }
    596 
    597 void
    598 kore_listener_free(struct listener *l)
    599 {
    600 	int	rm;
    601 
    602 	LIST_REMOVE(l, list);
    603 
    604 	if (l->fd != -1)
    605 		close(l->fd);
    606 
    607 	rm = 0;
    608 
    609 #if defined(__linux__)
    610 	if (worker == NULL && l->family == AF_UNIX && l->host[0] != '@')
    611 		rm++;
    612 #else
    613 	if (worker == NULL && l->family == AF_UNIX)
    614 		rm++;
    615 #endif
    616 	if (rm) {
    617 		if (unlink(l->host) == -1) {
    618 			kore_log(LOG_NOTICE,
    619 			    "failed to remove unix socket %s (%s)", l->host,
    620 			    errno_s);
    621 		}
    622 	}
    623 
    624 	kore_free(l->host);
    625 	kore_free(l->port);
    626 
    627 	kore_free(l);
    628 }
    629 
    630 void
    631 kore_listener_accept(void *arg, int error)
    632 {
    633 	struct connection	*c;
    634 	struct listener		*l = arg;
    635 	u_int32_t		accepted;
    636 
    637 	if (error)
    638 		fatal("error on listening socket");
    639 
    640 	if (!(l->evt.flags & KORE_EVENT_READ))
    641 		return;
    642 
    643 	accepted = 0;
    644 
    645 	while (worker_active_connections < worker_max_connections) {
    646 		if (worker_accept_threshold != 0 &&
    647 		    accepted >= worker_accept_threshold) {
    648 			kore_worker_make_busy();
    649 			break;
    650 		}
    651 
    652 		if (!kore_connection_accept(l, &c))
    653 			break;
    654 
    655 		if (c == NULL)
    656 			break;
    657 
    658 		accepted++;
    659 		kore_platform_event_all(c->fd, c);
    660 	}
    661 }
    662 
    663 int
    664 kore_sockopt(int fd, int what, int opt)
    665 {
    666 	int		on;
    667 
    668 	on = 1;
    669 	if (setsockopt(fd, what, opt, (const char *)&on, sizeof(on)) == -1) {
    670 		kore_log(LOG_ERR, "setsockopt(): %s", errno_s);
    671 		return (KORE_RESULT_ERROR);
    672 	}
    673 
    674 	return (KORE_RESULT_OK);
    675 }
    676 
    677 void
    678 kore_signal_setup(void)
    679 {
    680 	kore_signal_trap(SIGHUP);
    681 	kore_signal_trap(SIGQUIT);
    682 	kore_signal_trap(SIGTERM);
    683 	kore_signal_trap(SIGUSR1);
    684 	kore_signal_trap(SIGCHLD);
    685 
    686 	if (kore_foreground)
    687 		kore_signal_trap(SIGINT);
    688 	else
    689 		(void)signal(SIGINT, SIG_IGN);
    690 
    691 	(void)signal(SIGPIPE, SIG_IGN);
    692 }
    693 
    694 void
    695 kore_signal_trap(int sig)
    696 {
    697 	struct sigaction	sa;
    698 
    699 	sig_recv = 0;
    700 	memset(&sa, 0, sizeof(sa));
    701 	sa.sa_handler = kore_signal;
    702 
    703 	if (sigfillset(&sa.sa_mask) == -1)
    704 		fatal("sigfillset: %s", errno_s);
    705 
    706 	if (sigaction(sig, &sa, NULL) == -1)
    707 		fatal("sigaction: %s", errno_s);
    708 }
    709 
    710 void
    711 kore_server_closeall(void)
    712 {
    713 	struct listener		*l;
    714 	struct kore_server	*srv;
    715 
    716 	LIST_FOREACH(srv, &kore_servers, list) {
    717 		LIST_FOREACH(l, &srv->listeners, list)
    718 			l->fd = -1;
    719 	}
    720 }
    721 
    722 void
    723 kore_server_cleanup(void)
    724 {
    725 	struct kore_server	*srv;
    726 
    727 	while ((srv = LIST_FIRST(&kore_servers)) != NULL)
    728 		kore_server_free(srv);
    729 }
    730 
    731 void
    732 kore_signal(int sig)
    733 {
    734 	sig_recv = sig;
    735 }
    736 
    737 void
    738 kore_shutdown(void)
    739 {
    740 	if (worker != NULL) {
    741 		kore_msg_send(KORE_MSG_PARENT, KORE_MSG_SHUTDOWN, NULL, 0);
    742 		return;
    743 	}
    744 
    745 	fatal("kore_shutdown: called from parent");
    746 }
    747 
    748 void
    749 kore_proctitle(const char *title)
    750 {
    751 	int	len;
    752 
    753 	kore_argv[1] = NULL;
    754 
    755 	len = snprintf(kore_argv[0], proctitle_maxlen, "%s %s",
    756 	    basename(kore_progname), title);
    757 	if (len == -1 || (size_t)len >= proctitle_maxlen)
    758 		fatal("proctitle '%s' too large", title);
    759 
    760 	memset(kore_argv[0] + len, 0, proctitle_maxlen - len);
    761 }
    762 
    763 static void
    764 kore_proctitle_setup(void)
    765 {
    766 	int		i;
    767 	char		*p;
    768 
    769 	proctitle_maxlen = 0;
    770 
    771 	for (i = 0; environ[i] != NULL; i++) {
    772 		if ((p = strdup(environ[i])) == NULL)
    773 			fatal("strdup");
    774 		proctitle_maxlen += strlen(environ[i]) + 1;
    775 		environ[i] = p;
    776 	}
    777 
    778 	for (i = 0; kore_argv[i] != NULL; i++)
    779 		proctitle_maxlen += strlen(kore_argv[i]) + 1;
    780 }
    781 
    782 static void
    783 kore_server_start(int argc, char *argv[])
    784 {
    785 	u_int32_t			tmp;
    786 	struct kore_server		*srv;
    787 	u_int64_t			netwait;
    788 	int				last_sig;
    789 #if !defined(KORE_NO_HTTP)
    790 	int				alog;
    791 	struct kore_domain		*dom;
    792 #endif
    793 #if defined(KORE_SINGLE_BINARY)
    794 	struct kore_runtime_call	*rcall;
    795 #endif
    796 
    797 	if (!kore_quiet) {
    798 		kore_log(LOG_INFO, "%s %s starting, built=%s",
    799 		    __progname, kore_version, kore_build_date);
    800 		kore_log(LOG_INFO, "built-ins: "
    801 #if defined(__linux__)
    802 		    "seccomp "
    803 #endif
    804 #if defined(KORE_USE_PGSQL)
    805 		    "pgsql "
    806 #endif
    807 #if defined(KORE_USE_TASKS)
    808 		    "tasks "
    809 #endif
    810 #if defined(KORE_USE_JSONRPC)
    811 		    "jsonrpc "
    812 #endif
    813 #if defined(KORE_USE_PYTHON)
    814 		    "python "
    815 #endif
    816 #if defined(KORE_USE_ACME)
    817 		    "acme "
    818 #endif
    819 #if defined(KORE_USE_CURL)
    820 		    "curl "
    821 #endif
    822 		);
    823 	}
    824 
    825 	if (kore_foreground == 0) {
    826 		if (daemon(1, 0) == -1)
    827 			fatal("cannot daemon(): %s", errno_s);
    828 #if defined(KORE_SINGLE_BINARY)
    829 		rcall = kore_runtime_getcall(parent_daemonized_hook);
    830 		if (rcall != NULL) {
    831 			kore_runtime_execute(rcall);
    832 			kore_free(rcall);
    833 		}
    834 #endif
    835 	}
    836 
    837 	kore_pid = getpid();
    838 	kore_write_kore_pid();
    839 
    840 #if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
    841 	kore_call_parent_configure(argc, argv);
    842 #endif
    843 
    844 #if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY)
    845 	if (kore_pymodule == NULL)
    846 		kore_call_parent_configure(argc, argv);
    847 #endif
    848 
    849 #if defined(KORE_USE_PYTHON)
    850 	kore_python_routes_resolve();
    851 #endif
    852 
    853 	/* Check if keymgr will be active. */
    854 	if (kore_tls_supported()) {
    855 		LIST_FOREACH(srv, &kore_servers, list) {
    856 			if (srv->tls) {
    857 				kore_keymgr_active = 1;
    858 				break;
    859 			}
    860 		}
    861 	} else {
    862 		kore_keymgr_active = 0;
    863 	}
    864 
    865 	kore_platform_proctitle("[parent]");
    866 
    867 	if (!kore_worker_init()) {
    868 		kore_log(LOG_ERR, "last worker log lines:");
    869 		kore_log(LOG_ERR, "=====================================");
    870 		net_init();
    871 		kore_connection_init();
    872 		kore_platform_event_init();
    873 		kore_msg_parent_init();
    874 		kore_platform_event_wait(10);
    875 		kore_worker_dispatch_signal(SIGQUIT);
    876 		kore_log(LOG_ERR, "=====================================");
    877 		return;
    878 	}
    879 
    880 	/* Set worker_max_connections for kore_connection_init(). */
    881 	tmp = worker_max_connections;
    882 	worker_max_connections = worker_count;
    883 
    884 	net_init();
    885 	kore_connection_init();
    886 	kore_platform_event_init();
    887 	kore_msg_parent_init();
    888 
    889 	worker_max_connections = tmp;
    890 
    891 	kore_timer_init();
    892 
    893 #if !defined(KORE_NO_HTTP)
    894 	alog = 0;
    895 
    896 	LIST_FOREACH(srv, &kore_servers, list) {
    897 		TAILQ_FOREACH(dom, &srv->domains, list) {
    898 			if (dom->accesslog != -1)
    899 				alog = 1;
    900 		}
    901 	}
    902 
    903 	if (alog) {
    904 		kore_timer_add(kore_accesslog_run, 100, NULL, 0);
    905 		kore_log(LOG_INFO, "accesslog vacuum is enabled");
    906 	}
    907 #endif
    908 
    909 #if defined(KORE_USE_PYTHON)
    910 	kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
    911 #endif
    912 
    913 	while (kore_quit != 1) {
    914 		last_sig = sig_recv;
    915 
    916 		if (last_sig != 0) {
    917 			switch (last_sig) {
    918 			case SIGHUP:
    919 				kore_worker_dispatch_signal(last_sig);
    920 				kore_module_reload(0);
    921 				break;
    922 			case SIGINT:
    923 			case SIGQUIT:
    924 			case SIGTERM:
    925 				kore_quit = 1;
    926 				kore_worker_dispatch_signal(last_sig);
    927 				continue;
    928 			case SIGUSR1:
    929 				kore_worker_dispatch_signal(last_sig);
    930 				break;
    931 			case SIGCHLD:
    932 				kore_worker_reap();
    933 				break;
    934 			default:
    935 				break;
    936 			}
    937 
    938 			if (sig_recv == last_sig)
    939 				sig_recv = 0;
    940 			else
    941 				continue;
    942 		}
    943 
    944 		netwait = kore_timer_next_run(kore_time_ms());
    945 		kore_platform_event_wait(netwait);
    946 		kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
    947 		kore_timer_run(kore_time_ms());
    948 		kore_worker_reap();
    949 	}
    950 
    951 	kore_worker_dispatch_signal(SIGQUIT);
    952 }
    953 
    954 static void
    955 kore_server_shutdown(void)
    956 {
    957 	if (!kore_quiet)
    958 		kore_log(LOG_INFO, "server shutting down");
    959 
    960 	kore_worker_shutdown();
    961 
    962 #if !defined(KORE_NO_HTTP)
    963 	kore_accesslog_gather(NULL, kore_time_ms(), 1);
    964 #endif
    965 
    966 	kore_platform_event_cleanup();
    967 	kore_connection_cleanup();
    968 	kore_domain_cleanup();
    969 	kore_tls_cleanup();
    970 	net_cleanup();
    971 }
    972 
    973 static void
    974 kore_write_kore_pid(void)
    975 {
    976 	FILE		*fp;
    977 
    978 	if ((fp = fopen(kore_pidfile, "w+")) == NULL) {
    979 		printf("warning: couldn't write pid to %s (%s)\n",
    980 		    kore_pidfile, errno_s);
    981 	} else {
    982 		fprintf(fp, "%d\n", kore_pid);
    983 		fclose(fp);
    984 	}
    985 }
    986 
    987 static void
    988 kore_call_parent_configure(int argc, char **argv)
    989 {
    990 	struct kore_runtime_call	*rcall;
    991 
    992 	rcall = kore_runtime_getcall(parent_config_hook);
    993 	if (rcall != NULL) {
    994 		kore_runtime_configure(rcall, argc, argv);
    995 		kore_free(rcall);
    996 	}
    997 }