1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <errno.h>
35 #include <pthread.h>
36 #include <fcntl.h>
37 #include <poll.h>
38 #include <semaphore.h>
39
40 #include "../util/pool.h"
41 #include "../public/nsapi.h"
42 #include "../util/plist.h"
43 #include "../util/date.h"
44
45 #include <cx/string.h>
46
47 #include "webserver.h"
48 #include "log.h"
49 #include "httprequest.h"
50 #include "httplistener.h"
51 #include "srvctrl.h"
52
53 #include "configmanager.h"
54
55 #define LOG_THREAD_STACK_SIZE 32768
56 #define LOG_THREAD_MAX_POLL_FAILS 10
57 #define LOG_THREAD_READ_BUF 2048
58
59 static int std_out[
2];
60 static int std_err[
2];
61 static WSBool is_daemon;
62
63 void test() {
64 time_t t = time(
NULL);
65 pool_handle_t *pool = pool_create();
66 cxmutstr date = date_format_http(t, pool);
67 printf(
"%s\n", date.ptr);
68 }
69
70
71 WSBool main_is_daemon(
void) {
72 return is_daemon;
73 }
74
75
76
77
78 void sig_usr1_reload(
int sig) {
79 log_ereport(
LOG_INFORM,
"sig reload");
80 (
void)webserver_reconfig();
81 signal(
SIGUSR1, sig_usr1_reload);
82 }
83
84
85
86
87 void sig_term(
int sig) {
88 webserver_shutdown();
89
90 }
91
92 static void set_pipe_nonblocking(
int fd) {
93 int flags =
0;
94 flags = fcntl(fd,
F_GETFL,
0);
95 fcntl(fd,
F_SETFL, flags & ~
O_NONBLOCK);
96 }
97
98 static char log_pipe_readbuf[
LOG_THREAD_READ_BUF];
99 static char log_pipe_stdout_buf[
LOG_THREAD_READ_BUF];
100 static char log_pipe_stderr_buf[
LOG_THREAD_READ_BUF];
101 static size_t log_pipe_stdout_tmp_pos =
0;
102 static size_t log_pipe_stderr_tmp_pos =
0;
103
104
105
106
107 static int daemon_start_pipe[
2];
108
109
110
111 static int parent_log_pipe[
2];
112
113 static LogDup startup_log;
114
115 static void finish_daemon_startup(
int status) {
116 if(status !=
0) {
117 log_ereport(
LOG_FAILURE,
"daemon startup failed");
118 if(status >
127) {
119 status =
127;
120 }
121 }
122 char s = (
char)status;
123
124
125 write(daemon_start_pipe[
1], &s,
1);
126 close(daemon_start_pipe[
1]);
127
128
129 log_remove_logdup(&startup_log);
130 close(parent_log_pipe[
0]);
131 close(parent_log_pipe[
1]);
132 }
133
134 static int log_pipe(
const char *name,
int fd,
char *buf,
size_t *pos) {
135 ssize_t r = read(fd, log_pipe_readbuf,
2);
136 if(r <=
0) {
137 return r ==
0 ?
0 :
1;
138 }
139
140 char *tmp = buf;
141 int tmplen = *pos;
142
143 int s =
0;
144 for(
int i=
0;i<r;i++) {
145 if(log_pipe_readbuf[i] ==
'\n') {
146 if(tmplen + i-s >
0) {
147 log_message(name,
"%.*s%.*s", tmplen, tmp, i-s, log_pipe_readbuf + s);
148 }
149 tmplen =
0;
150 *pos =
0;
151 s = i+
1;
152 }
153 }
154
155 int remaining = r - s;
156 if(tmplen + remaining >=
LOG_THREAD_READ_BUF) {
157 log_message(name,
"%.*s%.*s", tmplen, tmp, remaining, log_pipe_readbuf + s);
158 *pos =
0;
159 }
else if(remaining >
0) {
160 memcpy(buf + *pos, log_pipe_readbuf + s, remaining);
161 *pos += remaining;
162 }
163
164 return 0;
165 }
166
167 void* log_pipe_thread(
void *data) {
168 set_pipe_nonblocking(std_out[
0]);
169 set_pipe_nonblocking(std_err[
0]);
170
171 struct pollfd fds[
2];
172 fds[
0].fd = std_out[
0];
173 fds[
0].events =
POLLIN;
174 fds[
1].fd = std_err[
0];
175 fds[
1].events =
POLLIN;
176
177 int poll_fails =
0;
178 for(;;) {
179 if(poll(fds,
1,
1000000) <
0) {
180 if(errno ==
EINTR) {
181 continue;
182 }
183 log_ereport(
LOG_FAILURE,
"log thread poll failed: %s", strerror(errno));
184 if(poll_fails++ >
LOG_THREAD_MAX_POLL_FAILS) {
185 break;
186 }
187 }
188
189
190 if(fds[
0].revents &
POLLIN) {
191 if(log_pipe(
"stdout", fds[
0].fd, log_pipe_stdout_buf, &log_pipe_stdout_tmp_pos)) {
192 log_ereport(
LOG_WARN,
"log_pipe stdout failed");
193 break;
194 }
195 }
196
197
198 if(fds[
1].revents &
POLLIN) {
199 if(log_pipe(
"stderr", fds[
0].fd, log_pipe_stderr_buf, &log_pipe_stderr_tmp_pos)) {
200 log_ereport(
LOG_WARN,
"log_pipe stderr failed");
201 break;
202 }
203 }
204 }
205
206 log_ereport(
LOG_INFORM,
"log thread end");
207
208 return NULL;
209 }
210
211
212
213
214
215
216 static int main_daemon_startup_wait(
void) {
217
218 char buf[
2048];
219 ssize_t r;
220 while((r = read(parent_log_pipe[
0], buf,
2048)) >
0) {
221 ssize_t pos =
0;
222 while(r >
0) {
223 ssize_t w = write(
STDOUT_FILENO, buf+pos, r-pos);
224 pos += w;
225 r -= w;
226 break;
227 }
228 }
229
230
231 char ret;
232 if(read(daemon_start_pipe[
0], &ret,
1) !=
1) {
233 return 255;
234 }
235 return ret;
236 }
237
238 static void startup_log_write(
void *cookie,
char *msg,
size_t length) {
239 write(parent_log_pipe[
1], msg, length);
240 }
241
242 int main(
int argc,
char **argv) {
243
244
245
246 is_daemon =
1;
247 for(
int i=
0;i<argc;i++) {
248 char *p = argv[i];
249 if(p[
0] ==
'-' && p[
1] ==
'c') {
250 is_daemon =
0;
251 break;
252 }
253 }
254
255 if(init_logging()) {
256 fprintf(stderr,
"OOM\n");
257 return 1;
258 }
259
260 if(is_daemon) {
261
262 if(pipe(daemon_start_pipe)) {
263 perror(
"pipe");
264 return EXIT_FAILURE;
265 }
266 if(pipe(parent_log_pipe)) {
267 perror(
"pipe");
268 return EXIT_FAILURE;
269 }
270
271 log_ereport(
LOG_INFORM,
"start daemon");
272
273
274
275
276 startup_log.write = startup_log_write;
277 log_add_logdup(&startup_log);
278
279
280 pid_t pid = fork();
281 if(pid <
0) {
282 perror(
"fork");
283 return EXIT_FAILURE;
284 }
else if(pid >
0) {
285 close(daemon_start_pipe[
1]);
286 close(parent_log_pipe[
1]);
287 return main_daemon_startup_wait();
288 }
289
290 if(setsid() <
0) {
291 fprintf(stderr,
"setsid failed\n");
292 return EXIT_FAILURE;
293 }
294
295
296 close(daemon_start_pipe[
0]);
297
298
299
300 if(pipe(std_out) !=
0) {
301 perror(
"pipe");
302 return EXIT_FAILURE;
303 }
304 if(pipe(std_err) !=
0) {
305 perror(
"pipe");
306 return EXIT_FAILURE;
307 }
308
309 for(
int i=
0;i<
3;i++) {
310 close(i);
311 }
312
313 dup2(std_out[
1],
1);
314 dup2(std_err[
1],
2);
315 close(std_out[
1]);
316 close(std_err[
1]);
317
318
319 pthread_attr_t tattr;
320 pthread_attr_init(&tattr);
321 pthread_attr_setstacksize(&tattr,
LOG_THREAD_STACK_SIZE);
322
323 pthread_t tid;
324 pthread_create(&tid, &tattr, log_pipe_thread,
NULL);
325 }
326
327 pool_init(
NULL,
NULL,
NULL);
328
329
330 signal(
SIGUSR1, sig_usr1_reload);
331 signal(
SIGTERM, sig_term);
332 signal(
SIGINT, sig_term);
333
334 struct sigaction act;
335 ZERO(&act,
sizeof(
struct sigaction));
336 act.sa_handler =
SIG_IGN;
337 sigaction(
SIGPIPE, &act,
NULL);
338
339
340 log_ereport(
LOG_INFORM,
"startup");
341
342 int status;
343 status = webserver_init();
344 if(status !=
0) {
345 log_ereport(
LOG_FAILURE,
"cannot initialize server.");
346 return EXIT_FAILURE;
347 }
348
349 status = webserver_run();
350 if(is_daemon) {
351 finish_daemon_startup(status);
352 }
353 if(status !=
0) {
354 log_ereport(
LOG_FAILURE,
"cannot run server.");
355 return EXIT_FAILURE;
356 }
357
358 if(srvctrl_wait()) {
359 return EXIT_FAILURE;
360 }
361 webserver_end();
362 log_ereport(
LOG_INFORM,
"webserver: exit");
363
364 return EXIT_SUCCESS;
365 }
366
367