Commit Diff


commit - 91f92cd4202d248899939b44dc3d4414d448a997
commit + 97e0634664f953267d4dca4b99383e4dfb25b817
blob - 1145399328b3be0c33705a4e62c64acf5072b386
blob + 453a31f9322abec89be8bdabd70c4897958d6883
--- gotwebd/gotwebd.c
+++ gotwebd/gotwebd.c
@@ -832,8 +832,19 @@ connect_children(struct gotwebd *env)
 		    NULL, 0))
 			fatal("send_imsg");
 		if (send_imsg(iev_gotweb, GOTWEBD_IMSG_CTL_PIPE, pipe[1],
+		    NULL, 0))
+			fatal("send_imsg");
+
+		if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe) == -1)
+			fatal("socketpair");
+
+		/* login -> access */
+		if (send_imsg(iev_login, GOTWEBD_IMSG_CTL_PIPE, pipe[0],
 		    NULL, 0))
 			fatal("send_imsg");
+		if (send_imsg(env->iev_access, GOTWEBD_IMSG_CTL_PIPE, pipe[1],
+		    NULL, 0))
+			fatal("send_imsg");
 	}
 }
 
@@ -1009,6 +1020,9 @@ gotwebd_configure_done(struct gotwebd *env)
 		if (main_compose_auth(env, GOTWEBD_IMSG_CTL_START,
 			-1, NULL, 0) == -1)
 			fatal("main_compose_auth GOTWEBD_IMSG_CTL_START");
+		if (send_imsg(env->iev_access, GOTWEBD_IMSG_CTL_START,
+			-1, NULL, 0) == -1)
+			fatal("send_imsg GOTWEBD_IMSG_CTL_START");
 	}
 }
 
blob - 9a0ec573dc71633cac84edcd4b1cf9c6889c3fa4
blob + 5c32a8e96a102bf500f969c4d00558c3ad7a8c75
--- gotwebd/login.c
+++ gotwebd/login.c
@@ -53,6 +53,10 @@ login_shutdown(void)
 		imsgbuf_clear(&env->iev_gotweb->ibuf);
 		free(env->iev_gotweb);
 	}
+	if (env->iev_access) {
+		imsgbuf_clear(&env->iev_access->ibuf);
+		free(env->iev_access);
+	}
 	free(env);
 
 	exit(0);
@@ -88,6 +92,7 @@ login_launch(struct gotwebd *env)
 {
 	event_add(&env->iev_server->ev, NULL);
 	event_add(&env->iev_gotweb->ev, NULL);
+	event_add(&env->iev_access->ev, NULL);
 }
 
 static void
@@ -543,9 +548,86 @@ recv_gotweb_pipe(struct gotwebd *env, struct imsg *ims
 	imsg_event_add(iev);
 
 	env->iev_gotweb = iev;
+}
+
+static void
+login_dispatch_access(int fd, short event, void *arg)
+{
+	struct imsgev		*iev = arg;
+	struct imsgbuf		*ibuf;
+	struct imsg		 imsg;
+	ssize_t			 n;
+	int			 shut = 0;
+
+	ibuf = &iev->ibuf;
+
+	if (event & EV_READ) {
+		if ((n = imsgbuf_read(ibuf)) == -1)
+			fatal("imsgbuf_read error");
+		if (n == 0)	/* Connection closed */
+			shut = 1;
+	}
+	if (event & EV_WRITE) {
+		if (imsgbuf_write(ibuf) == -1)
+			fatal("imsgbuf_write");
+	}
+
+	for (;;) {
+		if ((n = imsg_get(ibuf, &imsg)) == -1)
+			fatal("imsg_get");
+		if (n == 0)	/* No more messages. */
+			break;
+
+		switch (imsg.hdr.type) {
+		default:
+			fatalx("%s: unknown imsg type %d", __func__,
+			    imsg.hdr.type);
+		}
+
+		imsg_free(&imsg);
+	}
+
+	if (!shut)
+		imsg_event_add(iev);
+	else {
+		/* This pipe is dead.  Remove its event handler */
+		event_del(&iev->ev);
+		event_loopexit(NULL);
+	}
 }
 
 static void
+recv_access_pipe(struct gotwebd *env, struct imsg *imsg)
+{
+	struct imsgev *iev;
+	int fd;
+
+	if (env->iev_access != NULL) {
+		log_warn("access pipe already received");
+		return;
+	}
+
+	fd = imsg_get_fd(imsg);
+	if (fd == -1)
+		fatalx("invalid access pipe fd");
+
+	iev = calloc(1, sizeof(*iev));
+	if (iev == NULL)
+		fatal("calloc");
+
+	if (imsgbuf_init(&iev->ibuf, fd) == -1)
+		fatal("imsgbuf_init");
+	imsgbuf_allow_fdpass(&iev->ibuf);
+
+	iev->handler = login_dispatch_access;
+	iev->data = iev;
+	event_set(&iev->ev, fd, EV_READ, login_dispatch_access, iev);
+	imsg_event_add(iev);
+
+	env->iev_access = iev;
+}
+
+static void
 login_dispatch_main(int fd, short event, void *arg)
 {
 	struct imsgev		*iev = arg;
@@ -609,8 +691,10 @@ login_dispatch_main(int fd, short event, void *arg)
 		case GOTWEBD_IMSG_CTL_PIPE:
 			if (env->iev_server == NULL)
 				recv_server_pipe(env, &imsg);
-			else
+			else if (env->iev_gotweb == NULL)
 				recv_gotweb_pipe(env, &imsg);
+			else 
+				recv_access_pipe(env, &imsg);
 			break;
 		case GOTWEBD_IMSG_CTL_START:
 			login_launch(env);