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 (20132B)



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