aboutsummaryrefslogtreecommitdiff
path: root/gmid.c
diff options
context:
space:
mode:
Diffstat (limited to 'gmid.c')
-rw-r--r--gmid.c98
1 files changed, 59 insertions, 39 deletions
diff --git a/gmid.c b/gmid.c
index 7bd722b..56250f4 100644
--- a/gmid.c
+++ b/gmid.c
@@ -34,6 +34,8 @@ struct vhost hosts[HOSTSLEN];
int connected_clients;
int goterror;
+int exfd;
+
struct conf conf;
struct etm { /* file extension to mime */
@@ -458,7 +460,7 @@ handle(struct pollfd *fds, struct client *client)
/* fallthrough */
case S_SENDING:
- if (client->child != -1)
+ if (client->child)
handle_cgi(fds, client);
else
send_file(NULL, NULL, fds, client);
@@ -567,7 +569,8 @@ do_accept(int sock, struct tls *ctx, struct pollfd *fds, struct client *clients)
clients[i].state = S_HANDSHAKE;
clients[i].fd = -1;
- clients[i].child = -1;
+ clients[i].child = 0;
+ clients[i].waiting_on_child = 0;
clients[i].buf = MAP_FAILED;
clients[i].af = AF_INET;
clients[i].addr = addr;
@@ -730,6 +733,45 @@ load_vhosts(struct tls_config *tlsconf)
}
}
+int
+listener_main()
+{
+ int sock4, sock6;
+ struct tls *ctx = NULL;
+ struct tls_config *tlsconf;
+
+ if ((tlsconf = tls_config_new()) == NULL)
+ err(1, "tls_config_new");
+
+ /* optionally accept client certs, but don't try to verify them */
+ tls_config_verify_client_optional(tlsconf);
+ tls_config_insecure_noverifycert(tlsconf);
+
+ if (tls_config_set_protocols(tlsconf, conf.protos) == -1)
+ err(1, "tls_config_set_protocols");
+
+ if ((ctx = tls_server()) == NULL)
+ errx(1, "tls_server failure");
+
+ load_vhosts(tlsconf);
+
+ if (tls_configure(ctx, tlsconf) == -1)
+ errx(1, "tls_configure: %s", tls_error(ctx));
+
+ if (!conf.foreground && daemon(0, 1) == -1)
+ exit(1);
+
+ sock4 = make_socket(conf.port, AF_INET);
+ sock6 = -1;
+ if (conf.ipv6)
+ sock6 = make_socket(conf.port, AF_INET6);
+
+ sandbox();
+ loop(ctx, sock4, sock6);
+
+ return 0;
+}
+
void
usage(const char *me)
{
@@ -742,9 +784,7 @@ usage(const char *me)
int
main(int argc, char **argv)
{
- struct tls *ctx = NULL;
- struct tls_config *tlsconf;
- int sock4, sock6, ch;
+ int ch, p[2];
const char *config_path = NULL;
size_t i;
int conftest = 0;
@@ -838,41 +878,21 @@ main(int argc, char **argv)
if (!conf.foreground)
signal(SIGHUP, SIG_IGN);
- if ((tlsconf = tls_config_new()) == NULL)
- err(1, "tls_config_new");
-
- /* optionally accept client certs, but don't try to verify them */
- tls_config_verify_client_optional(tlsconf);
- tls_config_insecure_noverifycert(tlsconf);
-
- if (tls_config_set_protocols(tlsconf, conf.protos) == -1)
- err(1, "tls_config_set_protocols");
-
- load_vhosts(tlsconf);
-
- if ((ctx = tls_server()) == NULL)
- err(1, "tls_server");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) == -1)
+ fatal("socketpair: %s", strerror(errno));
- if (tls_configure(ctx, tlsconf) == -1)
- errx(1, "tls_configure: %s", tls_error(ctx));
-
- sock4 = make_socket(conf.port, AF_INET);
- if (conf.ipv6)
- sock6 = make_socket(conf.port, AF_INET6);
- else
- sock6 = -1;
-
- if (!conf.foreground && daemon(0, 1) == -1)
- exit(1);
-
- sandbox();
-
- loop(ctx, sock4, sock6);
+ switch (fork()) {
+ case -1:
+ fatal("fork: %s", strerror(errno));
- close(sock4);
- close(sock6);
- tls_free(ctx);
- tls_config_free(tlsconf);
+ case 0: /* child */
+ close(p[0]);
+ exfd = p[1];
+ listener_main();
+ _exit(0);
- return 0;
+ default: /* parent */
+ close(p[1]);
+ return executor_main(p[0]);
+ }
}