Blame


1 8a35f56c 2022-07-16 thomas /*
2 8a35f56c 2022-07-16 thomas * Copyright (c) 2016, 2019, 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 8a35f56c 2022-07-16 thomas * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
4 8a35f56c 2022-07-16 thomas *
5 8a35f56c 2022-07-16 thomas * Permission to use, copy, modify, and distribute this software for any
6 8a35f56c 2022-07-16 thomas * purpose with or without fee is hereby granted, provided that the above
7 8a35f56c 2022-07-16 thomas * copyright notice and this permission notice appear in all copies.
8 8a35f56c 2022-07-16 thomas *
9 8a35f56c 2022-07-16 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 8a35f56c 2022-07-16 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 8a35f56c 2022-07-16 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 8a35f56c 2022-07-16 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 8a35f56c 2022-07-16 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 8a35f56c 2022-07-16 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 8a35f56c 2022-07-16 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 8a35f56c 2022-07-16 thomas */
17 8a35f56c 2022-07-16 thomas
18 5f50119f 2023-11-25 thomas #include "got_compat.h"
19 5f50119f 2023-11-25 thomas
20 8a35f56c 2022-07-16 thomas #include <sys/param.h>
21 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
22 8a35f56c 2022-07-16 thomas #include <sys/socket.h>
23 8a35f56c 2022-07-16 thomas #include <sys/wait.h>
24 8a35f56c 2022-07-16 thomas
25 8a35f56c 2022-07-16 thomas #include <net/if.h>
26 8a35f56c 2022-07-16 thomas #include <netinet/in.h>
27 8a35f56c 2022-07-16 thomas
28 8a35f56c 2022-07-16 thomas #include <stdio.h>
29 8a35f56c 2022-07-16 thomas #include <stdlib.h>
30 8a35f56c 2022-07-16 thomas #include <string.h>
31 8a35f56c 2022-07-16 thomas #include <termios.h>
32 8a35f56c 2022-07-16 thomas #include <err.h>
33 8a35f56c 2022-07-16 thomas #include <errno.h>
34 8a35f56c 2022-07-16 thomas #include <event.h>
35 8a35f56c 2022-07-16 thomas #include <fcntl.h>
36 8a35f56c 2022-07-16 thomas #include <pwd.h>
37 8a35f56c 2022-07-16 thomas #include <signal.h>
38 8a35f56c 2022-07-16 thomas #include <syslog.h>
39 8a35f56c 2022-07-16 thomas #include <unistd.h>
40 8a35f56c 2022-07-16 thomas #include <ctype.h>
41 8a35f56c 2022-07-16 thomas
42 8a35f56c 2022-07-16 thomas #include "got_opentemp.h"
43 161663e7 2023-03-11 thomas #include "got_reference.h"
44 8a35f56c 2022-07-16 thomas
45 8a35f56c 2022-07-16 thomas #include "gotwebd.h"
46 8a35f56c 2022-07-16 thomas
47 8a35f56c 2022-07-16 thomas __dead void usage(void);
48 8a35f56c 2022-07-16 thomas
49 8a35f56c 2022-07-16 thomas int main(int, char **);
50 8a35f56c 2022-07-16 thomas int gotwebd_configure(struct gotwebd *);
51 8a35f56c 2022-07-16 thomas void gotwebd_configure_done(struct gotwebd *);
52 8a35f56c 2022-07-16 thomas void gotwebd_sighdlr(int sig, short event, void *arg);
53 8a35f56c 2022-07-16 thomas void gotwebd_shutdown(void);
54 f85c939f 2023-11-22 thomas void gotwebd_dispatch_sockets(int, short, void *);
55 8a35f56c 2022-07-16 thomas
56 8a35f56c 2022-07-16 thomas struct gotwebd *gotwebd_env;
57 8a35f56c 2022-07-16 thomas
58 f85c939f 2023-11-22 thomas void
59 f85c939f 2023-11-22 thomas imsg_event_add(struct imsgev *iev)
60 f85c939f 2023-11-22 thomas {
61 f85c939f 2023-11-22 thomas if (iev->handler == NULL) {
62 f85c939f 2023-11-22 thomas imsg_flush(&iev->ibuf);
63 f85c939f 2023-11-22 thomas return;
64 f85c939f 2023-11-22 thomas }
65 8a35f56c 2022-07-16 thomas
66 f85c939f 2023-11-22 thomas iev->events = EV_READ;
67 f85c939f 2023-11-22 thomas if (iev->ibuf.w.queued)
68 f85c939f 2023-11-22 thomas iev->events |= EV_WRITE;
69 f85c939f 2023-11-22 thomas
70 f85c939f 2023-11-22 thomas event_del(&iev->ev);
71 f85c939f 2023-11-22 thomas event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
72 f85c939f 2023-11-22 thomas event_add(&iev->ev, NULL);
73 f85c939f 2023-11-22 thomas }
74 f85c939f 2023-11-22 thomas
75 8a35f56c 2022-07-16 thomas int
76 f85c939f 2023-11-22 thomas imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
77 f85c939f 2023-11-22 thomas pid_t pid, int fd, const void *data, uint16_t datalen)
78 8a35f56c 2022-07-16 thomas {
79 f85c939f 2023-11-22 thomas int ret;
80 8a35f56c 2022-07-16 thomas
81 f85c939f 2023-11-22 thomas ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, datalen);
82 f85c939f 2023-11-22 thomas if (ret == -1)
83 f85c939f 2023-11-22 thomas return (ret);
84 f85c939f 2023-11-22 thomas imsg_event_add(iev);
85 f85c939f 2023-11-22 thomas return (ret);
86 f85c939f 2023-11-22 thomas }
87 f85c939f 2023-11-22 thomas
88 f85c939f 2023-11-22 thomas int
89 f85c939f 2023-11-22 thomas main_compose_sockets(struct gotwebd *env, uint32_t type, int fd,
90 f85c939f 2023-11-22 thomas const void *data, uint16_t len)
91 f85c939f 2023-11-22 thomas {
92 f85c939f 2023-11-22 thomas size_t i;
93 f85c939f 2023-11-22 thomas int ret, d;
94 f85c939f 2023-11-22 thomas
95 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
96 f85c939f 2023-11-22 thomas d = -1;
97 f85c939f 2023-11-22 thomas if (fd != -1 && (d = dup(fd)) == -1)
98 3bb657ab 2023-11-22 thomas goto err;
99 f85c939f 2023-11-22 thomas
100 f85c939f 2023-11-22 thomas ret = imsg_compose_event(&env->iev_server[i], type, 0, -1,
101 f85c939f 2023-11-22 thomas d, data, len);
102 f85c939f 2023-11-22 thomas if (ret == -1)
103 3bb657ab 2023-11-22 thomas goto err;
104 f85c939f 2023-11-22 thomas
105 f85c939f 2023-11-22 thomas /* prevent fd exhaustion */
106 f85c939f 2023-11-22 thomas if (d != -1) {
107 f85c939f 2023-11-22 thomas do {
108 f85c939f 2023-11-22 thomas ret = imsg_flush(&env->iev_server[i].ibuf);
109 f85c939f 2023-11-22 thomas } while (ret == -1 && errno == EAGAIN);
110 f85c939f 2023-11-22 thomas if (ret == -1)
111 3bb657ab 2023-11-22 thomas goto err;
112 f85c939f 2023-11-22 thomas imsg_event_add(&env->iev_server[i]);
113 f85c939f 2023-11-22 thomas }
114 8a35f56c 2022-07-16 thomas }
115 8a35f56c 2022-07-16 thomas
116 f85c939f 2023-11-22 thomas if (fd != -1)
117 f85c939f 2023-11-22 thomas close(fd);
118 f85c939f 2023-11-22 thomas return 0;
119 3bb657ab 2023-11-22 thomas
120 3bb657ab 2023-11-22 thomas err:
121 3bb657ab 2023-11-22 thomas if (fd != -1)
122 3bb657ab 2023-11-22 thomas close(fd);
123 3bb657ab 2023-11-22 thomas return -1;
124 8a35f56c 2022-07-16 thomas }
125 8a35f56c 2022-07-16 thomas
126 f85c939f 2023-11-22 thomas int
127 f85c939f 2023-11-22 thomas sockets_compose_main(struct gotwebd *env, uint32_t type, const void *d,
128 f85c939f 2023-11-22 thomas uint16_t len)
129 f85c939f 2023-11-22 thomas {
130 f85c939f 2023-11-22 thomas return (imsg_compose_event(env->iev_parent, type, 0, -1, -1, d, len));
131 f85c939f 2023-11-22 thomas }
132 f85c939f 2023-11-22 thomas
133 8a35f56c 2022-07-16 thomas void
134 f85c939f 2023-11-22 thomas gotwebd_dispatch_sockets(int fd, short event, void *arg)
135 f85c939f 2023-11-22 thomas {
136 f85c939f 2023-11-22 thomas struct imsgev *iev = arg;
137 f85c939f 2023-11-22 thomas struct imsgbuf *ibuf;
138 f85c939f 2023-11-22 thomas struct imsg imsg;
139 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
140 f85c939f 2023-11-22 thomas ssize_t n;
141 f85c939f 2023-11-22 thomas int shut = 0;
142 f85c939f 2023-11-22 thomas
143 f85c939f 2023-11-22 thomas ibuf = &iev->ibuf;
144 f85c939f 2023-11-22 thomas
145 f85c939f 2023-11-22 thomas if (event & EV_READ) {
146 f85c939f 2023-11-22 thomas if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
147 f85c939f 2023-11-22 thomas fatal("imsg_read error");
148 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
149 f85c939f 2023-11-22 thomas shut = 1;
150 f85c939f 2023-11-22 thomas }
151 f85c939f 2023-11-22 thomas if (event & EV_WRITE) {
152 f85c939f 2023-11-22 thomas if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
153 f85c939f 2023-11-22 thomas fatal("msgbuf_write");
154 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
155 f85c939f 2023-11-22 thomas shut = 1;
156 f85c939f 2023-11-22 thomas }
157 f85c939f 2023-11-22 thomas
158 f85c939f 2023-11-22 thomas for (;;) {
159 f85c939f 2023-11-22 thomas if ((n = imsg_get(ibuf, &imsg)) == -1)
160 f85c939f 2023-11-22 thomas fatal("imsg_get");
161 f85c939f 2023-11-22 thomas if (n == 0) /* No more messages. */
162 f85c939f 2023-11-22 thomas break;
163 f85c939f 2023-11-22 thomas
164 f85c939f 2023-11-22 thomas switch (imsg.hdr.type) {
165 f85c939f 2023-11-22 thomas case IMSG_CFG_DONE:
166 f85c939f 2023-11-22 thomas gotwebd_configure_done(env);
167 f85c939f 2023-11-22 thomas break;
168 f85c939f 2023-11-22 thomas default:
169 f85c939f 2023-11-22 thomas fatalx("%s: unknown imsg type %d", __func__,
170 f85c939f 2023-11-22 thomas imsg.hdr.type);
171 f85c939f 2023-11-22 thomas }
172 f85c939f 2023-11-22 thomas
173 f85c939f 2023-11-22 thomas imsg_free(&imsg);
174 f85c939f 2023-11-22 thomas }
175 f85c939f 2023-11-22 thomas
176 f85c939f 2023-11-22 thomas if (!shut)
177 f85c939f 2023-11-22 thomas imsg_event_add(iev);
178 f85c939f 2023-11-22 thomas else {
179 f85c939f 2023-11-22 thomas /* This pipe is dead. Remove its event handler */
180 f85c939f 2023-11-22 thomas event_del(&iev->ev);
181 f85c939f 2023-11-22 thomas event_loopexit(NULL);
182 f85c939f 2023-11-22 thomas }
183 f85c939f 2023-11-22 thomas }
184 f85c939f 2023-11-22 thomas
185 f85c939f 2023-11-22 thomas void
186 8a35f56c 2022-07-16 thomas gotwebd_sighdlr(int sig, short event, void *arg)
187 8a35f56c 2022-07-16 thomas {
188 8a35f56c 2022-07-16 thomas /* struct privsep *ps = arg; */
189 8a35f56c 2022-07-16 thomas
190 8a35f56c 2022-07-16 thomas switch (sig) {
191 8a35f56c 2022-07-16 thomas case SIGHUP:
192 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGHUP", __func__);
193 8a35f56c 2022-07-16 thomas break;
194 8a35f56c 2022-07-16 thomas case SIGPIPE:
195 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGPIPE", __func__);
196 8a35f56c 2022-07-16 thomas break;
197 8a35f56c 2022-07-16 thomas case SIGUSR1:
198 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGUSR1", __func__);
199 8a35f56c 2022-07-16 thomas break;
200 8a35f56c 2022-07-16 thomas case SIGTERM:
201 8a35f56c 2022-07-16 thomas case SIGINT:
202 8a35f56c 2022-07-16 thomas gotwebd_shutdown();
203 8a35f56c 2022-07-16 thomas break;
204 8a35f56c 2022-07-16 thomas default:
205 8a35f56c 2022-07-16 thomas fatalx("unexpected signal");
206 8a35f56c 2022-07-16 thomas }
207 8a35f56c 2022-07-16 thomas }
208 8a35f56c 2022-07-16 thomas
209 f85c939f 2023-11-22 thomas static int
210 f85c939f 2023-11-22 thomas spawn_socket_process(struct gotwebd *env, const char *argv0, int n)
211 f85c939f 2023-11-22 thomas {
212 f85c939f 2023-11-22 thomas const char *argv[5];
213 f85c939f 2023-11-22 thomas int argc = 0;
214 f85c939f 2023-11-22 thomas int p[2];
215 f85c939f 2023-11-22 thomas pid_t pid;
216 f85c939f 2023-11-22 thomas
217 f85c939f 2023-11-22 thomas if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) == -1)
218 f85c939f 2023-11-22 thomas fatal("socketpair");
219 f85c939f 2023-11-22 thomas
220 f85c939f 2023-11-22 thomas switch (pid = fork()) {
221 f85c939f 2023-11-22 thomas case -1:
222 f85c939f 2023-11-22 thomas fatal("fork");
223 f85c939f 2023-11-22 thomas case 0: /* child */
224 f85c939f 2023-11-22 thomas break;
225 f85c939f 2023-11-22 thomas default: /* parent */
226 f85c939f 2023-11-22 thomas close(p[0]);
227 f85c939f 2023-11-22 thomas imsg_init(&env->iev_server[n].ibuf, p[1]);
228 f85c939f 2023-11-22 thomas env->iev_server[n].handler = gotwebd_dispatch_sockets;
229 f85c939f 2023-11-22 thomas env->iev_server[n].data = &env->iev_server[n];
230 f85c939f 2023-11-22 thomas event_set(&env->iev_server[n].ev, p[1], EV_READ,
231 f85c939f 2023-11-22 thomas gotwebd_dispatch_sockets, &env->iev_server[n]);
232 f85c939f 2023-11-22 thomas event_add(&env->iev_server[n].ev, NULL);
233 f85c939f 2023-11-22 thomas return 0;
234 f85c939f 2023-11-22 thomas }
235 f85c939f 2023-11-22 thomas
236 f85c939f 2023-11-22 thomas close(p[1]);
237 f85c939f 2023-11-22 thomas
238 f85c939f 2023-11-22 thomas argv[argc++] = argv0;
239 f85c939f 2023-11-22 thomas argv[argc++] = "-S";
240 f85c939f 2023-11-22 thomas if (env->gotwebd_debug)
241 f85c939f 2023-11-22 thomas argv[argc++] = "-d";
242 f85c939f 2023-11-22 thomas if (env->gotwebd_verbose)
243 f85c939f 2023-11-22 thomas argv[argc++] = "-v";
244 f85c939f 2023-11-22 thomas argv[argc] = NULL;
245 f85c939f 2023-11-22 thomas
246 f1e20d01 2023-11-22 thomas if (p[0] != GOTWEBD_SOCK_FILENO) {
247 f1e20d01 2023-11-22 thomas if (dup2(p[0], GOTWEBD_SOCK_FILENO) == -1)
248 f85c939f 2023-11-22 thomas fatal("dup2");
249 f85c939f 2023-11-22 thomas } else if (fcntl(p[0], F_SETFD, 0) == -1)
250 f85c939f 2023-11-22 thomas fatal("fcntl");
251 f85c939f 2023-11-22 thomas
252 f85c939f 2023-11-22 thomas /* obnoxious cast */
253 f85c939f 2023-11-22 thomas execvp(argv0, (char * const *)argv);
254 f85c939f 2023-11-22 thomas fatal("execvp %s", argv0);
255 f85c939f 2023-11-22 thomas }
256 f85c939f 2023-11-22 thomas
257 8a35f56c 2022-07-16 thomas __dead void
258 8a35f56c 2022-07-16 thomas usage(void)
259 8a35f56c 2022-07-16 thomas {
260 8a35f56c 2022-07-16 thomas fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
261 8a35f56c 2022-07-16 thomas getprogname());
262 8a35f56c 2022-07-16 thomas exit(1);
263 8a35f56c 2022-07-16 thomas }
264 8a35f56c 2022-07-16 thomas
265 8a35f56c 2022-07-16 thomas int
266 8a35f56c 2022-07-16 thomas main(int argc, char **argv)
267 8a35f56c 2022-07-16 thomas {
268 f85c939f 2023-11-22 thomas struct event sigint, sigterm, sighup, sigpipe, sigusr1;
269 f85c939f 2023-11-22 thomas struct gotwebd *env;
270 f85c939f 2023-11-22 thomas struct passwd *pw;
271 f85c939f 2023-11-22 thomas int ch, i;
272 f85c939f 2023-11-22 thomas int no_action = 0;
273 f85c939f 2023-11-22 thomas int server_proc = 0;
274 f85c939f 2023-11-22 thomas const char *conffile = GOTWEBD_CONF;
275 f85c939f 2023-11-22 thomas const char *argv0;
276 8a35f56c 2022-07-16 thomas
277 f85c939f 2023-11-22 thomas if ((argv0 = argv[0]) == NULL)
278 f85c939f 2023-11-22 thomas argv0 = "gotwebd";
279 aada9b03 2023-11-22 thomas
280 aada9b03 2023-11-22 thomas /* log to stderr until daemonized */
281 aada9b03 2023-11-22 thomas log_init(1, LOG_DAEMON);
282 f85c939f 2023-11-22 thomas
283 8a35f56c 2022-07-16 thomas env = calloc(1, sizeof(*env));
284 8a35f56c 2022-07-16 thomas if (env == NULL)
285 8a35f56c 2022-07-16 thomas fatal("%s: calloc", __func__);
286 f85c939f 2023-11-22 thomas config_init(env);
287 b9c7eb91 2023-11-16 thomas
288 f85c939f 2023-11-22 thomas while ((ch = getopt(argc, argv, "D:df:nSv")) != -1) {
289 8a35f56c 2022-07-16 thomas switch (ch) {
290 8a35f56c 2022-07-16 thomas case 'D':
291 8a35f56c 2022-07-16 thomas if (cmdline_symset(optarg) < 0)
292 8a35f56c 2022-07-16 thomas log_warnx("could not parse macro definition %s",
293 8a35f56c 2022-07-16 thomas optarg);
294 8a35f56c 2022-07-16 thomas break;
295 8a35f56c 2022-07-16 thomas case 'd':
296 f85c939f 2023-11-22 thomas env->gotwebd_debug = 1;
297 8a35f56c 2022-07-16 thomas break;
298 8a35f56c 2022-07-16 thomas case 'f':
299 8a35f56c 2022-07-16 thomas conffile = optarg;
300 8a35f56c 2022-07-16 thomas break;
301 8a35f56c 2022-07-16 thomas case 'n':
302 f85c939f 2023-11-22 thomas no_action = 1;
303 8a35f56c 2022-07-16 thomas break;
304 f85c939f 2023-11-22 thomas case 'S':
305 f85c939f 2023-11-22 thomas server_proc = 1;
306 8a35f56c 2022-07-16 thomas break;
307 f7065961 2022-10-27 thomas case 'v':
308 f7065961 2022-10-27 thomas env->gotwebd_verbose++;
309 8a35f56c 2022-07-16 thomas break;
310 8a35f56c 2022-07-16 thomas default:
311 8a35f56c 2022-07-16 thomas usage();
312 8a35f56c 2022-07-16 thomas }
313 8a35f56c 2022-07-16 thomas }
314 8a35f56c 2022-07-16 thomas
315 8a35f56c 2022-07-16 thomas argc -= optind;
316 8a35f56c 2022-07-16 thomas if (argc > 0)
317 8a35f56c 2022-07-16 thomas usage();
318 8a35f56c 2022-07-16 thomas
319 8a35f56c 2022-07-16 thomas gotwebd_env = env;
320 8a35f56c 2022-07-16 thomas env->gotwebd_conffile = conffile;
321 8a35f56c 2022-07-16 thomas
322 8a35f56c 2022-07-16 thomas if (parse_config(env->gotwebd_conffile, env) == -1)
323 8a35f56c 2022-07-16 thomas exit(1);
324 8a35f56c 2022-07-16 thomas
325 f85c939f 2023-11-22 thomas if (no_action) {
326 f85c939f 2023-11-22 thomas fprintf(stderr, "configuration OK\n");
327 f85c939f 2023-11-22 thomas exit(0);
328 f85c939f 2023-11-22 thomas }
329 8a35f56c 2022-07-16 thomas
330 8a35f56c 2022-07-16 thomas /* check for root privileges */
331 f85c939f 2023-11-22 thomas if (geteuid())
332 f85c939f 2023-11-22 thomas fatalx("need root privileges");
333 8a35f56c 2022-07-16 thomas
334 f85c939f 2023-11-22 thomas pw = getpwnam(GOTWEBD_USER);
335 f85c939f 2023-11-22 thomas if (pw == NULL)
336 8a35f56c 2022-07-16 thomas fatalx("unknown user %s", GOTWEBD_USER);
337 f85c939f 2023-11-22 thomas env->pw = pw;
338 8a35f56c 2022-07-16 thomas
339 8a35f56c 2022-07-16 thomas log_init(env->gotwebd_debug, LOG_DAEMON);
340 8a35f56c 2022-07-16 thomas log_setverbose(env->gotwebd_verbose);
341 8a35f56c 2022-07-16 thomas
342 f85c939f 2023-11-22 thomas if (server_proc) {
343 f85c939f 2023-11-22 thomas setproctitle("sockets");
344 f85c939f 2023-11-22 thomas log_procinit("sockets");
345 8a35f56c 2022-07-16 thomas
346 96061886 2023-12-08 thomas if (chroot(env->httpd_chroot) == -1)
347 96061886 2023-12-08 thomas fatal("chroot %s", env->httpd_chroot);
348 f85c939f 2023-11-22 thomas if (chdir("/") == -1)
349 f85c939f 2023-11-22 thomas fatal("chdir /");
350 f85c939f 2023-11-22 thomas if (setgroups(1, &pw->pw_gid) == -1 ||
351 f85c939f 2023-11-22 thomas setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
352 f85c939f 2023-11-22 thomas setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
353 f85c939f 2023-11-22 thomas fatal("failed to drop privileges");
354 8a35f56c 2022-07-16 thomas
355 f1e20d01 2023-11-22 thomas sockets(env, GOTWEBD_SOCK_FILENO);
356 f85c939f 2023-11-22 thomas return 1;
357 f85c939f 2023-11-22 thomas }
358 8a35f56c 2022-07-16 thomas
359 1962c340 2023-11-22 thomas if (!env->gotwebd_debug && daemon(1, 0) == -1)
360 f85c939f 2023-11-22 thomas fatal("daemon");
361 8a35f56c 2022-07-16 thomas
362 8a35f56c 2022-07-16 thomas event_init();
363 8a35f56c 2022-07-16 thomas
364 f85c939f 2023-11-22 thomas env->nserver = env->prefork_gotwebd;
365 f85c939f 2023-11-22 thomas env->iev_server = calloc(env->nserver, sizeof(*env->iev_server));
366 f85c939f 2023-11-22 thomas if (env->iev_server == NULL)
367 f85c939f 2023-11-22 thomas fatal("calloc");
368 8a35f56c 2022-07-16 thomas
369 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
370 f85c939f 2023-11-22 thomas if (spawn_socket_process(env, argv0, i) == -1)
371 f85c939f 2023-11-22 thomas fatal("spawn_socket_process");
372 f85c939f 2023-11-22 thomas }
373 8a35f56c 2022-07-16 thomas
374 1962c340 2023-11-22 thomas if (chdir("/") == -1)
375 1962c340 2023-11-22 thomas fatal("chdir /");
376 1962c340 2023-11-22 thomas
377 f85c939f 2023-11-22 thomas log_procinit("gotwebd");
378 8a35f56c 2022-07-16 thomas
379 f85c939f 2023-11-22 thomas log_info("%s startup", getprogname());
380 f85c939f 2023-11-22 thomas
381 f85c939f 2023-11-22 thomas signal_set(&sigint, SIGINT, gotwebd_sighdlr, env);
382 f85c939f 2023-11-22 thomas signal_set(&sigterm, SIGTERM, gotwebd_sighdlr, env);
383 f85c939f 2023-11-22 thomas signal_set(&sighup, SIGHUP, gotwebd_sighdlr, env);
384 f85c939f 2023-11-22 thomas signal_set(&sigpipe, SIGPIPE, gotwebd_sighdlr, env);
385 f85c939f 2023-11-22 thomas signal_set(&sigusr1, SIGUSR1, gotwebd_sighdlr, env);
386 f85c939f 2023-11-22 thomas
387 f85c939f 2023-11-22 thomas signal_add(&sigint, NULL);
388 f85c939f 2023-11-22 thomas signal_add(&sigterm, NULL);
389 f85c939f 2023-11-22 thomas signal_add(&sighup, NULL);
390 f85c939f 2023-11-22 thomas signal_add(&sigpipe, NULL);
391 f85c939f 2023-11-22 thomas signal_add(&sigusr1, NULL);
392 f85c939f 2023-11-22 thomas
393 8a35f56c 2022-07-16 thomas if (gotwebd_configure(env) == -1)
394 8a35f56c 2022-07-16 thomas fatalx("configuration failed");
395 8a35f56c 2022-07-16 thomas
396 8a35f56c 2022-07-16 thomas #ifdef PROFILE
397 8a35f56c 2022-07-16 thomas if (unveil("gmon.out", "rwc") != 0)
398 8a35f56c 2022-07-16 thomas err(1, "gmon.out");
399 8a35f56c 2022-07-16 thomas #endif
400 8a35f56c 2022-07-16 thomas
401 79e60db6 2023-11-14 thomas if (unveil(env->httpd_chroot, "r") == -1)
402 8a35f56c 2022-07-16 thomas err(1, "unveil");
403 8a35f56c 2022-07-16 thomas
404 8a35f56c 2022-07-16 thomas if (unveil(GOTWEBD_CONF, "r") == -1)
405 8a35f56c 2022-07-16 thomas err(1, "unveil");
406 8a35f56c 2022-07-16 thomas
407 8a35f56c 2022-07-16 thomas if (unveil(NULL, NULL) != 0)
408 8a35f56c 2022-07-16 thomas err(1, "unveil");
409 8a35f56c 2022-07-16 thomas
410 8a35f56c 2022-07-16 thomas #ifndef PROFILE
411 9cfaa638 2023-11-14 thomas if (pledge("stdio", NULL) == -1)
412 8a35f56c 2022-07-16 thomas err(1, "pledge");
413 8a35f56c 2022-07-16 thomas #endif
414 8a35f56c 2022-07-16 thomas
415 8a35f56c 2022-07-16 thomas event_dispatch();
416 8a35f56c 2022-07-16 thomas
417 8a35f56c 2022-07-16 thomas log_debug("%s gotwebd exiting", getprogname());
418 8a35f56c 2022-07-16 thomas
419 8a35f56c 2022-07-16 thomas return (0);
420 8a35f56c 2022-07-16 thomas }
421 8a35f56c 2022-07-16 thomas
422 8a35f56c 2022-07-16 thomas int
423 8a35f56c 2022-07-16 thomas gotwebd_configure(struct gotwebd *env)
424 8a35f56c 2022-07-16 thomas {
425 8a35f56c 2022-07-16 thomas struct server *srv;
426 8a35f56c 2022-07-16 thomas struct socket *sock;
427 8a35f56c 2022-07-16 thomas
428 8a35f56c 2022-07-16 thomas /* gotweb need to reload its config. */
429 8a35f56c 2022-07-16 thomas env->gotwebd_reload = env->prefork_gotwebd;
430 8a35f56c 2022-07-16 thomas
431 8a35f56c 2022-07-16 thomas /* send our gotweb servers */
432 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &env->servers, entry) {
433 8a35f56c 2022-07-16 thomas if (config_setserver(env, srv) == -1)
434 8a35f56c 2022-07-16 thomas fatalx("%s: send server error", __func__);
435 8a35f56c 2022-07-16 thomas }
436 8a35f56c 2022-07-16 thomas
437 8a35f56c 2022-07-16 thomas /* send our sockets */
438 90d63d47 2022-08-16 thomas TAILQ_FOREACH(sock, &env->sockets, entry) {
439 8a35f56c 2022-07-16 thomas if (config_setsock(env, sock) == -1)
440 8a35f56c 2022-07-16 thomas fatalx("%s: send socket error", __func__);
441 8a35f56c 2022-07-16 thomas if (config_setfd(env, sock) == -1)
442 8a35f56c 2022-07-16 thomas fatalx("%s: send priv_fd error", __func__);
443 8a35f56c 2022-07-16 thomas }
444 8a35f56c 2022-07-16 thomas
445 f85c939f 2023-11-22 thomas if (main_compose_sockets(env, IMSG_CFG_DONE, -1, NULL, 0) == -1)
446 f85c939f 2023-11-22 thomas fatal("main_compose_sockets IMSG_CFG_DONE");
447 8a35f56c 2022-07-16 thomas
448 8a35f56c 2022-07-16 thomas return (0);
449 8a35f56c 2022-07-16 thomas }
450 8a35f56c 2022-07-16 thomas
451 8a35f56c 2022-07-16 thomas void
452 8a35f56c 2022-07-16 thomas gotwebd_configure_done(struct gotwebd *env)
453 8a35f56c 2022-07-16 thomas {
454 8a35f56c 2022-07-16 thomas if (env->gotwebd_reload == 0) {
455 8a35f56c 2022-07-16 thomas log_warnx("%s: configuration already finished", __func__);
456 8a35f56c 2022-07-16 thomas return;
457 8a35f56c 2022-07-16 thomas }
458 8a35f56c 2022-07-16 thomas
459 8a35f56c 2022-07-16 thomas env->gotwebd_reload--;
460 f85c939f 2023-11-22 thomas if (env->gotwebd_reload == 0 &&
461 f85c939f 2023-11-22 thomas main_compose_sockets(env, IMSG_CTL_START, -1, NULL, 0) == -1)
462 f85c939f 2023-11-22 thomas fatal("main_compose_sockets IMSG_CTL_START");
463 8a35f56c 2022-07-16 thomas }
464 8a35f56c 2022-07-16 thomas
465 8a35f56c 2022-07-16 thomas void
466 8a35f56c 2022-07-16 thomas gotwebd_shutdown(void)
467 8a35f56c 2022-07-16 thomas {
468 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
469 f85c939f 2023-11-22 thomas pid_t pid;
470 f85c939f 2023-11-22 thomas int i, status;
471 8a35f56c 2022-07-16 thomas
472 f85c939f 2023-11-22 thomas for (i = 0; i < env->nserver; ++i) {
473 f85c939f 2023-11-22 thomas event_del(&env->iev_server[i].ev);
474 f85c939f 2023-11-22 thomas imsg_clear(&env->iev_server[i].ibuf);
475 f85c939f 2023-11-22 thomas close(env->iev_server[i].ibuf.fd);
476 f85c939f 2023-11-22 thomas env->iev_server[i].ibuf.fd = -1;
477 f85c939f 2023-11-22 thomas }
478 f85c939f 2023-11-22 thomas
479 f85c939f 2023-11-22 thomas do {
480 f85c939f 2023-11-22 thomas pid = waitpid(WAIT_ANY, &status, 0);
481 f85c939f 2023-11-22 thomas if (pid <= 0)
482 f85c939f 2023-11-22 thomas continue;
483 f85c939f 2023-11-22 thomas
484 f85c939f 2023-11-22 thomas if (WIFSIGNALED(status))
485 f85c939f 2023-11-22 thomas log_warnx("lost child: pid %u terminated; signal %d",
486 f85c939f 2023-11-22 thomas pid, WTERMSIG(status));
487 f85c939f 2023-11-22 thomas else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
488 f85c939f 2023-11-22 thomas log_warnx("lost child: pid %u exited abnormally",
489 f85c939f 2023-11-22 thomas pid);
490 f85c939f 2023-11-22 thomas } while (pid != -1 || (pid == -1 && errno == EINTR));
491 f85c939f 2023-11-22 thomas
492 8a35f56c 2022-07-16 thomas free(gotwebd_env);
493 8a35f56c 2022-07-16 thomas
494 8a35f56c 2022-07-16 thomas log_warnx("gotwebd terminating");
495 8a35f56c 2022-07-16 thomas exit(0);
496 8a35f56c 2022-07-16 thomas }