1 #include "uwsgi.h"
2
3
4 extern struct uwsgi_server uwsgi;
5
6 #ifdef __BIG_ENDIAN__
uwsgi_swap16(uint16_t x)7 uint16_t uwsgi_swap16(uint16_t x) {
8 return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8);
9 }
10
uwsgi_swap32(uint32_t x)11 uint32_t uwsgi_swap32(uint32_t x) {
12 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
13 return (x >> 16) | (x << 16);
14 }
15
16 // thanks to ffmpeg project for this idea :P
uwsgi_swap64(uint64_t x)17 uint64_t uwsgi_swap64(uint64_t x) {
18 union {
19 uint64_t ll;
20 uint32_t l[2];
21 } w, r;
22 w.ll = x;
23 r.l[0] = uwsgi_swap32(w.l[1]);
24 r.l[1] = uwsgi_swap32(w.l[0]);
25 return r.ll;
26 }
27
28 #endif
29
30 // check if a string is a valid hex number
check_hex(char * str,int len)31 int check_hex(char *str, int len) {
32 int i;
33 for (i = 0; i < len; i++) {
34 if ((str[i] < '0' && str[i] > '9') && (str[i] < 'a' && str[i] > 'f') && (str[i] < 'A' && str[i] > 'F')
35 ) {
36 return 0;
37 }
38 }
39
40 return 1;
41
42 }
43
44 // increase worker harakiri
inc_harakiri(int sec)45 void inc_harakiri(int sec) {
46 if (uwsgi.master_process) {
47 uwsgi.workers[uwsgi.mywid].harakiri += sec;
48 }
49 else {
50 alarm(uwsgi.harakiri_options.workers + sec);
51 }
52 }
53
54 // set worker harakiri
set_harakiri(int sec)55 void set_harakiri(int sec) {
56 if (sec == 0) {
57 uwsgi.workers[uwsgi.mywid].harakiri = 0;
58 }
59 else {
60 uwsgi.workers[uwsgi.mywid].harakiri = uwsgi_now() + sec;
61 }
62 if (!uwsgi.master_process) {
63 alarm(sec);
64 }
65 }
66
67 // set user harakiri
set_user_harakiri(int sec)68 void set_user_harakiri(int sec) {
69 if (!uwsgi.master_process) {
70 uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
71 return;
72 }
73 // a 0 seconds value, reset the timer
74 if (sec == 0) {
75 if (uwsgi.muleid > 0) {
76 uwsgi.mules[uwsgi.muleid - 1].user_harakiri = 0;
77 }
78 else if (uwsgi.i_am_a_spooler) {
79 struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
80 uspool->user_harakiri = 0;
81 }
82 else {
83 uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
84 }
85 }
86 else {
87 if (uwsgi.muleid > 0) {
88 uwsgi.mules[uwsgi.muleid - 1].user_harakiri = uwsgi_now() + sec;
89 }
90 else if (uwsgi.i_am_a_spooler) {
91 struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
92 uspool->user_harakiri = uwsgi_now() + sec;
93 }
94 else {
95 uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
96 }
97 }
98 }
99
100 // set mule harakiri
set_mule_harakiri(int sec)101 void set_mule_harakiri(int sec) {
102 if (sec == 0) {
103 uwsgi.mules[uwsgi.muleid - 1].harakiri = 0;
104 }
105 else {
106 uwsgi.mules[uwsgi.muleid - 1].harakiri = uwsgi_now() + sec;
107 }
108 if (!uwsgi.master_process) {
109 alarm(sec);
110 }
111 }
112
113 // set spooler harakiri
set_spooler_harakiri(int sec)114 void set_spooler_harakiri(int sec) {
115 if (sec == 0) {
116 uwsgi.i_am_a_spooler->harakiri = 0;
117 }
118 else {
119 uwsgi.i_am_a_spooler->harakiri = uwsgi_now() + sec;
120 }
121 if (!uwsgi.master_process) {
122 alarm(sec);
123 }
124 }
125
126
127 // daemonize to the specified logfile
daemonize(char * logfile)128 void daemonize(char *logfile) {
129 pid_t pid;
130
131 // do not daemonize under emperor
132 if (uwsgi.has_emperor) {
133 logto(logfile);
134 return;
135 }
136
137 pid = fork();
138 if (pid < 0) {
139 uwsgi_error("fork()");
140 exit(1);
141 }
142 if (pid != 0) {
143 _exit(0);
144 }
145
146 if (setsid() < 0) {
147 uwsgi_error("setsid()");
148 exit(1);
149 }
150
151 /* refork... */
152 pid = fork();
153 if (pid < 0) {
154 uwsgi_error("fork()");
155 exit(1);
156 }
157 if (pid != 0) {
158 _exit(0);
159 }
160
161 if (!uwsgi.do_not_change_umask) {
162 umask(0);
163 }
164
165 /*if (chdir("/") != 0) {
166 uwsgi_error("chdir()");
167 exit(1);
168 } */
169
170 uwsgi_remap_fd(0, "/dev/null");
171
172 logto(logfile);
173 }
174
175 // get current working directory
uwsgi_get_cwd()176 char *uwsgi_get_cwd() {
177
178 // set this to static to avoid useless reallocations in stats mode
179 static size_t newsize = 256;
180
181 char *cwd = uwsgi_malloc(newsize);
182
183 if (getcwd(cwd, newsize) == NULL && errno == ERANGE) {
184 newsize += 256;
185 uwsgi_log("need a bigger buffer (%lu bytes) for getcwd(). doing reallocation.\n", (unsigned long) newsize);
186 free(cwd);
187 cwd = uwsgi_malloc(newsize);
188 if (getcwd(cwd, newsize) == NULL) {
189 uwsgi_error("getcwd()");
190 exit(1);
191 }
192 }
193
194 return cwd;
195
196 }
197
198 #ifdef __linux__
uwsgi_set_cgroup()199 void uwsgi_set_cgroup() {
200
201 char *cgroup_taskfile;
202 FILE *cgroup;
203 char *cgroup_opt;
204 struct uwsgi_string_list *usl, *uslo;
205
206 if (!uwsgi.cgroup)
207 return;
208
209 if (getuid())
210 return;
211
212 usl = uwsgi.cgroup;
213
214 while (usl) {
215 int mode = strtol(uwsgi.cgroup_dir_mode, 0, 8);
216 if (mkdir(usl->value, mode)) {
217 if (errno != EEXIST) {
218 uwsgi_error("uwsgi_set_cgroup()/mkdir()");
219 exit(1);
220 }
221 if (chmod(usl->value, mode)) {
222 uwsgi_error("uwsgi_set_cgroup()/chmod()");
223 exit(1);
224 }
225 uwsgi_log("using Linux cgroup %s with mode %o\n", usl->value, mode);
226 }
227 else {
228 uwsgi_log("created Linux cgroup %s with mode %o\n", usl->value, mode);
229 }
230
231 cgroup_taskfile = uwsgi_concat2(usl->value, "/tasks");
232 cgroup = fopen(cgroup_taskfile, "w");
233 if (!cgroup) {
234 uwsgi_error_open(cgroup_taskfile);
235 exit(1);
236 }
237 if (fprintf(cgroup, "%d\n", (int) getpid()) <= 0 || ferror(cgroup) || fclose(cgroup)) {
238 uwsgi_error("could not set cgroup");
239 exit(1);
240 }
241 uwsgi_log("assigned process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
242 free(cgroup_taskfile);
243
244
245 uslo = uwsgi.cgroup_opt;
246 while (uslo) {
247 cgroup_opt = strchr(uslo->value, '=');
248 if (!cgroup_opt) {
249 cgroup_opt = strchr(uslo->value, ':');
250 if (!cgroup_opt) {
251 uwsgi_log("invalid cgroup-opt syntax\n");
252 exit(1);
253 }
254 }
255
256 cgroup_opt[0] = 0;
257 cgroup_opt++;
258
259 cgroup_taskfile = uwsgi_concat3(usl->value, "/", uslo->value);
260 cgroup = fopen(cgroup_taskfile, "w");
261 if (cgroup) {
262 if (fprintf(cgroup, "%s\n", cgroup_opt) <= 0 || ferror(cgroup) || fclose(cgroup)) {
263 uwsgi_log("could not set cgroup option %s to %s\n", uslo->value, cgroup_opt);
264 exit(1);
265 }
266 uwsgi_log("set %s to %s\n", cgroup_opt, cgroup_taskfile);
267 }
268 free(cgroup_taskfile);
269
270 cgroup_opt[-1] = '=';
271
272 uslo = uslo->next;
273 }
274
275 usl = usl->next;
276 }
277
278 }
279 #endif
280
281 #ifdef UWSGI_CAP
uwsgi_apply_cap(cap_value_t * cap,int caps_count)282 void uwsgi_apply_cap(cap_value_t * cap, int caps_count) {
283 cap_value_t minimal_cap_values[] = { CAP_SYS_CHROOT, CAP_SETUID, CAP_SETGID, CAP_SETPCAP };
284
285 cap_t caps = cap_init();
286
287 if (!caps) {
288 uwsgi_error("cap_init()");
289 exit(1);
290 }
291 cap_clear(caps);
292
293 cap_set_flag(caps, CAP_EFFECTIVE, 4, minimal_cap_values, CAP_SET);
294
295 cap_set_flag(caps, CAP_PERMITTED, 4, minimal_cap_values, CAP_SET);
296 cap_set_flag(caps, CAP_PERMITTED, caps_count, cap, CAP_SET);
297
298 cap_set_flag(caps, CAP_INHERITABLE, caps_count, cap, CAP_SET);
299
300 if (cap_set_proc(caps) < 0) {
301 uwsgi_error("cap_set_proc()");
302 exit(1);
303 }
304 cap_free(caps);
305
306 #ifdef __linux__
307 #ifdef SECBIT_KEEP_CAPS
308 if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
309 uwsgi_error("prctl()");
310 exit(1);
311 }
312 #else
313 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
314 uwsgi_error("prctl()");
315 exit(1);
316 }
317 #endif
318 #endif
319 }
320 #endif
321
322 // drop privileges (as root)
323 /*
324
325 here we manage jails/namespaces too
326 it is a pretty huge function... refactory is needed
327
328 */
uwsgi_as_root()329 void uwsgi_as_root() {
330
331
332 if (getuid() > 0)
333 goto nonroot;
334
335 if (!uwsgi.master_as_root && !uwsgi.uidname) {
336 uwsgi_log_initial("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
337 }
338
339 int in_jail = 0;
340
341 #if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
342 if (uwsgi.unshare && !uwsgi.reloads) {
343
344 if (unshare(uwsgi.unshare)) {
345 uwsgi_error("unshare()");
346 exit(1);
347 }
348 else {
349 uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare);
350 }
351
352 #ifdef CLONE_NEWUSER
353 if (uwsgi.unshare & CLONE_NEWUSER) {
354 if (setuid(0)) {
355 uwsgi_error("uwsgi_as_root()/setuid(0)");
356 exit(1);
357 }
358 }
359 #endif
360 in_jail = 1;
361 }
362 #endif
363
364 #ifdef UWSGI_CAP
365 if (uwsgi.cap && uwsgi.cap_count > 0 && !uwsgi.reloads) {
366 uwsgi_apply_cap(uwsgi.cap, uwsgi.cap_count);
367 }
368 #endif
369
370
371 #if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
372 if (uwsgi.jail && !uwsgi.reloads) {
373
374 struct jail ujail;
375 char *jarg = uwsgi_str(uwsgi.jail);
376 char *j_hostname = NULL;
377 char *j_name = NULL;
378
379 char *space = strchr(jarg, ' ');
380 if (space) {
381 *space = 0;
382 j_hostname = space + 1;
383 space = strchr(j_hostname, ' ');
384 if (space) {
385 *space = 0;
386 j_name = space + 1;
387 }
388 }
389 ujail.version = JAIL_API_VERSION;
390 ujail.path = jarg;
391 ujail.hostname = j_hostname ? j_hostname : "";
392 ujail.jailname = j_name;
393 ujail.ip4s = 0;
394 ujail.ip6s = 0;
395
396 struct uwsgi_string_list *usl = NULL;
397
398 uwsgi_foreach(usl, uwsgi.jail_ip4) {
399 ujail.ip4s++;
400 }
401 struct in_addr *saddr = uwsgi_calloc(sizeof(struct in_addr) * ujail.ip4s);
402 int i = 0;
403 uwsgi_foreach(usl, uwsgi.jail_ip4) {
404 if (!inet_pton(AF_INET, usl->value, &saddr[i].s_addr)) {
405 uwsgi_error("jail()/inet_pton()");
406 exit(1);
407 }
408 i++;
409 }
410 ujail.ip4 = saddr;
411 #ifdef AF_INET6
412 uwsgi_foreach(usl, uwsgi.jail_ip6) {
413 ujail.ip6s++;
414 }
415
416 struct in6_addr *saddr6 = uwsgi_calloc(sizeof(struct in6_addr) * ujail.ip6s);
417 i = 0;
418 uwsgi_foreach(usl, uwsgi.jail_ip6) {
419 if (!inet_pton(AF_INET6, usl->value, &saddr6[i].s6_addr)) {
420 uwsgi_error("jail()/inet_pton()");
421 exit(1);
422 }
423 i++;
424 }
425 ujail.ip6 = saddr6;
426 #endif
427
428 int jail_id = jail(&ujail);
429 if (jail_id < 0) {
430 uwsgi_error("jail()");
431 exit(1);
432 }
433
434 if (uwsgi.jidfile) {
435 if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
436 uwsgi_log("unable to write jidfile\n");
437 exit(1);
438 }
439 }
440
441 uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
442 in_jail = 1;
443 }
444
445 #ifdef UWSGI_HAS_FREEBSD_LIBJAIL
446 if (uwsgi.jail_attach && !uwsgi.reloads) {
447 struct jailparam jparam;
448 uwsgi_log("attaching to FreeBSD jail %s ...\n", uwsgi.jail_attach);
449 if (!is_a_number(uwsgi.jail_attach)) {
450 if (jailparam_init(&jparam, "name")) {
451 uwsgi_error("jailparam_init()");
452 exit(1);
453 }
454 }
455 else {
456 if (jailparam_init(&jparam, "jid")) {
457 uwsgi_error("jailparam_init()");
458 exit(1);
459 }
460 }
461 jailparam_import(&jparam, uwsgi.jail_attach);
462 int jail_id = jailparam_set(&jparam, 1, JAIL_UPDATE | JAIL_ATTACH);
463 if (jail_id < 0) {
464 uwsgi_error("jailparam_set()");
465 exit(1);
466 }
467
468 jailparam_free(&jparam, 1);
469 uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
470 in_jail = 1;
471 }
472
473 if (uwsgi.jail2 && !uwsgi.reloads) {
474 struct uwsgi_string_list *usl = NULL;
475 unsigned nparams = 0;
476 uwsgi_foreach(usl, uwsgi.jail2) {
477 nparams++;
478 }
479 struct jailparam *params = uwsgi_malloc(sizeof(struct jailparam) * nparams);
480 int i = 0;
481 uwsgi_foreach(usl, uwsgi.jail2) {
482 uwsgi_log("FreeBSD libjail applying %s\n", usl->value);
483 char *equal = strchr(usl->value, '=');
484 if (equal) {
485 *equal = 0;
486 }
487 if (jailparam_init(¶ms[i], usl->value)) {
488 uwsgi_error("jailparam_init()");
489 exit(1);
490 }
491 if (equal) {
492 jailparam_import(¶ms[i], equal + 1);
493 *equal = '=';
494 }
495 else {
496 jailparam_import(¶ms[i], "1");
497 }
498 i++;
499 }
500 int jail_id = jailparam_set(params, nparams, JAIL_CREATE | JAIL_ATTACH);
501 if (jail_id < 0) {
502 uwsgi_error("jailparam_set()");
503 exit(1);
504 }
505
506 jailparam_free(params, nparams);
507
508 if (uwsgi.jidfile) {
509 if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
510 uwsgi_log("unable to write jidfile\n");
511 exit(1);
512 }
513 }
514
515 uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
516 in_jail = 1;
517 }
518 #endif
519 #endif
520
521 if (in_jail || uwsgi.jailed) {
522 int i;
523 for (i = 0; i < uwsgi.gp_cnt; i++) {
524 if (uwsgi.gp[i]->early_post_jail) {
525 uwsgi.gp[i]->early_post_jail();
526 }
527 }
528 uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
529 struct uwsgi_string_list *usl = NULL;
530 uwsgi_foreach(usl, uwsgi.mount_post_jail) {
531 uwsgi_log("mounting \"%s\" (post-jail)...\n", usl->value);
532 if (uwsgi_mount_hook(usl->value)) {
533 exit(1);
534 }
535 }
536
537 uwsgi_foreach(usl, uwsgi.umount_post_jail) {
538 uwsgi_log("un-mounting \"%s\" (post-jail)...\n", usl->value);
539 if (uwsgi_umount_hook(usl->value)) {
540 exit(1);
541 }
542 }
543
544 uwsgi_foreach(usl, uwsgi.exec_post_jail) {
545 uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
546 int ret = uwsgi_run_command_and_wait(NULL, usl->value);
547 if (ret != 0) {
548 uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
549 exit(1);
550 }
551 }
552
553 uwsgi_foreach(usl, uwsgi.call_post_jail) {
554 if (uwsgi_call_symbol(usl->value)) {
555 uwsgi_log("unable to call function \"%s\"\n", usl->value);
556 exit(1);
557 }
558 }
559
560 if (uwsgi.refork_post_jail) {
561 uwsgi_log("re-fork()ing...\n");
562 pid_t pid = fork();
563 if (pid < 0) {
564 uwsgi_error("fork()");
565 exit(1);
566 }
567 if (pid > 0) {
568 // block all signals
569 sigset_t smask;
570 sigfillset(&smask);
571 sigprocmask(SIG_BLOCK, &smask, NULL);
572 int status;
573 if (waitpid(pid, &status, 0) < 0) {
574 uwsgi_error("waitpid()");
575 }
576 _exit(0);
577 }
578 }
579
580
581 for (i = 0; i < uwsgi.gp_cnt; i++) {
582 if (uwsgi.gp[i]->post_jail) {
583 uwsgi.gp[i]->post_jail();
584 }
585 }
586 }
587
588 if (uwsgi.chroot && !uwsgi.is_chrooted && !uwsgi.reloads) {
589 if (!uwsgi.master_as_root)
590 uwsgi_log("chroot() to %s\n", uwsgi.chroot);
591
592 if (chroot(uwsgi.chroot)) {
593 uwsgi_error("chroot()");
594 exit(1);
595 }
596 uwsgi.is_chrooted = 1;
597 #ifdef __linux__
598 if (uwsgi.logging_options.memory_report) {
599 uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
600 }
601 #endif
602 }
603
604 #ifdef __linux__
605 if (uwsgi.pivot_root && !uwsgi.reloads) {
606 char *arg = uwsgi_str(uwsgi.pivot_root);
607 char *space = strchr(arg, ' ');
608 if (!space) {
609 uwsgi_log("invalid pivot_root syntax, new_root and put_old must be separated by a space\n");
610 exit(1);
611 }
612 *space = 0;
613 #if defined(MS_REC) && defined(MS_PRIVATE)
614 if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
615 uwsgi_error("mount()");
616 exit(1);
617 }
618 #endif
619 if (chdir(arg)) {
620 uwsgi_error("pivot_root()/chdir()");
621 exit(1);
622 }
623 space += 1 + strlen(arg);
624 if (space[0] == '/')
625 space++;
626 if (pivot_root(".", space)) {
627 uwsgi_error("pivot_root()");
628 exit(1);
629 }
630 if (uwsgi.logging_options.memory_report) {
631 uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
632 }
633 free(arg);
634 if (chdir("/")) {
635 uwsgi_error("chdir()");
636 exit(1);
637 }
638
639 }
640 #endif
641
642 #if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
643 if (uwsgi.unshare2 && !uwsgi.reloads) {
644
645 if (unshare(uwsgi.unshare2)) {
646 uwsgi_error("unshare()");
647 exit(1);
648 }
649 else {
650 uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare2);
651 }
652 #ifdef CLONE_NEWUSER
653 if (uwsgi.unshare2 & CLONE_NEWUSER) {
654 if (setuid(0)) {
655 uwsgi_error("uwsgi_as_root()/setuid(0)");
656 exit(1);
657 }
658 }
659 #endif
660 in_jail = 1;
661 }
662 #endif
663
664 if (uwsgi.refork_as_root) {
665 uwsgi_log("re-fork()ing...\n");
666 pid_t pid = fork();
667 if (pid < 0) {
668 uwsgi_error("fork()");
669 exit(1);
670 }
671 if (pid > 0) {
672 // block all signals
673 sigset_t smask;
674 sigfillset(&smask);
675 sigprocmask(SIG_BLOCK, &smask, NULL);
676 int status;
677 if (waitpid(pid, &status, 0) < 0) {
678 uwsgi_error("waitpid()");
679 }
680 _exit(0);
681 }
682 }
683
684
685 struct uwsgi_string_list *usl;
686 uwsgi_foreach(usl, uwsgi.wait_for_interface) {
687 if (!uwsgi.wait_for_interface_timeout) {
688 uwsgi.wait_for_interface_timeout = 60;
689 }
690 uwsgi_log("waiting for interface %s (max %d seconds) ...\n", usl->value, uwsgi.wait_for_interface_timeout);
691 int counter = 0;
692 for (;;) {
693 if (counter > uwsgi.wait_for_interface_timeout) {
694 uwsgi_log("interface %s unavailable after %d seconds\n", usl->value, counter);
695 exit(1);
696 }
697 unsigned int index = if_nametoindex(usl->value);
698 if (index > 0) {
699 uwsgi_log("interface %s found with index %u\n", usl->value, index);
700 break;
701 }
702 else {
703 sleep(1);
704 counter++;
705 }
706 }
707 }
708
709 uwsgi_foreach(usl, uwsgi.wait_for_fs) {
710 if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
711 }
712
713 uwsgi_foreach(usl, uwsgi.wait_for_file) {
714 if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
715 }
716
717 uwsgi_foreach(usl, uwsgi.wait_for_dir) {
718 if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
719 }
720
721 uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
722 if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
723 }
724
725 uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
726
727 uwsgi_foreach(usl, uwsgi.mount_as_root) {
728 uwsgi_log("mounting \"%s\" (as root)...\n", usl->value);
729 if (uwsgi_mount_hook(usl->value)) {
730 exit(1);
731 }
732 }
733
734 uwsgi_foreach(usl, uwsgi.umount_as_root) {
735 uwsgi_log("un-mounting \"%s\" (as root)...\n", usl->value);
736 if (uwsgi_umount_hook(usl->value)) {
737 exit(1);
738 }
739 }
740
741 // now run the scripts needed by root
742 uwsgi_foreach(usl, uwsgi.exec_as_root) {
743 uwsgi_log("running \"%s\" (as root)...\n", usl->value);
744 int ret = uwsgi_run_command_and_wait(NULL, usl->value);
745 if (ret != 0) {
746 uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
747 exit(1);
748 }
749 }
750
751 uwsgi_foreach(usl, uwsgi.call_as_root) {
752 if (uwsgi_call_symbol(usl->value)) {
753 uwsgi_log("unable to call function \"%s\"\n", usl->value);
754 }
755 }
756
757
758 if (uwsgi.gidname) {
759 struct group *ugroup = getgrnam(uwsgi.gidname);
760 if (ugroup) {
761 uwsgi.gid = ugroup->gr_gid;
762 }
763 else {
764 uwsgi_log("group %s not found.\n", uwsgi.gidname);
765 exit(1);
766 }
767 }
768 if (uwsgi.uidname) {
769 struct passwd *upasswd = getpwnam(uwsgi.uidname);
770 if (upasswd) {
771 uwsgi.uid = upasswd->pw_uid;
772 }
773 else {
774 uwsgi_log("user %s not found.\n", uwsgi.uidname);
775 exit(1);
776 }
777 }
778
779 if (uwsgi.logfile_chown) {
780 int log_fd = 2;
781 if (uwsgi.log_master && uwsgi.original_log_fd > -1) {
782 log_fd = uwsgi.original_log_fd;
783 }
784 if (fchown(log_fd, uwsgi.uid, uwsgi.gid)) {
785 uwsgi_error("fchown()");
786 exit(1);
787 }
788 }
789
790 // fix ipcsem owner
791 if (uwsgi.lock_ops.lock_init == uwsgi_lock_ipcsem_init) {
792 struct uwsgi_lock_item *uli = uwsgi.registered_locks;
793
794 while (uli) {
795 union semun {
796 int val;
797 struct semid_ds *buf;
798 ushort *array;
799 } semu;
800
801 struct semid_ds sds;
802 memset(&sds, 0, sizeof(sds));
803 semu.buf = &sds;
804 int semid = 0;
805 memcpy(&semid, uli->lock_ptr, sizeof(int));
806
807 if (semctl(semid, 0, IPC_STAT, semu)) {
808 uwsgi_error("semctl()");
809 exit(1);
810 }
811
812 semu.buf->sem_perm.uid = uwsgi.uid;
813 semu.buf->sem_perm.gid = uwsgi.gid;
814
815 if (semctl(semid, 0, IPC_SET, semu)) {
816 uwsgi_error("semctl()");
817 exit(1);
818 }
819 uli = uli->next;
820 }
821
822 }
823
824 // ok try to call some special hook before finally dropping privileges
825 int i;
826 for (i = 0; i < uwsgi.gp_cnt; i++) {
827 if (uwsgi.gp[i]->before_privileges_drop) {
828 uwsgi.gp[i]->before_privileges_drop();
829 }
830 }
831
832 if (uwsgi.gid) {
833 if (!uwsgi.master_as_root)
834 uwsgi_log("setgid() to %d\n", uwsgi.gid);
835 if (setgid(uwsgi.gid)) {
836 uwsgi_error("setgid()");
837 exit(1);
838 }
839 if (uwsgi.no_initgroups || !uwsgi.uid) {
840 if (setgroups(0, NULL)) {
841 uwsgi_error("setgroups()");
842 exit(1);
843 }
844 }
845 else {
846 char *uidname = uwsgi.uidname;
847 if (!uidname) {
848 struct passwd *pw = getpwuid(uwsgi.uid);
849 if (pw)
850 uidname = pw->pw_name;
851
852 }
853 if (!uidname)
854 uidname = uwsgi_num2str(uwsgi.uid);
855 if (initgroups(uidname, uwsgi.gid)) {
856 uwsgi_error("setgroups()");
857 exit(1);
858 }
859 }
860 struct uwsgi_string_list *usl;
861 size_t ags = 0;
862 uwsgi_foreach(usl, uwsgi.additional_gids) ags++;
863 if (ags > 0) {
864 gid_t *ags_list = uwsgi_calloc(sizeof(gid_t) * ags);
865 size_t g_pos = 0;
866 uwsgi_foreach(usl, uwsgi.additional_gids) {
867 ags_list[g_pos] = atoi(usl->value);
868 if (!ags_list[g_pos]) {
869 struct group *g = getgrnam(usl->value);
870 if (g) {
871 ags_list[g_pos] = g->gr_gid;
872 }
873 else {
874 uwsgi_log("unable to find group %s\n", usl->value);
875 exit(1);
876 }
877 }
878 g_pos++;
879 }
880 if (setgroups(ags, ags_list)) {
881 uwsgi_error("setgroups()");
882 exit(1);
883 }
884 }
885 int additional_groups = getgroups(0, NULL);
886 if (additional_groups > 0) {
887 gid_t *gids = uwsgi_calloc(sizeof(gid_t) * additional_groups);
888 if (getgroups(additional_groups, gids) > 0) {
889 int i;
890 for (i = 0; i < additional_groups; i++) {
891 if (gids[i] == uwsgi.gid)
892 continue;
893 struct group *gr = getgrgid(gids[i]);
894 if (gr) {
895 uwsgi_log("set additional group %d (%s)\n", gids[i], gr->gr_name);
896 }
897 else {
898 uwsgi_log("set additional group %d\n", gids[i]);
899 }
900 }
901 }
902 }
903 }
904 if (uwsgi.uid) {
905 if (!uwsgi.master_as_root)
906 uwsgi_log("setuid() to %d\n", uwsgi.uid);
907 if (setuid(uwsgi.uid)) {
908 uwsgi_error("setuid()");
909 exit(1);
910 }
911 }
912
913 if (!getuid()) {
914 uwsgi_log_initial("*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n");
915 }
916
917 #ifdef UWSGI_CAP
918
919 if (uwsgi.cap && uwsgi.cap_count > 0 && !uwsgi.reloads) {
920
921 cap_t caps = cap_init();
922
923 if (!caps) {
924 uwsgi_error("cap_init()");
925 exit(1);
926 }
927 cap_clear(caps);
928
929 cap_set_flag(caps, CAP_EFFECTIVE, uwsgi.cap_count, uwsgi.cap, CAP_SET);
930 cap_set_flag(caps, CAP_PERMITTED, uwsgi.cap_count, uwsgi.cap, CAP_SET);
931 cap_set_flag(caps, CAP_INHERITABLE, uwsgi.cap_count, uwsgi.cap, CAP_SET);
932
933 if (cap_set_proc(caps) < 0) {
934 uwsgi_error("cap_set_proc()");
935 exit(1);
936 }
937 cap_free(caps);
938 }
939 #endif
940
941 if (uwsgi.refork) {
942 uwsgi_log("re-fork()ing...\n");
943 pid_t pid = fork();
944 if (pid < 0) {
945 uwsgi_error("fork()");
946 exit(1);
947 }
948 if (pid > 0) {
949 // block all signals
950 sigset_t smask;
951 sigfillset(&smask);
952 sigprocmask(SIG_BLOCK, &smask, NULL);
953 int status;
954 if (waitpid(pid, &status, 0) < 0) {
955 uwsgi_error("waitpid()");
956 }
957 _exit(0);
958 }
959 }
960
961 uwsgi_hooks_run(uwsgi.hook_as_user, "as user", 1);
962
963 // now run the scripts needed by the user
964 uwsgi_foreach(usl, uwsgi.exec_as_user) {
965 uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
966 int ret = uwsgi_run_command_and_wait(NULL, usl->value);
967 if (ret != 0) {
968 uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
969 exit(1);
970 }
971 }
972
973 uwsgi_foreach(usl, uwsgi.call_as_user) {
974 if (uwsgi_call_symbol(usl->value)) {
975 uwsgi_log("unable to call function \"%s\"\n", usl->value);
976 exit(1);
977 }
978 }
979
980 // we could now patch the binary
981 if (uwsgi.unprivileged_binary_patch) {
982 uwsgi.argv[0] = uwsgi.unprivileged_binary_patch;
983 execvp(uwsgi.unprivileged_binary_patch, uwsgi.argv);
984 uwsgi_error("execvp()");
985 exit(1);
986 }
987
988 if (uwsgi.unprivileged_binary_patch_arg) {
989 uwsgi_exec_command_with_args(uwsgi.unprivileged_binary_patch_arg);
990 }
991 return;
992
993 nonroot:
994 if (uwsgi.chroot && !uwsgi.is_chrooted && !uwsgi.is_a_reload) {
995 uwsgi_log("cannot chroot() as non-root user\n");
996 exit(1);
997 }
998 if (uwsgi.gid && getgid() != uwsgi.gid) {
999 uwsgi_log("cannot setgid() as non-root user\n");
1000 exit(1);
1001 }
1002 if (uwsgi.uid && getuid() != uwsgi.uid) {
1003 uwsgi_log("cannot setuid() as non-root user\n");
1004 exit(1);
1005 }
1006 }
1007
close_and_free_request(struct wsgi_request * wsgi_req)1008 static void close_and_free_request(struct wsgi_request *wsgi_req) {
1009
1010 // close the connection with the client
1011 if (!wsgi_req->fd_closed) {
1012 // NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
1013 wsgi_req->socket->proto_close(wsgi_req);
1014 }
1015
1016 if (wsgi_req->post_file) {
1017 fclose(wsgi_req->post_file);
1018 }
1019
1020 if (wsgi_req->post_read_buf) {
1021 free(wsgi_req->post_read_buf);
1022 }
1023
1024 if (wsgi_req->post_readline_buf) {
1025 free(wsgi_req->post_readline_buf);
1026 }
1027
1028 if (wsgi_req->proto_parser_buf) {
1029 free(wsgi_req->proto_parser_buf);
1030 }
1031
1032 }
1033
1034 // destroy a request
uwsgi_destroy_request(struct wsgi_request * wsgi_req)1035 void uwsgi_destroy_request(struct wsgi_request *wsgi_req) {
1036
1037 close_and_free_request(wsgi_req);
1038
1039 int foo;
1040 if (uwsgi.threads > 1) {
1041 // now the thread can die...
1042 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &foo);
1043 }
1044
1045 // reset for avoiding following requests to fail on non-uwsgi protocols
1046 // thanks Marko Tiikkaja for catching it
1047 wsgi_req->uh->pktsize = 0;
1048
1049 // some plugins expected async_id to be defined before setup
1050 int tmp_id = wsgi_req->async_id;
1051 memset(wsgi_req, 0, sizeof(struct wsgi_request));
1052 wsgi_req->async_id = tmp_id;
1053 }
1054
1055 // finalize/close/free a request
uwsgi_close_request(struct wsgi_request * wsgi_req)1056 void uwsgi_close_request(struct wsgi_request *wsgi_req) {
1057
1058 int waitpid_status;
1059 int tmp_id;
1060 uint64_t tmp_rt, rss = 0, vsz = 0;
1061
1062 // apply transformations
1063 if (wsgi_req->transformations) {
1064 if (uwsgi_apply_final_transformations(wsgi_req) == 0) {
1065 if (wsgi_req->transformed_chunk && wsgi_req->transformed_chunk_len > 0) {
1066 uwsgi_response_write_body_do(wsgi_req, wsgi_req->transformed_chunk, wsgi_req->transformed_chunk_len);
1067 }
1068 }
1069 uwsgi_free_transformations(wsgi_req);
1070 }
1071
1072 // check if headers should be sent
1073 if (wsgi_req->headers) {
1074 if (!wsgi_req->headers_sent && !wsgi_req->headers_size && !wsgi_req->response_size) {
1075 uwsgi_response_write_headers_do(wsgi_req);
1076 }
1077 uwsgi_buffer_destroy(wsgi_req->headers);
1078 }
1079
1080 uint64_t end_of_request = uwsgi_micros();
1081 wsgi_req->end_of_request = end_of_request;
1082
1083 if (!wsgi_req->do_not_account_avg_rt) {
1084 tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
1085 uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
1086 uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
1087 }
1088
1089 // get memory usage
1090 if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
1091 get_memusage(&rss, &vsz);
1092 uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
1093 uwsgi.workers[uwsgi.mywid].rss_size = rss;
1094 }
1095
1096 if (!wsgi_req->do_not_account) {
1097 uwsgi.workers[0].requests++;
1098 uwsgi.workers[uwsgi.mywid].requests++;
1099 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
1100 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
1101 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].read_errors += wsgi_req->read_errors;
1102 // this is used for MAX_REQUESTS
1103 uwsgi.workers[uwsgi.mywid].delta_requests++;
1104 }
1105
1106 #ifdef UWSGI_ROUTING
1107 // apply final routes after accounting
1108 uwsgi_apply_final_routes(wsgi_req);
1109 #endif
1110
1111 // close socket and free parsers-allocated memory
1112 close_and_free_request(wsgi_req);
1113
1114 // after_request hook
1115 if (!wsgi_req->is_raw && uwsgi.p[wsgi_req->uh->modifier1]->after_request)
1116 uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req);
1117
1118 // after_request custom hooks
1119 struct uwsgi_string_list *usl = NULL;
1120 uwsgi_foreach(usl, uwsgi.after_request_hooks) {
1121 void (*func) (struct wsgi_request *) = (void (*)(struct wsgi_request *)) usl->custom_ptr;
1122 func(wsgi_req);
1123 }
1124
1125 if (uwsgi.threads > 1) {
1126 // now the thread can die...
1127 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &tmp_id);
1128 }
1129
1130 // leave harakiri mode
1131 if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
1132 set_harakiri(0);
1133 }
1134
1135 // leave user harakiri mode
1136 if (uwsgi.workers[uwsgi.mywid].user_harakiri > 0) {
1137 set_user_harakiri(0);
1138 }
1139
1140 if (!wsgi_req->do_not_account) {
1141 // this is racy in multithread mode
1142 if (wsgi_req->response_size > 0) {
1143 uwsgi.workers[uwsgi.mywid].tx += wsgi_req->response_size;
1144 }
1145 if (wsgi_req->headers_size > 0) {
1146 uwsgi.workers[uwsgi.mywid].tx += wsgi_req->headers_size;
1147 }
1148 }
1149
1150 // defunct process reaper
1151 if (uwsgi.reaper == 1) {
1152 while (waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0);
1153 }
1154
1155 // free logvars
1156 struct uwsgi_logvar *lv = wsgi_req->logvars;
1157 while (lv) {
1158 struct uwsgi_logvar *ptr = lv;
1159 lv = lv->next;
1160 free(ptr);
1161 }
1162
1163 // free additional headers
1164 struct uwsgi_string_list *ah = wsgi_req->additional_headers;
1165 while (ah) {
1166 struct uwsgi_string_list *ptr = ah;
1167 ah = ah->next;
1168 free(ptr->value);
1169 free(ptr);
1170 }
1171 // free remove headers
1172 ah = wsgi_req->remove_headers;
1173 while (ah) {
1174 struct uwsgi_string_list *ptr = ah;
1175 ah = ah->next;
1176 free(ptr->value);
1177 free(ptr);
1178 }
1179
1180 // free chunked input
1181 if (wsgi_req->chunked_input_buf) {
1182 uwsgi_buffer_destroy(wsgi_req->chunked_input_buf);
1183 }
1184
1185 // free websocket engine
1186 if (wsgi_req->websocket_buf) {
1187 uwsgi_buffer_destroy(wsgi_req->websocket_buf);
1188 }
1189 if (wsgi_req->websocket_send_buf) {
1190 uwsgi_buffer_destroy(wsgi_req->websocket_send_buf);
1191 }
1192
1193
1194 // reset request
1195 wsgi_req->uh->pktsize = 0;
1196 tmp_id = wsgi_req->async_id;
1197 memset(wsgi_req, 0, sizeof(struct wsgi_request));
1198 // some plugins expected async_id to be defined before setup
1199 wsgi_req->async_id = tmp_id;
1200 // yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
1201 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
1202
1203 if (uwsgi.max_requests > 0 && uwsgi.workers[uwsgi.mywid].delta_requests >= uwsgi.max_requests
1204 && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
1205 goodbye_cruel_world();
1206 }
1207
1208 if (uwsgi.reload_on_as && (rlim_t) vsz >= uwsgi.reload_on_as && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
1209 goodbye_cruel_world();
1210 }
1211
1212 if (uwsgi.reload_on_rss && (rlim_t) rss >= uwsgi.reload_on_rss && (end_of_request - (uwsgi.workers[uwsgi.mywid].last_spawn * 1000000) >= uwsgi.min_worker_lifetime * 1000000)) {
1213 goodbye_cruel_world();
1214 }
1215
1216
1217 // after the first request, if i am a vassal, signal Emperor about my loyalty
1218 if (uwsgi.has_emperor && !uwsgi.loyal) {
1219 uwsgi_log("announcing my loyalty to the Emperor...\n");
1220 char byte = 17;
1221 if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
1222 uwsgi_error("write()");
1223 }
1224 uwsgi.loyal = 1;
1225 }
1226
1227 #ifdef __linux__
1228 #ifdef MADV_MERGEABLE
1229 // run the ksm mapper
1230 if (uwsgi.linux_ksm > 0 && (uwsgi.workers[uwsgi.mywid].requests % uwsgi.linux_ksm) == 0) {
1231 uwsgi_linux_ksm_map();
1232 }
1233 #endif
1234 #endif
1235
1236 }
1237
1238 #ifdef __linux__
1239 #ifdef MADV_MERGEABLE
1240
uwsgi_linux_ksm_map(void)1241 void uwsgi_linux_ksm_map(void) {
1242
1243 int dirty = 0;
1244 size_t i;
1245 unsigned long long start = 0, end = 0;
1246 int errors = 0;
1247 int lines = 0;
1248
1249 int fd = open("/proc/self/maps", O_RDONLY);
1250 if (fd < 0) {
1251 uwsgi_error_open("[uwsgi-KSM] /proc/self/maps");
1252 return;
1253 }
1254
1255 // allocate memory if not available;
1256 if (uwsgi.ksm_mappings_current == NULL) {
1257 if (!uwsgi.ksm_buffer_size)
1258 uwsgi.ksm_buffer_size = 32768;
1259 uwsgi.ksm_mappings_current = uwsgi_malloc(uwsgi.ksm_buffer_size);
1260 uwsgi.ksm_mappings_current_size = 0;
1261 }
1262 if (uwsgi.ksm_mappings_last == NULL) {
1263 if (!uwsgi.ksm_buffer_size)
1264 uwsgi.ksm_buffer_size = 32768;
1265 uwsgi.ksm_mappings_last = uwsgi_malloc(uwsgi.ksm_buffer_size);
1266 uwsgi.ksm_mappings_last_size = 0;
1267 }
1268
1269 uwsgi.ksm_mappings_current_size = read(fd, uwsgi.ksm_mappings_current, uwsgi.ksm_buffer_size);
1270 close(fd);
1271 if (uwsgi.ksm_mappings_current_size <= 0) {
1272 uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
1273 return;
1274 }
1275
1276 // we now have areas
1277 if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
1278 dirty = 1;
1279 }
1280 else {
1281 if (memcmp(uwsgi.ksm_mappings_current, uwsgi.ksm_mappings_last, uwsgi.ksm_mappings_current_size) != 0) {
1282 dirty = 1;
1283 }
1284 }
1285
1286 // it is dirty, swap addresses and parse it
1287 if (dirty) {
1288 char *tmp = uwsgi.ksm_mappings_last;
1289 uwsgi.ksm_mappings_last = uwsgi.ksm_mappings_current;
1290 uwsgi.ksm_mappings_current = tmp;
1291
1292 size_t tmp_size = uwsgi.ksm_mappings_last_size;
1293 uwsgi.ksm_mappings_last_size = uwsgi.ksm_mappings_current_size;
1294 uwsgi.ksm_mappings_current_size = tmp_size;
1295
1296 // scan each line and call madvise on it
1297 char *ptr = uwsgi.ksm_mappings_last;
1298 for (i = 0; i < uwsgi.ksm_mappings_last_size; i++) {
1299 if (uwsgi.ksm_mappings_last[i] == '\n') {
1300 lines++;
1301 uwsgi.ksm_mappings_last[i] = 0;
1302 if (sscanf(ptr, "%llx-%llx %*s", &start, &end) == 2) {
1303 if (madvise((void *) (long) start, (size_t) (end - start), MADV_MERGEABLE)) {
1304 errors++;
1305 }
1306 }
1307 uwsgi.ksm_mappings_last[i] = '\n';
1308 ptr = uwsgi.ksm_mappings_last + i + 1;
1309 }
1310 }
1311
1312 if (errors >= lines) {
1313 uwsgi_error("[uwsgi-KSM] unable to share pages");
1314 }
1315 }
1316 }
1317 #endif
1318 #endif
1319
1320 #ifdef __linux__
uwsgi_num_from_file(char * filename,int quiet)1321 long uwsgi_num_from_file(char *filename, int quiet) {
1322 char buf[16];
1323 ssize_t len;
1324 int fd = open(filename, O_RDONLY);
1325 if (fd < 0) {
1326 if (!quiet)
1327 uwsgi_error_open(filename);
1328 return -1L;
1329 }
1330 len = read(fd, buf, sizeof(buf));
1331 if (len == 0) {
1332 if (!quiet)
1333 uwsgi_log("read error %s\n", filename);
1334 close(fd);
1335 return -1L;
1336 }
1337 close(fd);
1338 return strtol(buf, (char **) NULL, 10);
1339 }
1340 #endif
1341
1342 // setup for a new request
wsgi_req_setup(struct wsgi_request * wsgi_req,int async_id,struct uwsgi_socket * uwsgi_sock)1343 void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_socket *uwsgi_sock) {
1344
1345 wsgi_req->app_id = -1;
1346
1347 wsgi_req->async_id = async_id;
1348 wsgi_req->sendfile_fd = -1;
1349
1350 wsgi_req->hvec = uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].hvec;
1351 // skip the first 4 bytes;
1352 wsgi_req->uh = (struct uwsgi_header *) uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].buffer;
1353 wsgi_req->buffer = uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].buffer + 4;
1354
1355 if (uwsgi.post_buffering > 0) {
1356 wsgi_req->post_buffering_buf = uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].post_buf;
1357 }
1358
1359 if (uwsgi_sock) {
1360 wsgi_req->socket = uwsgi_sock;
1361 }
1362
1363 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
1364
1365 // now check for suspend request
1366 if (uwsgi.workers[uwsgi.mywid].suspended == 1) {
1367 uwsgi_log_verbose("*** worker %d suspended ***\n", uwsgi.mywid);
1368 cycle:
1369 // wait for some signal (normally SIGTSTP) or 10 seconds (as fallback)
1370 (void) poll(NULL, 0, 10 * 1000);
1371 if (uwsgi.workers[uwsgi.mywid].suspended == 1)
1372 goto cycle;
1373 uwsgi_log_verbose("*** worker %d resumed ***\n", uwsgi.mywid);
1374 }
1375 }
1376
wsgi_req_async_recv(struct wsgi_request * wsgi_req)1377 int wsgi_req_async_recv(struct wsgi_request *wsgi_req) {
1378
1379 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
1380
1381 wsgi_req->start_of_request = uwsgi_micros();
1382 wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request / 1000000;
1383
1384 if (!wsgi_req->do_not_add_to_async_queue) {
1385 if (event_queue_add_fd_read(uwsgi.async_queue, wsgi_req->fd) < 0)
1386 return -1;
1387
1388 async_add_timeout(wsgi_req, uwsgi.socket_timeout);
1389 uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
1390 }
1391
1392 // enter harakiri mode
1393 if (uwsgi.harakiri_options.workers > 0) {
1394 set_harakiri(uwsgi.harakiri_options.workers);
1395 }
1396
1397 return 0;
1398 }
1399
1400 // receive a new request
wsgi_req_recv(int queue,struct wsgi_request * wsgi_req)1401 int wsgi_req_recv(int queue, struct wsgi_request *wsgi_req) {
1402
1403 uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
1404
1405 wsgi_req->start_of_request = uwsgi_micros();
1406 wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request / 1000000;
1407
1408 // edge triggered sockets get the whole request during accept() phase
1409 if (!wsgi_req->socket->edge_trigger) {
1410 for (;;) {
1411 int ret = wsgi_req->socket->proto(wsgi_req);
1412 if (ret == UWSGI_OK)
1413 break;
1414 if (ret == UWSGI_AGAIN) {
1415 ret = uwsgi_wait_read_req(wsgi_req);
1416 if (ret <= 0)
1417 return -1;
1418 continue;
1419 }
1420 return -1;
1421 }
1422 }
1423
1424 // enter harakiri mode
1425 if (uwsgi.harakiri_options.workers > 0) {
1426 set_harakiri(uwsgi.harakiri_options.workers);
1427 }
1428
1429 #ifdef UWSGI_ROUTING
1430 if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK)
1431 return 0;
1432 #endif
1433
1434 wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
1435
1436 return 0;
1437 }
1438
uwsgi_post_accept(struct wsgi_request * wsgi_req)1439 void uwsgi_post_accept(struct wsgi_request *wsgi_req) {
1440
1441 // set close on exec (if not a new socket)
1442 if (!wsgi_req->socket->edge_trigger && uwsgi.close_on_exec) {
1443 if (fcntl(wsgi_req->fd, F_SETFD, FD_CLOEXEC) < 0) {
1444 uwsgi_error("fcntl()");
1445 }
1446 }
1447
1448 // enable TCP_NODELAY ?
1449 if (uwsgi.tcp_nodelay) {
1450 uwsgi_tcp_nodelay(wsgi_req->fd);
1451 }
1452 }
1453
1454 // accept a new request
wsgi_req_simple_accept(struct wsgi_request * wsgi_req,int fd)1455 int wsgi_req_simple_accept(struct wsgi_request *wsgi_req, int fd) {
1456
1457 wsgi_req->fd = wsgi_req->socket->proto_accept(wsgi_req, fd);
1458
1459 if (wsgi_req->fd < 0) {
1460 return -1;
1461 }
1462
1463 uwsgi_post_accept(wsgi_req);
1464
1465 return 0;
1466 }
1467
1468 // send heartbeat to the emperor
uwsgi_heartbeat()1469 void uwsgi_heartbeat() {
1470
1471 if (!uwsgi.has_emperor)
1472 return;
1473
1474 time_t now = uwsgi_now();
1475 if (uwsgi.next_heartbeat <= now) {
1476 char byte = 26;
1477 if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
1478 uwsgi_error("write()");
1479 }
1480 uwsgi.next_heartbeat = now + uwsgi.heartbeat;
1481 }
1482
1483 }
1484
1485 // accept a request
wsgi_req_accept(int queue,struct wsgi_request * wsgi_req)1486 int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
1487
1488 int ret;
1489 int interesting_fd = -1;
1490 struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
1491 int timeout = -1;
1492
1493
1494 thunder_lock;
1495
1496 // Recheck the manage_next_request before going forward.
1497 // This is because the worker might get cheaped while it's
1498 // blocking on the thunder_lock, because thunder_lock is
1499 // not interruptable, it'll slow down the cheaping process
1500 // (the worker will handle the next request before shuts down).
1501 if (!uwsgi.workers[uwsgi.mywid].manage_next_request) {
1502 thunder_unlock;
1503 return -1;
1504 }
1505
1506 // heartbeat
1507 // in multithreaded mode we are now locked
1508 if (uwsgi.has_emperor && uwsgi.heartbeat) {
1509 time_t now = uwsgi_now();
1510 // overengineering ... (reduce skew problems)
1511 timeout = uwsgi.heartbeat;
1512 if (!uwsgi.next_heartbeat) {
1513 uwsgi.next_heartbeat = now;
1514 }
1515 if (uwsgi.next_heartbeat >= now) {
1516 timeout = uwsgi.next_heartbeat - now;
1517 }
1518 }
1519
1520 // need edge trigger ?
1521 if (uwsgi.is_et) {
1522 while (uwsgi_sock) {
1523 if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
1524 timeout = 0;
1525 break;
1526 }
1527 uwsgi_sock = uwsgi_sock->next;
1528 }
1529 // reset pointer
1530 uwsgi_sock = uwsgi.sockets;
1531 }
1532
1533 ret = event_queue_wait(queue, timeout, &interesting_fd);
1534 if (ret < 0) {
1535 thunder_unlock;
1536 return -1;
1537 }
1538
1539 // check for heartbeat
1540 if (uwsgi.has_emperor && uwsgi.heartbeat) {
1541 uwsgi_heartbeat();
1542 // no need to continue if timed-out
1543 if (ret == 0) {
1544 thunder_unlock;
1545 return -1;
1546 }
1547 }
1548
1549 // kill the thread after the request completion
1550 if (uwsgi.threads > 1)
1551 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ret);
1552
1553 if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
1554
1555 thunder_unlock;
1556
1557 uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
1558
1559 if (uwsgi.threads > 1)
1560 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
1561 return -1;
1562 }
1563
1564
1565 while (uwsgi_sock) {
1566 if (interesting_fd == uwsgi_sock->fd || (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) || (uwsgi_sock->fd_threads && interesting_fd == uwsgi_sock->fd_threads[wsgi_req->async_id])) {
1567 wsgi_req->socket = uwsgi_sock;
1568 wsgi_req->fd = wsgi_req->socket->proto_accept(wsgi_req, interesting_fd);
1569 thunder_unlock;
1570 if (wsgi_req->fd < 0) {
1571 if (uwsgi.threads > 1)
1572 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
1573 return -1;
1574 }
1575
1576 if (!uwsgi_sock->edge_trigger) {
1577 uwsgi_post_accept(wsgi_req);
1578 }
1579
1580 return 0;
1581 }
1582
1583 uwsgi_sock = uwsgi_sock->next;
1584 }
1585
1586 thunder_unlock;
1587 if (uwsgi.threads > 1)
1588 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
1589 return -1;
1590 }
1591
1592 // translate a OS env to a uWSGI option
env_to_arg(char * src,char * dst)1593 void env_to_arg(char *src, char *dst) {
1594 int i;
1595 int val = 0;
1596
1597 for (i = 0; i < (int) strlen(src); i++) {
1598 if (src[i] == '=') {
1599 val = 1;
1600 }
1601 if (val) {
1602 dst[i] = src[i];
1603 }
1604 else {
1605 dst[i] = tolower((int) src[i]);
1606 if (dst[i] == '_') {
1607 dst[i] = '-';
1608 }
1609 }
1610 }
1611
1612 dst[strlen(src)] = 0;
1613 }
1614
1615 // parse OS envs
parse_sys_envs(char ** envs)1616 void parse_sys_envs(char **envs) {
1617
1618 char **uenvs = envs;
1619 char *earg, *eq_pos;
1620
1621 while (*uenvs) {
1622 if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=", 14) && strncmp(*uenvs, "UWSGI_VASSALS_DIR=", 18) && strncmp(*uenvs, "UWSGI_EMPEROR_FD=", 17) && strncmp(*uenvs, "UWSGI_BROODLORD_NUM=", 20) && strncmp(*uenvs, "UWSGI_EMPEROR_FD_CONFIG=", 24) && strncmp(*uenvs, "UWSGI_EMPEROR_PROXY=", 20) && strncmp(*uenvs, "UWSGI_JAIL_PID=", 15) && strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
1623 earg = uwsgi_malloc(strlen(*uenvs + 6) + 1);
1624 env_to_arg(*uenvs + 6, earg);
1625 eq_pos = strchr(earg, '=');
1626 if (!eq_pos) {
1627 break;
1628 }
1629 eq_pos[0] = 0;
1630
1631 add_exported_option(earg, eq_pos + 1, 0);
1632 }
1633 uenvs++;
1634 }
1635
1636 }
1637
1638 // get the application id
uwsgi_get_app_id(struct wsgi_request * wsgi_req,char * key,uint16_t key_len,int modifier1)1639 int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, int modifier1) {
1640
1641 int i;
1642 struct stat st;
1643 int found;
1644
1645 char *app_name = key;
1646 uint16_t app_name_len = key_len;
1647
1648 if (app_name_len == 0 && wsgi_req) {
1649 app_name = wsgi_req->appid;
1650 app_name_len = wsgi_req->appid_len;
1651 if (app_name_len == 0) {
1652 if (!uwsgi.ignore_script_name) {
1653 app_name = wsgi_req->script_name;
1654 app_name_len = wsgi_req->script_name_len;
1655 }
1656
1657 if (uwsgi.vhost) {
1658 char *vhost_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|", 1, wsgi_req->script_name, wsgi_req->script_name_len);
1659 app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
1660 app_name = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, vhost_name, app_name_len);
1661 free(vhost_name);
1662 if (!app_name) {
1663 uwsgi_log("unable to add UWSGI_APPID to the uwsgi buffer, consider increasing it\n");
1664 return -1;
1665 }
1666 #ifdef UWSGI_DEBUG
1667 uwsgi_debug("VirtualHost KEY=%.*s\n", app_name_len, app_name);
1668 #endif
1669 }
1670 wsgi_req->appid = app_name;
1671 wsgi_req->appid_len = app_name_len;
1672 }
1673 }
1674
1675
1676 for (i = 0; i < uwsgi_apps_cnt; i++) {
1677 // reset check
1678 found = 0;
1679 #ifdef UWSGI_DEBUG
1680 uwsgi_log("searching for %.*s in %.*s %p\n", app_name_len, app_name, uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint, uwsgi_apps[i].callable);
1681 #endif
1682 if (!uwsgi_apps[i].callable) {
1683 continue;
1684 }
1685
1686 if (!uwsgi_strncmp(uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len, app_name, app_name_len)) {
1687 found = 1;
1688 }
1689
1690 if (found) {
1691 if (uwsgi_apps[i].touch_reload[0]) {
1692 if (!stat(uwsgi_apps[i].touch_reload, &st)) {
1693 if (st.st_mtime != uwsgi_apps[i].touch_reload_mtime) {
1694 // serve the new request and reload
1695 uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
1696 if (uwsgi.threads > 1) {
1697 uwsgi.workers[uwsgi.mywid].destroy = 1;
1698 }
1699
1700 #ifdef UWSGI_DEBUG
1701 uwsgi_log("mtime %d %d\n", st.st_mtime, uwsgi_apps[i].touch_reload_mtime);
1702 #endif
1703 }
1704 }
1705 }
1706 if (modifier1 == -1)
1707 return i;
1708 if (modifier1 == uwsgi_apps[i].modifier1)
1709 return i;
1710 }
1711 }
1712
1713 return -1;
1714 }
1715
uwsgi_substitute(char * src,char * what,char * with)1716 char *uwsgi_substitute(char *src, char *what, char *with) {
1717
1718 int count = 0;
1719 if (!with)
1720 return src;
1721
1722 size_t len = strlen(src);
1723 size_t wlen = strlen(what);
1724 size_t with_len = strlen(with);
1725
1726 char *p = strstr(src, what);
1727 if (!p) {
1728 return src;
1729 }
1730
1731 while (p) {
1732 count++;
1733 p = strstr(p + wlen, what);
1734 }
1735
1736 len += (count * with_len) + 1;
1737
1738 char *dst = uwsgi_calloc(len);
1739 char *ptr = src;
1740 char *dst_ptr = dst;
1741
1742 p = strstr(ptr, what);
1743 while (p) {
1744 memcpy(dst_ptr, ptr, p - ptr);
1745 dst_ptr += p - ptr;
1746 memcpy(dst_ptr, with, with_len);
1747 dst_ptr += with_len;
1748 ptr = p + wlen;
1749 p = strstr(ptr, what);
1750 }
1751
1752 snprintf(dst_ptr, strlen(ptr) + 1, "%s", ptr);
1753
1754 return dst;
1755 }
1756
uwsgi_is_file(char * filename)1757 int uwsgi_is_file(char *filename) {
1758 struct stat st;
1759 if (stat(filename, &st)) {
1760 return 0;
1761 }
1762 if (S_ISREG(st.st_mode))
1763 return 1;
1764 return 0;
1765 }
1766
uwsgi_is_file2(char * filename,struct stat * st)1767 int uwsgi_is_file2(char *filename, struct stat *st) {
1768 if (stat(filename, st)) {
1769 return 0;
1770 }
1771 if (S_ISREG(st->st_mode))
1772 return 1;
1773 return 0;
1774 }
1775
1776
uwsgi_is_dir(char * filename)1777 int uwsgi_is_dir(char *filename) {
1778 struct stat st;
1779 if (stat(filename, &st)) {
1780 return 0;
1781 }
1782 if (S_ISDIR(st.st_mode))
1783 return 1;
1784 return 0;
1785 }
1786
uwsgi_is_link(char * filename)1787 int uwsgi_is_link(char *filename) {
1788 struct stat st;
1789 if (lstat(filename, &st)) {
1790 return 0;
1791 }
1792 if (S_ISLNK(st.st_mode))
1793 return 1;
1794 return 0;
1795 }
1796
uwsgi_malloc(size_t size)1797 void *uwsgi_malloc(size_t size) {
1798
1799 char *ptr = malloc(size);
1800 if (ptr == NULL) {
1801 uwsgi_error("malloc()");
1802 uwsgi_log("!!! tried memory allocation of %llu bytes !!!\n", (unsigned long long) size);
1803 uwsgi_backtrace(uwsgi.backtrace_depth);
1804 exit(1);
1805 }
1806
1807 return ptr;
1808 }
1809
uwsgi_calloc(size_t size)1810 void *uwsgi_calloc(size_t size) {
1811
1812 char *ptr = uwsgi_malloc(size);
1813 memset(ptr, 0, size);
1814 return ptr;
1815 }
1816
1817
uwsgi_resolve_ip(char * domain)1818 char *uwsgi_resolve_ip(char *domain) {
1819
1820 struct hostent *he;
1821
1822 he = gethostbyname(domain);
1823 if (!he || !*he->h_addr_list || (he->h_addrtype != AF_INET
1824 #ifdef AF_INET6
1825 && he->h_addrtype != AF_INET6
1826 #endif
1827 )) {
1828 return NULL;
1829 }
1830
1831 return inet_ntoa(*(struct in_addr *) he->h_addr_list[0]);
1832 }
1833
uwsgi_file_exists(char * filename)1834 int uwsgi_file_exists(char *filename) {
1835 // TODO check for http url or stdin
1836 return !access(filename, R_OK);
1837 }
1838
uwsgi_file_executable(char * filename)1839 int uwsgi_file_executable(char *filename) {
1840 // TODO check for http url or stdin
1841 return !access(filename, R_OK | X_OK);
1842 }
1843
magic_sub(char * buffer,size_t len,size_t * size,char * magic_table[])1844 char *magic_sub(char *buffer, size_t len, size_t * size, char *magic_table[]) {
1845
1846 size_t i;
1847 size_t magic_len = 0;
1848 char *magic_buf = uwsgi_malloc(len);
1849 char *magic_ptr = magic_buf;
1850 char *old_magic_buf;
1851
1852 for (i = 0; i < len; i++) {
1853 if (buffer[i] == '%' && (i + 1) < len && magic_table[(unsigned char) buffer[i + 1]]) {
1854 old_magic_buf = magic_buf;
1855 magic_buf = uwsgi_concat3n(old_magic_buf, magic_len, magic_table[(unsigned char) buffer[i + 1]], strlen(magic_table[(unsigned char) buffer[i + 1]]), buffer + i + 2, len - i);
1856 free(old_magic_buf);
1857 magic_len += strlen(magic_table[(unsigned char) buffer[i + 1]]);
1858 magic_ptr = magic_buf + magic_len;
1859 i++;
1860 }
1861 else {
1862 *magic_ptr = buffer[i];
1863 magic_ptr++;
1864 magic_len++;
1865 }
1866 }
1867
1868 *size = magic_len;
1869
1870 return magic_buf;
1871
1872 }
1873
init_magic_table(char * magic_table[])1874 void init_magic_table(char *magic_table[]) {
1875
1876 int i;
1877 for (i = 0; i <= 0xff; i++) {
1878 magic_table[i] = "";
1879 }
1880
1881 magic_table['%'] = "%";
1882 magic_table['('] = "%(";
1883 }
1884
uwsgi_get_last_char(char * what,char c)1885 char *uwsgi_get_last_char(char *what, char c) {
1886 size_t len = strlen(what);
1887 while (len--) {
1888 if (what[len] == c)
1889 return what + len;
1890 }
1891 return NULL;
1892 }
1893
uwsgi_get_last_charn(char * what,size_t len,char c)1894 char *uwsgi_get_last_charn(char *what, size_t len, char c) {
1895 while (len--) {
1896 if (what[len] == c)
1897 return what + len;
1898 }
1899 return NULL;
1900 }
1901
1902
uwsgi_num2str(int num)1903 char *uwsgi_num2str(int num) {
1904
1905 char *str = uwsgi_malloc(11);
1906
1907 snprintf(str, 11, "%d", num);
1908 return str;
1909 }
1910
uwsgi_float2str(float num)1911 char *uwsgi_float2str(float num) {
1912
1913 char *str = uwsgi_malloc(11);
1914
1915 snprintf(str, 11, "%f", num);
1916 return str;
1917 }
1918
uwsgi_64bit2str(int64_t num)1919 char *uwsgi_64bit2str(int64_t num) {
1920 char *str = uwsgi_malloc(sizeof(MAX64_STR) + 1);
1921 snprintf(str, sizeof(MAX64_STR) + 1, "%lld", (long long) num);
1922 return str;
1923 }
1924
uwsgi_size2str(size_t num)1925 char *uwsgi_size2str(size_t num) {
1926 char *str = uwsgi_malloc(sizeof(UMAX64_STR) + 1);
1927 snprintf(str, sizeof(UMAX64_STR) + 1, "%llu", (unsigned long long) num);
1928 return str;
1929 }
1930
uwsgi_num2str2(int num,char * ptr)1931 int uwsgi_num2str2(int num, char *ptr) {
1932
1933 return snprintf(ptr, 11, "%d", num);
1934 }
1935
uwsgi_num2str2n(int num,char * ptr,int size)1936 int uwsgi_num2str2n(int num, char *ptr, int size) {
1937 return snprintf(ptr, size, "%d", num);
1938 }
1939
uwsgi_long2str2n(unsigned long long num,char * ptr,int size)1940 int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
1941 int ret = snprintf(ptr, size, "%llu", num);
1942 if (ret <= 0 || ret > size)
1943 return 0;
1944 return ret;
1945 }
1946
is_unix(char * socket_name,int len)1947 int is_unix(char *socket_name, int len) {
1948 int i;
1949 for (i = 0; i < len; i++) {
1950 if (socket_name[i] == ':')
1951 return 0;
1952 }
1953
1954 return 1;
1955 }
1956
is_a_number(char * what)1957 int is_a_number(char *what) {
1958 int i;
1959
1960 for (i = 0; i < (int) strlen(what); i++) {
1961 if (!isdigit((int) what[i]))
1962 return 0;
1963 }
1964
1965 return 1;
1966 }
1967
uwsgi_unix_signal(int signum,void (* func)(int))1968 void uwsgi_unix_signal(int signum, void (*func) (int)) {
1969
1970 struct sigaction sa;
1971
1972 memset(&sa, 0, sizeof(struct sigaction));
1973
1974 sa.sa_handler = func;
1975
1976 sigemptyset(&sa.sa_mask);
1977
1978 if (sigaction(signum, &sa, NULL) < 0) {
1979 uwsgi_error("sigaction()");
1980 }
1981 }
1982
uwsgi_list_has_num(char * list,int num)1983 int uwsgi_list_has_num(char *list, int num) {
1984
1985 char *list2 = uwsgi_concat2(list, "");
1986 char *p, *ctx = NULL;
1987 uwsgi_foreach_token(list2, ",", p, ctx) {
1988 if (atoi(p) == num) {
1989 free(list2);
1990 return 1;
1991 }
1992 }
1993
1994 free(list2);
1995 return 0;
1996 }
1997
uwsgi_list_has_str(char * list,char * str)1998 int uwsgi_list_has_str(char *list, char *str) {
1999
2000 char *list2 = uwsgi_str(list);
2001 char *p, *ctx = NULL;
2002 uwsgi_foreach_token(list2, " ", p, ctx) {
2003 if (!strcasecmp(p, str)) {
2004 free(list2);
2005 return 1;
2006 }
2007 }
2008
2009 free(list2);
2010 return 0;
2011 }
2012
hex2num(char * str)2013 static char hex2num(char *str) {
2014
2015 char val = 0;
2016
2017 val <<= 4;
2018
2019 if (str[0] >= '0' && str[0] <= '9') {
2020 val += str[0] & 0x0F;
2021 }
2022 else if (str[0] >= 'A' && str[0] <= 'F') {
2023 val += (str[0] & 0x0F) + 9;
2024 }
2025 else if (str[0] >= 'a' && str[0] <= 'f') {
2026 val += (str[0] & 0x0F) + 9;
2027 }
2028 else {
2029 return 0;
2030 }
2031
2032 val <<= 4;
2033
2034 if (str[1] >= '0' && str[1] <= '9') {
2035 val += str[1] & 0x0F;
2036 }
2037 else if (str[1] >= 'A' && str[1] <= 'F') {
2038 val += (str[1] & 0x0F) + 9;
2039 }
2040 else if (str[1] >= 'a' && str[1] <= 'f') {
2041 val += (str[1] & 0x0F) + 9;
2042 }
2043 else {
2044 return 0;
2045 }
2046
2047 return val;
2048 }
2049
uwsgi_str2_num(char * str)2050 int uwsgi_str2_num(char *str) {
2051
2052 int num = 0;
2053
2054 num = 10 * (str[0] - 48);
2055 num += str[1] - 48;
2056
2057 return num;
2058 }
2059
uwsgi_str3_num(char * str)2060 int uwsgi_str3_num(char *str) {
2061
2062 int num = 0;
2063
2064 num = 100 * (str[0] - 48);
2065 num += 10 * (str[1] - 48);
2066 num += str[2] - 48;
2067
2068 return num;
2069 }
2070
2071
uwsgi_str4_num(char * str)2072 int uwsgi_str4_num(char *str) {
2073
2074 int num = 0;
2075
2076 num = 1000 * (str[0] - 48);
2077 num += 100 * (str[1] - 48);
2078 num += 10 * (str[2] - 48);
2079 num += str[3] - 48;
2080
2081 return num;
2082 }
2083
uwsgi_str_num(char * str,int len)2084 uint64_t uwsgi_str_num(char *str, int len) {
2085
2086 int i;
2087 uint64_t num = 0;
2088
2089 uint64_t delta = pow(10, len);
2090
2091 for (i = 0; i < len; i++) {
2092 delta = delta / 10;
2093 num += delta * (str[i] - 48);
2094 }
2095
2096 return num;
2097 }
2098
uwsgi_split3(char * buf,size_t len,char sep,char ** part1,size_t * part1_len,char ** part2,size_t * part2_len,char ** part3,size_t * part3_len)2099 char *uwsgi_split3(char *buf, size_t len, char sep, char **part1, size_t * part1_len, char **part2, size_t * part2_len, char **part3, size_t * part3_len) {
2100
2101 size_t i;
2102 int status = 0;
2103
2104 *part1 = NULL;
2105 *part2 = NULL;
2106 *part3 = NULL;
2107
2108 for (i = 0; i < len; i++) {
2109 if (buf[i] == sep) {
2110 // get part1
2111 if (status == 0) {
2112 *part1 = buf;
2113 *part1_len = i;
2114 status = 1;
2115 }
2116 // get part2
2117 else if (status == 1) {
2118 *part2 = *part1 + *part1_len + 1;
2119 *part2_len = (buf + i) - *part2;
2120 break;
2121 }
2122 }
2123 }
2124
2125 if (*part1 && *part2) {
2126 if (*part2 + *part2_len + 1 > buf + len) {
2127 return NULL;
2128 }
2129 *part3 = *part2 + *part2_len + 1;
2130 *part3_len = (buf + len) - *part3;
2131 return buf + len;
2132 }
2133
2134 return NULL;
2135 }
2136
uwsgi_split4(char * buf,size_t len,char sep,char ** part1,size_t * part1_len,char ** part2,size_t * part2_len,char ** part3,size_t * part3_len,char ** part4,size_t * part4_len)2137 char *uwsgi_split4(char *buf, size_t len, char sep, char **part1, size_t * part1_len, char **part2, size_t * part2_len, char **part3, size_t * part3_len, char **part4, size_t * part4_len) {
2138
2139 size_t i;
2140 int status = 0;
2141
2142 *part1 = NULL;
2143 *part2 = NULL;
2144 *part3 = NULL;
2145 *part4 = NULL;
2146
2147 for (i = 0; i < len; i++) {
2148 if (buf[i] == sep) {
2149 // get part1
2150 if (status == 0) {
2151 *part1 = buf;
2152 *part1_len = i;
2153 status = 1;
2154 }
2155 // get part2
2156 else if (status == 1) {
2157 *part2 = *part1 + *part1_len + 1;
2158 *part2_len = (buf + i) - *part2;
2159 status = 2;
2160 }
2161 // get part3
2162 else if (status == 2) {
2163 *part3 = *part2 + *part2_len + 1;
2164 *part3_len = (buf + i) - *part3;
2165 break;
2166 }
2167 }
2168 }
2169
2170 if (*part1 && *part2 && *part3) {
2171 if (*part3 + *part3_len + 1 > buf + len) {
2172 return NULL;
2173 }
2174 *part4 = *part3 + *part3_len + 1;
2175 *part4_len = (buf + len) - *part4;
2176 return buf + len;
2177 }
2178
2179 return NULL;
2180 }
2181
2182
uwsgi_netstring(char * buf,size_t len,char ** netstring,size_t * netstring_len)2183 char *uwsgi_netstring(char *buf, size_t len, char **netstring, size_t * netstring_len) {
2184
2185 char *ptr = buf;
2186 char *watermark = buf + len;
2187 *netstring_len = 0;
2188
2189 while (ptr < watermark) {
2190 // end of string size ?
2191 if (*ptr == ':') {
2192 *netstring_len = uwsgi_str_num(buf, ptr - buf);
2193
2194 if (ptr + *netstring_len + 2 > watermark) {
2195 return NULL;
2196 }
2197 *netstring = ptr + 1;
2198 return ptr + *netstring_len + 2;
2199 }
2200 ptr++;
2201 }
2202
2203 return NULL;
2204 }
2205
uwsgi_dyn_dict_new(struct uwsgi_dyn_dict ** dd,char * key,int keylen,char * val,int vallen)2206 struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **dd, char *key, int keylen, char *val, int vallen) {
2207
2208 struct uwsgi_dyn_dict *uwsgi_dd = *dd, *old_dd;
2209
2210 if (!uwsgi_dd) {
2211 *dd = uwsgi_malloc(sizeof(struct uwsgi_dyn_dict));
2212 uwsgi_dd = *dd;
2213 uwsgi_dd->prev = NULL;
2214 }
2215 else {
2216 while (uwsgi_dd) {
2217 old_dd = uwsgi_dd;
2218 uwsgi_dd = uwsgi_dd->next;
2219 }
2220
2221 uwsgi_dd = uwsgi_malloc(sizeof(struct uwsgi_dyn_dict));
2222 old_dd->next = uwsgi_dd;
2223 uwsgi_dd->prev = old_dd;
2224 }
2225
2226 uwsgi_dd->key = key;
2227 uwsgi_dd->keylen = keylen;
2228 uwsgi_dd->value = val;
2229 uwsgi_dd->vallen = vallen;
2230 uwsgi_dd->hits = 0;
2231 uwsgi_dd->status = 0;
2232 uwsgi_dd->next = NULL;
2233
2234 return uwsgi_dd;
2235 }
2236
uwsgi_dyn_dict_del(struct uwsgi_dyn_dict * item)2237 void uwsgi_dyn_dict_del(struct uwsgi_dyn_dict *item) {
2238
2239 struct uwsgi_dyn_dict *prev = item->prev;
2240 struct uwsgi_dyn_dict *next = item->next;
2241
2242 if (prev) {
2243 prev->next = next;
2244 }
2245
2246 if (next) {
2247 next->prev = prev;
2248 }
2249
2250 free(item);
2251 }
2252
uwsgi_malloc_shared(size_t size)2253 void *uwsgi_malloc_shared(size_t size) {
2254
2255 void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
2256
2257 if (addr == MAP_FAILED) {
2258 uwsgi_log("unable to allocate %llu bytes (%lluMB)\n", (unsigned long long) size, (unsigned long long) (size / (1024 * 1024)));
2259 uwsgi_error("mmap()");
2260 exit(1);
2261 }
2262
2263 return addr;
2264 }
2265
uwsgi_calloc_shared(size_t size)2266 void *uwsgi_calloc_shared(size_t size) {
2267 void *ptr = uwsgi_malloc_shared(size);
2268 memset(ptr, 0, size);
2269 return ptr;
2270 }
2271
2272
uwsgi_string_new_list(struct uwsgi_string_list ** list,char * value)2273 struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list, char *value) {
2274
2275 struct uwsgi_string_list *uwsgi_string = *list, *old_uwsgi_string;
2276
2277 if (!uwsgi_string) {
2278 *list = uwsgi_malloc(sizeof(struct uwsgi_string_list));
2279 uwsgi_string = *list;
2280 }
2281 else {
2282 while (uwsgi_string) {
2283 old_uwsgi_string = uwsgi_string;
2284 uwsgi_string = uwsgi_string->next;
2285 }
2286
2287 uwsgi_string = uwsgi_malloc(sizeof(struct uwsgi_string_list));
2288 old_uwsgi_string->next = uwsgi_string;
2289 }
2290
2291 uwsgi_string->value = value;
2292 uwsgi_string->len = 0;
2293 if (value) {
2294 uwsgi_string->len = strlen(value);
2295 }
2296 uwsgi_string->next = NULL;
2297 uwsgi_string->custom = 0;
2298 uwsgi_string->custom2 = 0;
2299 uwsgi_string->custom_ptr = NULL;
2300
2301 return uwsgi_string;
2302 }
2303
2304 #ifdef UWSGI_PCRE
uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list ** list,char * value,char * custom)2305 struct uwsgi_regexp_list *uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list **list, char *value, char *custom) {
2306
2307 struct uwsgi_regexp_list *url = *list, *old_url;
2308
2309 if (!url) {
2310 *list = uwsgi_malloc(sizeof(struct uwsgi_regexp_list));
2311 url = *list;
2312 }
2313 else {
2314 while (url) {
2315 old_url = url;
2316 url = url->next;
2317 }
2318
2319 url = uwsgi_malloc(sizeof(struct uwsgi_regexp_list));
2320 old_url->next = url;
2321 }
2322
2323 if (uwsgi_regexp_build(value, &url->pattern, &url->pattern_extra)) {
2324 exit(1);
2325 }
2326 url->next = NULL;
2327 url->custom = 0;
2328 url->custom_ptr = NULL;
2329 url->custom_str = custom;
2330
2331 return url;
2332 }
2333
uwsgi_regexp_match_pattern(char * pattern,char * str)2334 int uwsgi_regexp_match_pattern(char *pattern, char *str) {
2335
2336 pcre *regexp;
2337 pcre_extra *regexp_extra;
2338
2339 if (uwsgi_regexp_build(pattern, ®exp, ®exp_extra))
2340 return 1;
2341 return !uwsgi_regexp_match(regexp, regexp_extra, str, strlen(str));
2342 }
2343
2344
2345 #endif
2346
uwsgi_string_get_list(struct uwsgi_string_list ** list,int pos,size_t * len)2347 char *uwsgi_string_get_list(struct uwsgi_string_list **list, int pos, size_t * len) {
2348
2349 struct uwsgi_string_list *uwsgi_string = *list;
2350 int counter = 0;
2351
2352 while (uwsgi_string) {
2353 if (counter == pos) {
2354 *len = uwsgi_string->len;
2355 return uwsgi_string->value;
2356 }
2357 uwsgi_string = uwsgi_string->next;
2358 counter++;
2359 }
2360
2361 *len = 0;
2362 return NULL;
2363
2364 }
2365
2366
uwsgi_string_del_list(struct uwsgi_string_list ** list,struct uwsgi_string_list * item)2367 void uwsgi_string_del_list(struct uwsgi_string_list **list, struct uwsgi_string_list *item) {
2368
2369 struct uwsgi_string_list *uwsgi_string = *list, *old_uwsgi_string = NULL;
2370
2371 while (uwsgi_string) {
2372 if (uwsgi_string == item) {
2373 // parent instance ?
2374 if (old_uwsgi_string == NULL) {
2375 *list = uwsgi_string->next;
2376 }
2377 else {
2378 old_uwsgi_string->next = uwsgi_string->next;
2379 }
2380
2381 free(uwsgi_string);
2382 return;
2383 }
2384
2385 old_uwsgi_string = uwsgi_string;
2386 uwsgi_string = uwsgi_string->next;
2387 }
2388
2389 }
2390
uwsgi_sig_pause()2391 void uwsgi_sig_pause() {
2392
2393 sigset_t mask;
2394 sigemptyset(&mask);
2395 sigsuspend(&mask);
2396 }
2397
uwsgi_binsh()2398 char *uwsgi_binsh() {
2399 struct uwsgi_string_list *usl = NULL;
2400 uwsgi_foreach(usl, uwsgi.binsh) {
2401 if (uwsgi_file_executable(usl->value)) {
2402 return usl->value;
2403 }
2404 }
2405 return "/bin/sh";
2406 }
2407
uwsgi_exec_command_with_args(char * cmdline)2408 void uwsgi_exec_command_with_args(char *cmdline) {
2409 char *argv[4];
2410 argv[0] = uwsgi_binsh();
2411 argv[1] = "-c";
2412 argv[2] = cmdline;
2413 argv[3] = NULL;
2414 execvp(argv[0], argv);
2415 uwsgi_error("execvp()");
2416 exit(1);
2417 }
2418
uwsgi_run_command_do(char * command,char * arg)2419 static int uwsgi_run_command_do(char *command, char *arg) {
2420
2421 char *argv[4];
2422
2423 #ifdef __linux__
2424 if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
2425 uwsgi_error("prctl()");
2426 }
2427 #endif
2428
2429 if (command == NULL) {
2430 argv[0] = uwsgi_binsh();
2431 argv[1] = "-c";
2432 argv[2] = arg;
2433 argv[3] = NULL;
2434 execvp(argv[0], argv);
2435 }
2436 else {
2437 argv[0] = command;
2438 argv[1] = arg;
2439 argv[2] = NULL;
2440 execvp(command, argv);
2441 }
2442
2443
2444 uwsgi_error("execvp()");
2445 //never here
2446 exit(1);
2447 }
2448
uwsgi_run_command_and_wait(char * command,char * arg)2449 int uwsgi_run_command_and_wait(char *command, char *arg) {
2450
2451 int waitpid_status = 0;
2452 pid_t pid = fork();
2453 if (pid < 0) {
2454 return -1;
2455 }
2456
2457 if (pid > 0) {
2458 if (waitpid(pid, &waitpid_status, 0) < 0) {
2459 uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
2460 return -1;
2461 }
2462
2463 return WEXITSTATUS(waitpid_status);
2464 }
2465 return uwsgi_run_command_do(command, arg);
2466 }
2467
uwsgi_run_command_putenv_and_wait(char * command,char * arg,char ** envs,unsigned int nenvs)2468 int uwsgi_run_command_putenv_and_wait(char *command, char *arg, char **envs, unsigned int nenvs) {
2469
2470 int waitpid_status = 0;
2471 pid_t pid = fork();
2472 if (pid < 0) {
2473 return -1;
2474 }
2475
2476 if (pid > 0) {
2477 if (waitpid(pid, &waitpid_status, 0) < 0) {
2478 uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
2479 return -1;
2480 }
2481
2482 return WEXITSTATUS(waitpid_status);
2483 }
2484
2485 unsigned int i;
2486 for (i = 0; i < nenvs; i++) {
2487 if (putenv(envs[i])) {
2488 uwsgi_error("uwsgi_run_command_putenv_and_wait()/putenv()");
2489 exit(1);
2490 }
2491 }
2492
2493 return uwsgi_run_command_do(command, arg);
2494 }
2495
2496
uwsgi_run_command(char * command,int * stdin_fd,int stdout_fd)2497 pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
2498
2499 char *argv[4];
2500
2501 int waitpid_status = 0;
2502 pid_t pid = fork();
2503 if (pid < 0) {
2504 return -1;
2505 }
2506
2507 if (pid > 0) {
2508 if (stdin_fd && stdin_fd[0] > -1) {
2509 close(stdin_fd[0]);
2510 }
2511 if (stdout_fd > -1) {
2512 close(stdout_fd);
2513 }
2514 if (waitpid(pid, &waitpid_status, WNOHANG) < 0) {
2515 uwsgi_error("waitpid()");
2516 return -1;
2517 }
2518
2519 return pid;
2520 }
2521
2522 uwsgi_close_all_sockets();
2523 //uwsgi_close_all_fds();
2524 int i;
2525 for (i = 3; i < (int) uwsgi.max_fd; i++) {
2526 if (stdin_fd) {
2527 if (i == stdin_fd[0] || i == stdin_fd[1]) {
2528 continue;
2529 }
2530 }
2531 if (stdout_fd > -1) {
2532 if (i == stdout_fd) {
2533 continue;
2534 }
2535 }
2536 #ifdef __APPLE__
2537 fcntl(i, F_SETFD, FD_CLOEXEC);
2538 #else
2539 close(i);
2540 #endif
2541 }
2542
2543
2544
2545 if (stdin_fd) {
2546 close(stdin_fd[1]);
2547 }
2548 else {
2549 if (!uwsgi_valid_fd(0)) {
2550 int in_fd = open("/dev/null", O_RDONLY);
2551 if (in_fd < 0) {
2552 uwsgi_error_open("/dev/null");
2553 }
2554 else {
2555 if (in_fd != 0) {
2556 if (dup2(in_fd, 0) < 0) {
2557 uwsgi_error("dup2()");
2558 }
2559 }
2560 }
2561 }
2562 }
2563
2564 if (stdout_fd > -1 && stdout_fd != 1) {
2565 if (dup2(stdout_fd, 1) < 0) {
2566 uwsgi_error("dup2()");
2567 exit(1);
2568 }
2569 }
2570
2571 if (stdin_fd && stdin_fd[0] > -1 && stdin_fd[0] != 0) {
2572 if (dup2(stdin_fd[0], 0) < 0) {
2573 uwsgi_error("dup2()");
2574 exit(1);
2575 }
2576 }
2577
2578 if (setsid() < 0) {
2579 uwsgi_error("setsid()");
2580 exit(1);
2581 }
2582
2583 argv[0] = uwsgi_binsh();
2584 argv[1] = "-c";
2585 argv[2] = command;
2586 argv[3] = NULL;
2587
2588 execvp(uwsgi_binsh(), argv);
2589
2590 uwsgi_error("execvp()");
2591 //never here
2592 exit(1);
2593 }
2594
uwsgi_endswith(char * str1,char * str2)2595 int uwsgi_endswith(char *str1, char *str2) {
2596
2597 size_t i;
2598 size_t str1len = strlen(str1);
2599 size_t str2len = strlen(str2);
2600 char *ptr;
2601
2602 if (str2len > str1len)
2603 return 0;
2604
2605 ptr = (str1 + str1len) - str2len;
2606
2607 for (i = 0; i < str2len; i++) {
2608 if (*ptr != str2[i])
2609 return 0;
2610 ptr++;
2611 }
2612
2613 return 1;
2614 }
2615
uwsgi_chown(char * filename,char * owner)2616 void uwsgi_chown(char *filename, char *owner) {
2617
2618 uid_t new_uid = -1;
2619 uid_t new_gid = -1;
2620 struct group *new_group = NULL;
2621 struct passwd *new_user = NULL;
2622
2623 char *colon = strchr(owner, ':');
2624 if (colon) {
2625 colon[0] = 0;
2626 }
2627
2628
2629 if (is_a_number(owner)) {
2630 new_uid = atoi(owner);
2631 }
2632 else {
2633 new_user = getpwnam(owner);
2634 if (!new_user) {
2635 uwsgi_log("unable to find user %s\n", owner);
2636 exit(1);
2637 }
2638 new_uid = new_user->pw_uid;
2639 }
2640
2641 if (colon) {
2642 colon[0] = ':';
2643 if (is_a_number(colon + 1)) {
2644 new_gid = atoi(colon + 1);
2645 }
2646 else {
2647 new_group = getgrnam(colon + 1);
2648 if (!new_group) {
2649 uwsgi_log("unable to find group %s\n", colon + 1);
2650 exit(1);
2651 }
2652 new_gid = new_group->gr_gid;
2653 }
2654 }
2655
2656 if (chown(filename, new_uid, new_gid)) {
2657 uwsgi_error("chown()");
2658 exit(1);
2659 }
2660
2661 }
2662
uwsgi_get_binary_path(char * argvzero)2663 char *uwsgi_get_binary_path(char *argvzero) {
2664
2665 #if defined(__linux__) || defined(__CYGWIN__)
2666 char *buf = uwsgi_calloc(PATH_MAX + 1);
2667 ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
2668 if (len > 0) {
2669 return buf;
2670 }
2671 free(buf);
2672 #elif defined(_WIN32)
2673 char *buf = uwsgi_calloc(PATH_MAX + 1);
2674 if (GetModuleFileName(NULL, buf, PATH_MAX) > 0) {
2675 return buf;
2676 }
2677 free(buf);
2678 #elif defined(__NetBSD__)
2679 char *buf = uwsgi_calloc(PATH_MAX + 1);
2680 ssize_t len = readlink("/proc/curproc/exe", buf, PATH_MAX);
2681 if (len > 0) {
2682 return buf;
2683 }
2684
2685 if (realpath(argvzero, buf)) {
2686 return buf;
2687 }
2688 free(buf);
2689 #elif defined(__APPLE__)
2690 char *buf = uwsgi_malloc(uwsgi.page_size);
2691 uint32_t len = uwsgi.page_size;
2692 if (_NSGetExecutablePath(buf, &len) == 0) {
2693 // return only absolute path
2694 #ifndef OLD_REALPATH
2695 char *newbuf = realpath(buf, NULL);
2696 if (newbuf) {
2697 free(buf);
2698 return newbuf;
2699 }
2700 #endif
2701 }
2702 free(buf);
2703 #elif defined(__sun__)
2704 // do not free this value !!!
2705 char *buf = (char *) getexecname();
2706 if (buf) {
2707 // return only absolute path
2708 if (buf[0] == '/') {
2709 return buf;
2710 }
2711
2712 char *newbuf = uwsgi_malloc(PATH_MAX + 1);
2713 if (realpath(buf, newbuf)) {
2714 return newbuf;
2715 }
2716 }
2717 #elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
2718 char *buf = uwsgi_malloc(uwsgi.page_size);
2719 size_t len = uwsgi.page_size;
2720 int mib[4];
2721 mib[0] = CTL_KERN;
2722 mib[1] = KERN_PROC;
2723 mib[2] = KERN_PROC_PATHNAME;
2724 mib[3] = -1;
2725 if (sysctl(mib, 4, buf, &len, NULL, 0) == 0) {
2726 return buf;
2727 }
2728 free(buf);
2729 #endif
2730
2731
2732 return argvzero;
2733
2734 }
2735
uwsgi_get_line(char * ptr,char * watermark,int * size)2736 char *uwsgi_get_line(char *ptr, char *watermark, int *size) {
2737 char *p = ptr;
2738 int count = 0;
2739
2740 while (p < watermark) {
2741 if (*p == '\n') {
2742 *size = count;
2743 return ptr + count;
2744 }
2745 count++;
2746 p++;
2747 }
2748
2749 return NULL;
2750 }
2751
uwsgi_build_mime_dict(char * filename)2752 void uwsgi_build_mime_dict(char *filename) {
2753
2754 size_t size = 0;
2755 char *buf = uwsgi_open_and_read(filename, &size, 1, NULL);
2756 char *watermark = buf + size;
2757
2758 int linesize = 0;
2759 char *line = buf;
2760 int i;
2761 int type_size = 0;
2762 int ext_start = 0;
2763 int found;
2764 int entries = 0;
2765
2766 uwsgi_log("building mime-types dictionary from file %s...", filename);
2767
2768 while (uwsgi_get_line(line, watermark, &linesize) != NULL) {
2769 found = 0;
2770 if (isalnum((int) line[0])) {
2771 // get the type size
2772 for (i = 0; i < linesize; i++) {
2773 if (isblank((int) line[i])) {
2774 type_size = i;
2775 found = 1;
2776 break;
2777 }
2778 }
2779 if (!found) {
2780 line += linesize + 1;
2781 continue;
2782 }
2783 found = 0;
2784 for (i = type_size; i < linesize; i++) {
2785 if (!isblank((int) line[i])) {
2786 ext_start = i;
2787 found = 1;
2788 break;
2789 }
2790 }
2791 if (!found) {
2792 line += linesize + 1;
2793 continue;
2794 }
2795
2796 char *current = line + ext_start;
2797 int ext_size = 0;
2798 for (i = ext_start; i < linesize; i++) {
2799 if (isblank((int) line[i])) {
2800 #ifdef UWSGI_DEBUG
2801 uwsgi_log("%.*s %.*s\n", ext_size, current, type_size, line);
2802 #endif
2803 uwsgi_dyn_dict_new(&uwsgi.mimetypes, current, ext_size, line, type_size);
2804 entries++;
2805 ext_size = 0;
2806 current = NULL;
2807 continue;
2808 }
2809 else if (current == NULL) {
2810 current = line + i;
2811 }
2812 ext_size++;
2813 }
2814 if (current && ext_size > 1) {
2815 #ifdef UWSGI_DEBUG
2816 uwsgi_log("%.*s %.*s\n", ext_size, current, type_size, line);
2817 #endif
2818 uwsgi_dyn_dict_new(&uwsgi.mimetypes, current, ext_size, line, type_size);
2819 entries++;
2820 }
2821
2822 }
2823 line += linesize + 1;
2824 }
2825
2826 uwsgi_log("%d entry found\n", entries);
2827
2828 }
2829
2830 #ifdef __linux__
2831 struct uwsgi_unshare_id {
2832 char *name;
2833 int value;
2834 };
2835
2836 static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
2837 #ifdef CLONE_FILES
2838 {"files", CLONE_FILES},
2839 #endif
2840 #ifdef CLONE_NEWIPC
2841 {"ipc", CLONE_NEWIPC},
2842 #endif
2843 #ifdef CLONE_NEWNET
2844 {"net", CLONE_NEWNET},
2845 #endif
2846 #ifdef CLONE_IO
2847 {"io", CLONE_IO},
2848 #endif
2849 #ifdef CLONE_PARENT
2850 {"parent", CLONE_PARENT},
2851 #endif
2852 #ifdef CLONE_NEWPID
2853 {"pid", CLONE_NEWPID},
2854 #endif
2855 #ifdef CLONE_NEWNS
2856 {"ns", CLONE_NEWNS},
2857 {"fs", CLONE_NEWNS},
2858 {"mount", CLONE_NEWNS},
2859 {"mnt", CLONE_NEWNS},
2860 #endif
2861 #ifdef CLONE_SYSVSEM
2862 {"sysvsem", CLONE_SYSVSEM},
2863 #endif
2864 #ifdef CLONE_NEWUTS
2865 {"uts", CLONE_NEWUTS},
2866 #endif
2867 #ifdef CLONE_NEWUSER
2868 {"user", CLONE_NEWUSER},
2869 #endif
2870 {NULL, -1}
2871 };
2872
uwsgi_get_unshare_id(char * name)2873 static int uwsgi_get_unshare_id(char *name) {
2874
2875 struct uwsgi_unshare_id *uui = uwsgi_unshare_list;
2876 while (uui->name) {
2877 if (!strcmp(uui->name, name))
2878 return uui->value;
2879 uui++;
2880 }
2881
2882 return -1;
2883 }
2884
uwsgi_build_unshare(char * what,int * mask)2885 void uwsgi_build_unshare(char *what, int *mask) {
2886
2887 char *list = uwsgi_str(what);
2888 char *p, *ctx = NULL;
2889 uwsgi_foreach_token(list, ",", p, ctx) {
2890 int u_id = uwsgi_get_unshare_id(p);
2891 if (u_id != -1) {
2892 *mask |= u_id;
2893 }
2894 else {
2895 uwsgi_log("unknown namespace subsystem: %s\n", p);
2896 exit(1);
2897 }
2898 }
2899 free(list);
2900 }
2901
2902
2903 #endif
2904
2905 #ifdef UWSGI_CAP
2906 struct uwsgi_cap {
2907 char *name;
2908 cap_value_t value;
2909 };
2910
2911 static struct uwsgi_cap uwsgi_cap_list[] = {
2912 {"chown", CAP_CHOWN},
2913 {"dac_override", CAP_DAC_OVERRIDE},
2914 {"dac_read_search", CAP_DAC_READ_SEARCH},
2915 {"fowner", CAP_FOWNER},
2916 {"fsetid", CAP_FSETID},
2917 {"kill", CAP_KILL},
2918 {"setgid", CAP_SETGID},
2919 {"setuid", CAP_SETUID},
2920 {"setpcap", CAP_SETPCAP},
2921 {"linux_immutable", CAP_LINUX_IMMUTABLE},
2922 {"net_bind_service", CAP_NET_BIND_SERVICE},
2923 {"net_broadcast", CAP_NET_BROADCAST},
2924 {"net_admin", CAP_NET_ADMIN},
2925 {"net_raw", CAP_NET_RAW},
2926 {"ipc_lock", CAP_IPC_LOCK},
2927 {"ipc_owner", CAP_IPC_OWNER},
2928 {"sys_module", CAP_SYS_MODULE},
2929 {"sys_rawio", CAP_SYS_RAWIO},
2930 {"sys_chroot", CAP_SYS_CHROOT},
2931 {"sys_ptrace", CAP_SYS_PTRACE},
2932 {"sys_pacct", CAP_SYS_PACCT},
2933 {"sys_admin", CAP_SYS_ADMIN},
2934 {"sys_boot", CAP_SYS_BOOT},
2935 {"sys_nice", CAP_SYS_NICE},
2936 {"sys_resource", CAP_SYS_RESOURCE},
2937 {"sys_time", CAP_SYS_TIME},
2938 {"sys_tty_config", CAP_SYS_TTY_CONFIG},
2939 {"mknod", CAP_MKNOD},
2940 #ifdef CAP_LEASE
2941 {"lease", CAP_LEASE},
2942 #endif
2943 #ifdef CAP_AUDIT_WRITE
2944 {"audit_write", CAP_AUDIT_WRITE},
2945 #endif
2946 #ifdef CAP_AUDIT_CONTROL
2947 {"audit_control", CAP_AUDIT_CONTROL},
2948 #endif
2949 #ifdef CAP_SETFCAP
2950 {"setfcap", CAP_SETFCAP},
2951 #endif
2952 #ifdef CAP_MAC_OVERRIDE
2953 {"mac_override", CAP_MAC_OVERRIDE},
2954 #endif
2955 #ifdef CAP_MAC_ADMIN
2956 {"mac_admin", CAP_MAC_ADMIN},
2957 #endif
2958 #ifdef CAP_SYSLOG
2959 {"syslog", CAP_SYSLOG},
2960 #endif
2961 #ifdef CAP_WAKE_ALARM
2962 {"wake_alarm", CAP_WAKE_ALARM},
2963 #endif
2964 {NULL, -1}
2965 };
2966
uwsgi_get_cap_id(char * name)2967 static int uwsgi_get_cap_id(char *name) {
2968
2969 struct uwsgi_cap *ucl = uwsgi_cap_list;
2970 while (ucl->name) {
2971 if (!strcmp(ucl->name, name))
2972 return ucl->value;
2973 ucl++;
2974 }
2975
2976 return -1;
2977 }
2978
uwsgi_build_cap(char * what,cap_value_t ** cap)2979 int uwsgi_build_cap(char *what, cap_value_t ** cap) {
2980
2981 int cap_id;
2982 char *caps = uwsgi_str(what);
2983 int pos = 0;
2984 int count = 0;
2985
2986 char *p, *ctx = NULL;
2987 uwsgi_foreach_token(caps, ",", p, ctx) {
2988 if (is_a_number(p)) {
2989 count++;
2990 }
2991 else {
2992 cap_id = uwsgi_get_cap_id(p);
2993 if (cap_id != -1) {
2994 count++;
2995 }
2996 else {
2997 uwsgi_log("[security] unknown capability: %s\n", p);
2998 }
2999 }
3000 }
3001 free(caps);
3002
3003 *cap = uwsgi_malloc(sizeof(cap_value_t) * count);
3004
3005 caps = uwsgi_str(what);
3006 ctx = NULL;
3007 uwsgi_foreach_token(caps, ",", p, ctx) {
3008 if (is_a_number(p)) {
3009 cap_id = atoi(p);
3010 }
3011 else {
3012 cap_id = uwsgi_get_cap_id(p);
3013 }
3014 if (cap_id != -1) {
3015 (*cap)[pos] = cap_id;
3016 uwsgi_log("setting capability %s [%d]\n", p, cap_id);
3017 pos++;
3018 }
3019 else {
3020 uwsgi_log("[security] unknown capability: %s\n", p);
3021 }
3022 }
3023 free(caps);
3024
3025 return count;
3026 }
3027
3028 #endif
3029
uwsgi_apply_config_pass(char symbol,char * (* hook)(char *))3030 void uwsgi_apply_config_pass(char symbol, char *(*hook) (char *)) {
3031
3032 int i, j;
3033
3034 for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
3035 int has_symbol = 0;
3036 int depth = 0;
3037 char *magic_key = NULL;
3038 char *magic_val = NULL;
3039 if (uwsgi.exported_opts[i]->value && !uwsgi.exported_opts[i]->configured) {
3040 for (j = 0; j < (int) strlen(uwsgi.exported_opts[i]->value); j++) {
3041 if (uwsgi.exported_opts[i]->value[j] == symbol) {
3042 has_symbol = 1;
3043 }
3044 else if (uwsgi.exported_opts[i]->value[j] == '(' && has_symbol == 1) {
3045 has_symbol = 2;
3046 depth = 0;
3047 magic_key = uwsgi.exported_opts[i]->value + j + 1;
3048 }
3049 else if (has_symbol > 1) {
3050 if (uwsgi.exported_opts[i]->value[j] == '(') {
3051 has_symbol++;
3052 depth++;
3053 }
3054 else if (uwsgi.exported_opts[i]->value[j] == ')') {
3055 if (depth > 0) {
3056 has_symbol++;
3057 depth--;
3058 continue;
3059 }
3060 if (has_symbol <= 2) {
3061 magic_key = NULL;
3062 has_symbol = 0;
3063 continue;
3064 }
3065 #ifdef UWSGI_DEBUG
3066 uwsgi_log("need to interpret the %.*s tag\n", has_symbol - 2, magic_key);
3067 #endif
3068 char *tmp_magic_key = uwsgi_concat2n(magic_key, has_symbol - 2, "", 0);
3069 magic_val = hook(tmp_magic_key);
3070 free(tmp_magic_key);
3071 if (!magic_val) {
3072 magic_key = NULL;
3073 has_symbol = 0;
3074 continue;
3075 }
3076 uwsgi.exported_opts[i]->value = uwsgi_concat4n(uwsgi.exported_opts[i]->value, (magic_key - 2) - uwsgi.exported_opts[i]->value, magic_val, strlen(magic_val), magic_key + (has_symbol - 1), strlen(magic_key + (has_symbol - 1)), "", 0);
3077 #ifdef UWSGI_DEBUG
3078 uwsgi_log("computed new value = %s\n", uwsgi.exported_opts[i]->value);
3079 #endif
3080 magic_key = NULL;
3081 has_symbol = 0;
3082 j = 0;
3083 }
3084 else {
3085 has_symbol++;
3086 }
3087 }
3088 else {
3089 has_symbol = 0;
3090 }
3091 }
3092 }
3093 }
3094
3095 }
3096
uwsgi_set_processname(char * name)3097 void uwsgi_set_processname(char *name) {
3098
3099 #if defined(__linux__) || defined(__sun__)
3100 size_t amount = 0;
3101
3102 // prepare for strncat
3103 *uwsgi.orig_argv[0] = 0;
3104
3105 if (uwsgi.procname_prefix) {
3106 amount += strlen(uwsgi.procname_prefix);
3107 if ((int) amount > uwsgi.max_procname - 1)
3108 return;
3109 strncat(uwsgi.orig_argv[0], uwsgi.procname_prefix, uwsgi.max_procname - (amount + 1));
3110 }
3111
3112 amount += strlen(name);
3113 if ((int) amount > uwsgi.max_procname - 1)
3114 return;
3115 strncat(uwsgi.orig_argv[0], name, (uwsgi.max_procname - amount + 1));
3116
3117 if (uwsgi.procname_append) {
3118 amount += strlen(uwsgi.procname_append);
3119 if ((int) amount > uwsgi.max_procname - 1)
3120 return;
3121 strncat(uwsgi.orig_argv[0], uwsgi.procname_append, uwsgi.max_procname - (amount + 1));
3122 }
3123
3124 // fill with spaces...
3125 memset(uwsgi.orig_argv[0] + amount + 1, ' ', uwsgi.max_procname - (amount));
3126 // end with \0
3127 memset(uwsgi.orig_argv[0] + amount + 1 + (uwsgi.max_procname - (amount)), '\0', 1);
3128
3129 #elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__) || defined(__NetBSD__)
3130 if (uwsgi.procname_prefix) {
3131 if (!uwsgi.procname_append) {
3132 setproctitle("-%s%s", uwsgi.procname_prefix, name);
3133 }
3134 else {
3135 setproctitle("-%s%s%s", uwsgi.procname_prefix, name, uwsgi.procname_append);
3136 }
3137 }
3138 else if (uwsgi.procname_append) {
3139 if (!uwsgi.procname_prefix) {
3140 setproctitle("-%s%s", name, uwsgi.procname_append);
3141 }
3142 else {
3143 setproctitle("-%s%s%s", uwsgi.procname_prefix, name, uwsgi.procname_append);
3144 }
3145 }
3146 else {
3147 setproctitle("-%s", name);
3148 }
3149 #endif
3150 }
3151
3152 // this is a wrapper for fork restoring original argv
uwsgi_fork(char * name)3153 pid_t uwsgi_fork(char *name) {
3154
3155
3156 pid_t pid = fork();
3157 if (pid == 0) {
3158
3159 #ifndef __CYGWIN__
3160 if (uwsgi.never_swap) {
3161 if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
3162 uwsgi_error("mlockall()");
3163 }
3164 }
3165 #endif
3166
3167 #if defined(__linux__) || defined(__sun__)
3168 int i;
3169 for (i = 0; i < uwsgi.argc; i++) {
3170 // stop fixing original argv if the new one is bigger
3171 if (!uwsgi.orig_argv[i]) break;
3172 strcpy(uwsgi.orig_argv[i], uwsgi.argv[i]);
3173 }
3174 #endif
3175
3176 if (uwsgi.auto_procname && name) {
3177 if (uwsgi.procname) {
3178 uwsgi_set_processname(uwsgi.procname);
3179 }
3180 else {
3181 uwsgi_set_processname(name);
3182 }
3183 }
3184 }
3185
3186 return pid;
3187 }
3188
escape_shell_arg(char * src,size_t len,char * dst)3189 void escape_shell_arg(char *src, size_t len, char *dst) {
3190
3191 size_t i;
3192 char *ptr = dst;
3193
3194 for (i = 0; i < len; i++) {
3195 if (strchr("&;`'\"|*?~<>^()[]{}$\\\n", src[i])) {
3196 *ptr++ = '\\';
3197 }
3198 *ptr++ = src[i];
3199 }
3200
3201 *ptr++ = 0;
3202 }
3203
escape_json(char * src,size_t len,char * dst)3204 void escape_json(char *src, size_t len, char *dst) {
3205
3206 size_t i;
3207 char *ptr = dst;
3208
3209 for (i = 0; i < len; i++) {
3210 if (src[i] == '\t') {
3211 *ptr++ = '\\';
3212 *ptr++ = 't';
3213 }
3214 else if (src[i] == '\n') {
3215 *ptr++ = '\\';
3216 *ptr++ = 'n';
3217 }
3218 else if (src[i] == '\r') {
3219 *ptr++ = '\\';
3220 *ptr++ = 'r';
3221 }
3222 else if (src[i] == '"') {
3223 *ptr++ = '\\';
3224 *ptr++ = '"';
3225 }
3226 else if (src[i] == '\\') {
3227 *ptr++ = '\\';
3228 *ptr++ = '\\';
3229 }
3230 else {
3231 *ptr++ = src[i];
3232 }
3233 }
3234
3235 *ptr++ = 0;
3236 }
3237
3238 /*
3239
3240 build PATH_INFO from raw_uri
3241
3242 it manages:
3243
3244 percent encoding
3245 dot_segments removal
3246 stop at the first #
3247
3248 */
http_url_decode(char * buf,uint16_t * len,char * dst)3249 void http_url_decode(char *buf, uint16_t * len, char *dst) {
3250
3251 enum {
3252 zero = 0,
3253 percent1,
3254 percent2,
3255 slash,
3256 dot,
3257 dotdot
3258 } status;
3259
3260 uint16_t i, current_new_len, new_len = 0;
3261
3262 char value[2];
3263
3264 char *ptr = dst;
3265
3266 value[0] = '0';
3267 value[1] = '0';
3268
3269 status = zero;
3270 int no_slash = 0;
3271
3272 if (*len > 0 && buf[0] != '/') {
3273 status = slash;
3274 no_slash = 1;
3275 }
3276
3277 for (i = 0; i < *len; i++) {
3278 char c = buf[i];
3279 if (c == '#')
3280 break;
3281 switch (status) {
3282 case zero:
3283 if (c == '%') {
3284 status = percent1;
3285 break;
3286 }
3287 if (c == '/') {
3288 status = slash;
3289 break;
3290 }
3291 *ptr++ = c;
3292 new_len++;
3293 break;
3294 case percent1:
3295 if (c == '%') {
3296 *ptr++ = '%';
3297 new_len++;
3298 status = zero;
3299 break;
3300 }
3301 value[0] = c;
3302 status = percent2;
3303 break;
3304 case percent2:
3305 value[1] = c;
3306 *ptr++ = hex2num(value);
3307 new_len++;
3308 status = zero;
3309 break;
3310 case slash:
3311 if (c == '.') {
3312 status = dot;
3313 break;
3314 }
3315 // we could be at the first round (in non slash)
3316 if (i > 0 || !no_slash) {
3317 *ptr++ = '/';
3318 new_len++;
3319 }
3320 if (c == '%') {
3321 status = percent1;
3322 break;
3323 }
3324 if (c == '/') {
3325 status = slash;
3326 break;
3327 }
3328 *ptr++ = c;
3329 new_len++;
3330 status = zero;
3331 break;
3332 case dot:
3333 if (c == '.') {
3334 status = dotdot;
3335 break;
3336 }
3337 if (c == '/') {
3338 status = slash;
3339 break;
3340 }
3341 if (i > 1) {
3342 *ptr++ = '/';
3343 new_len++;
3344 }
3345 *ptr++ = '.';
3346 new_len++;
3347 if (c == '%') {
3348 status = percent1;
3349 break;
3350 }
3351 *ptr++ = c;
3352 new_len++;
3353 status = zero;
3354 break;
3355 case dotdot:
3356 // here we need to remove a segment
3357 if (c == '/') {
3358 current_new_len = new_len;
3359 while (current_new_len) {
3360 current_new_len--;
3361 ptr--;
3362 if (dst[current_new_len] == '/') {
3363 break;
3364 }
3365 }
3366 new_len = current_new_len;
3367 status = slash;
3368 break;
3369 }
3370 if (i > 2) {
3371 *ptr++ = '/';
3372 new_len++;
3373 }
3374 *ptr++ = '.';
3375 new_len++;
3376 *ptr++ = '.';
3377 new_len++;
3378 if (c == '%') {
3379 status = percent1;
3380 break;
3381 }
3382 *ptr++ = c;
3383 new_len++;
3384 status = zero;
3385 break;
3386 // over engineering
3387 default:
3388 *ptr++ = c;
3389 new_len++;
3390 break;
3391 }
3392 }
3393
3394 switch (status) {
3395 case slash:
3396 case dot:
3397 *ptr++ = '/';
3398 new_len++;
3399 break;
3400 case dotdot:
3401 current_new_len = new_len;
3402 while (current_new_len) {
3403 if (dst[current_new_len - 1] == '/') {
3404 break;
3405 }
3406 current_new_len--;
3407 }
3408 new_len = current_new_len;
3409 break;
3410 default:
3411 break;
3412 }
3413
3414 *len = new_len;
3415
3416 }
3417
3418
3419 /*
3420 we scan the table in reverse, as updated values are at the end
3421 */
uwsgi_get_var(struct wsgi_request * wsgi_req,char * key,uint16_t keylen,uint16_t * len)3422 char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t * len) {
3423
3424 int i;
3425
3426 for (i = wsgi_req->var_cnt - 1; i > 0; i -= 2) {
3427 if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i - 1].iov_base, wsgi_req->hvec[i - 1].iov_len)) {
3428 *len = wsgi_req->hvec[i].iov_len;
3429 return wsgi_req->hvec[i].iov_base;
3430 }
3431 }
3432
3433 return NULL;
3434 }
3435
uwsgi_add_app(int id,uint8_t modifier1,char * mountpoint,int mountpoint_len,void * interpreter,void * callable)3436 struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int mountpoint_len, void *interpreter, void *callable) {
3437
3438 if (id > uwsgi.max_apps) {
3439 uwsgi_log("FATAL ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
3440 exit(1);
3441 }
3442
3443 struct uwsgi_app *wi = &uwsgi_apps[id];
3444 memset(wi, 0, sizeof(struct uwsgi_app));
3445
3446 wi->modifier1 = modifier1;
3447 wi->mountpoint_len = mountpoint_len < 0xff ? mountpoint_len : (0xff - 1);
3448 strncpy(wi->mountpoint, mountpoint, wi->mountpoint_len);
3449 wi->interpreter = interpreter;
3450 wi->callable = callable;
3451
3452 uwsgi_apps_cnt++;
3453 // check if we need to emulate fork() COW
3454 int i;
3455 if (uwsgi.mywid == 0) {
3456 for (i = 1; i <= uwsgi.numproc; i++) {
3457 memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
3458 uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
3459 }
3460 }
3461
3462 if (!uwsgi.no_default_app) {
3463 if ((mountpoint_len == 0 || (mountpoint_len == 1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
3464 uwsgi.default_app = id;
3465 }
3466 }
3467
3468 return wi;
3469 }
3470
3471
uwsgi_check_touches(struct uwsgi_string_list * touch_list)3472 char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
3473
3474 // touch->value - file path
3475 // touch->custom - file timestamp
3476 // touch->custom2 - 0 if file exists, 1 if it does not exists
3477
3478 struct uwsgi_string_list *touch = touch_list;
3479 while (touch) {
3480 struct stat tr_st;
3481 if (stat(touch->value, &tr_st)) {
3482 if (touch->custom && !touch->custom2) {
3483 #ifdef UWSGI_DEBUG
3484 uwsgi_log("[uwsgi-check-touches] File %s was removed\n", touch->value);
3485 #endif
3486 touch->custom2 = 1;
3487 return touch->custom_ptr ? touch->custom_ptr : touch->value;
3488 }
3489 else if (!touch->custom && !touch->custom2) {
3490 uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
3491 touch->custom2 = 1;
3492 }
3493 touch->custom = 0;
3494 }
3495 else {
3496 if (!touch->custom && touch->custom2) {
3497 #ifdef UWSGI_DEBUG
3498 uwsgi_log("[uwsgi-check-touches] File was created: %s\n", touch->value);
3499 #endif
3500 touch->custom = (uint64_t) tr_st.st_mtime;
3501 touch->custom2 = 0;
3502 return touch->custom_ptr ? touch->custom_ptr : touch->value;
3503 }
3504 else if (touch->custom && (uint64_t) tr_st.st_mtime > touch->custom) {
3505 #ifdef UWSGI_DEBUG
3506 uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
3507 #endif
3508 touch->custom = (uint64_t) tr_st.st_mtime;
3509 return touch->custom_ptr ? touch->custom_ptr : touch->value;
3510 }
3511 touch->custom = (uint64_t) tr_st.st_mtime;
3512 }
3513 touch = touch->next;
3514 }
3515
3516 return NULL;
3517 }
3518
uwsgi_chomp(char * str)3519 char *uwsgi_chomp(char *str) {
3520 ssize_t slen = (ssize_t) strlen(str), i;
3521 if (!slen)
3522 return str;
3523 slen--;
3524 for (i = slen; i >= 0; i--) {
3525 if (str[i] == '\r' || str[i] == '\n') {
3526 str[i] = 0;
3527 }
3528 else {
3529 return str;
3530 }
3531 }
3532
3533 return str;
3534 }
3535
uwsgi_chomp2(char * str)3536 char *uwsgi_chomp2(char *str) {
3537 ssize_t slen = (ssize_t) strlen(str), i;
3538 if (!slen)
3539 return str;
3540 slen--;
3541 for (i = slen; i >= 0; i--) {
3542 if (str[i] == '\r' || str[i] == '\n' || str[i] == '\t' || str[i] == ' ') {
3543 str[i] = 0;
3544 }
3545 else {
3546 return str;
3547 }
3548 }
3549
3550 return str;
3551 }
3552
3553
3554
uwsgi_tmpfd()3555 int uwsgi_tmpfd() {
3556 int fd = -1;
3557 char *tmpdir = getenv("TMPDIR");
3558 if (!tmpdir) {
3559 tmpdir = "/tmp";
3560 }
3561 #ifdef O_TMPFILE
3562 fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
3563 if (fd >= 0) {
3564 return fd;
3565 }
3566 // fallback to old style
3567 #endif
3568 char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
3569 fd = mkstemp(template);
3570 unlink(template);
3571 free(template);
3572 return fd;
3573 }
3574
uwsgi_tmpfile()3575 FILE *uwsgi_tmpfile() {
3576 int fd = uwsgi_tmpfd();
3577 if (fd < 0)
3578 return NULL;
3579 return fdopen(fd, "w+");
3580 }
3581
uwsgi_file_to_string_list(char * filename,struct uwsgi_string_list ** list)3582 int uwsgi_file_to_string_list(char *filename, struct uwsgi_string_list **list) {
3583
3584 char line[1024];
3585
3586 FILE *fh = fopen(filename, "r");
3587 if (fh) {
3588 while (fgets(line, 1024, fh)) {
3589 uwsgi_string_new_list(list, uwsgi_chomp(uwsgi_str(line)));
3590 }
3591 fclose(fh);
3592 return 1;
3593 }
3594 uwsgi_error_open(filename);
3595 return 0;
3596 }
3597
uwsgi_setup_post_buffering()3598 void uwsgi_setup_post_buffering() {
3599
3600 if (!uwsgi.post_buffering_bufsize)
3601 uwsgi.post_buffering_bufsize = 8192;
3602
3603 if (uwsgi.post_buffering_bufsize < uwsgi.post_buffering) {
3604 uwsgi.post_buffering_bufsize = uwsgi.post_buffering;
3605 uwsgi_log("setting request body buffering size to %lu bytes\n", (unsigned long) uwsgi.post_buffering_bufsize);
3606 }
3607
3608 }
3609
uwsgi_emulate_cow_for_apps(int id)3610 void uwsgi_emulate_cow_for_apps(int id) {
3611 int i;
3612 // check if we need to emulate fork() COW
3613 if (uwsgi.mywid == 0) {
3614 for (i = 1; i <= uwsgi.numproc; i++) {
3615 memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
3616 uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
3617 }
3618 }
3619 }
3620
uwsgi_write_intfile(char * filename,int n)3621 int uwsgi_write_intfile(char *filename, int n) {
3622 FILE *pidfile = fopen(filename, "w");
3623 if (!pidfile) {
3624 uwsgi_error_open(filename);
3625 exit(1);
3626 }
3627 if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile)) {
3628 fclose(pidfile);
3629 return -1;
3630 }
3631 if (fclose(pidfile)) {
3632 return -1;
3633 }
3634 return 0;
3635 }
3636
uwsgi_write_pidfile(char * pidfile_name)3637 void uwsgi_write_pidfile(char *pidfile_name) {
3638 uwsgi_log("writing pidfile to %s\n", pidfile_name);
3639 if (uwsgi_write_intfile(pidfile_name, (int) getpid())) {
3640 uwsgi_log("could not write pidfile.\n");
3641 }
3642 }
3643
uwsgi_write_pidfile_explicit(char * pidfile_name,pid_t pid)3644 void uwsgi_write_pidfile_explicit(char *pidfile_name, pid_t pid) {
3645 uwsgi_log("writing pidfile to %s\n", pidfile_name);
3646 if (uwsgi_write_intfile(pidfile_name, (int) pid)) {
3647 uwsgi_log("could not write pidfile.\n");
3648 }
3649 }
3650
uwsgi_expand_path(char * dir,int dir_len,char * ptr)3651 char *uwsgi_expand_path(char *dir, int dir_len, char *ptr) {
3652 if (dir_len > PATH_MAX)
3653 {
3654 uwsgi_log("invalid path size: %d (max %d)\n", dir_len, PATH_MAX);
3655 return NULL;
3656 }
3657 char *src = uwsgi_concat2n(dir, dir_len, "", 0);
3658 char *dst = ptr;
3659 if (!dst)
3660 dst = uwsgi_malloc(PATH_MAX + 1);
3661 if (!realpath(src, dst)) {
3662 uwsgi_error_realpath(src);
3663 if (!ptr)
3664 free(dst);
3665 free(src);
3666 return NULL;
3667 }
3668 free(src);
3669 return dst;
3670 }
3671
3672
uwsgi_set_cpu_affinity()3673 void uwsgi_set_cpu_affinity() {
3674 char buf[4096];
3675 int ret;
3676 int pos = 0;
3677 if (uwsgi.cpu_affinity) {
3678 int base_cpu = (uwsgi.mywid - 1) * uwsgi.cpu_affinity;
3679 if (base_cpu >= uwsgi.cpus) {
3680 base_cpu = base_cpu % uwsgi.cpus;
3681 }
3682 ret = snprintf(buf, 4096, "mapping worker %d to CPUs:", uwsgi.mywid);
3683 if (ret < 25 || ret >= 4096) {
3684 uwsgi_log("unable to initialize cpu affinity !!!\n");
3685 exit(1);
3686 }
3687 pos += ret;
3688 #if defined(__linux__) || defined(__GNU_kFreeBSD__)
3689 cpu_set_t cpuset;
3690 #elif defined(__FreeBSD__)
3691 cpuset_t cpuset;
3692 #endif
3693 #if defined(__linux__) || defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
3694 CPU_ZERO(&cpuset);
3695 int i;
3696 for (i = 0; i < uwsgi.cpu_affinity; i++) {
3697 if (base_cpu >= uwsgi.cpus)
3698 base_cpu = 0;
3699 CPU_SET(base_cpu, &cpuset);
3700 ret = snprintf(buf + pos, 4096 - pos, " %d", base_cpu);
3701 if (ret < 2 || ret >= 4096) {
3702 uwsgi_log("unable to initialize cpu affinity !!!\n");
3703 exit(1);
3704 }
3705 pos += ret;
3706 base_cpu++;
3707 }
3708 #endif
3709 #if defined(__linux__) || defined(__GNU_kFreeBSD__)
3710 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset)) {
3711 uwsgi_error("sched_setaffinity()");
3712 }
3713 #elif defined(__FreeBSD__)
3714 if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset), &cpuset)) {
3715 uwsgi_error("cpuset_setaffinity");
3716 }
3717 #endif
3718 uwsgi_log("%s\n", buf);
3719 }
3720
3721 }
3722
3723 #ifdef UWSGI_ELF
3724 #if defined(__linux__)
3725 #include <elf.h>
3726 #endif
uwsgi_elf_section(char * filename,char * s,size_t * len)3727 char *uwsgi_elf_section(char *filename, char *s, size_t * len) {
3728 struct stat st;
3729 char *output = NULL;
3730 int fd = open(filename, O_RDONLY);
3731 if (fd < 0) {
3732 uwsgi_error_open(filename);
3733 return NULL;
3734 }
3735
3736 if (fstat(fd, &st)) {
3737 uwsgi_error("stat()");
3738 close(fd);
3739 return NULL;
3740 }
3741
3742 if (st.st_size < EI_NIDENT) {
3743 uwsgi_log("invalid elf file: %s\n", filename);
3744 close(fd);
3745 return NULL;
3746 }
3747
3748 char *addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
3749 if (addr == MAP_FAILED) {
3750 uwsgi_error("mmap()");
3751 close(fd);
3752 return NULL;
3753 }
3754
3755 if (addr[0] != ELFMAG0)
3756 goto clear;
3757 if (addr[1] != ELFMAG1)
3758 goto clear;
3759 if (addr[2] != ELFMAG2)
3760 goto clear;
3761 if (addr[3] != ELFMAG3)
3762 goto clear;
3763
3764 if (addr[4] == ELFCLASS32) {
3765 // elf header
3766 Elf32_Ehdr *elfh = (Elf32_Ehdr *) addr;
3767 // first section
3768 Elf32_Shdr *sections = ((Elf32_Shdr *) (addr + elfh->e_shoff));
3769 // number of sections
3770 int ns = elfh->e_shnum;
3771 // the names table
3772 Elf32_Shdr *table = §ions[elfh->e_shstrndx];
3773 // string table session pointer
3774 char *names = addr + table->sh_offset;
3775 Elf32_Shdr *ss = NULL;
3776 int i;
3777 for (i = 0; i < ns; i++) {
3778 char *name = names + sections[i].sh_name;
3779 if (!strcmp(name, s)) {
3780 ss = §ions[i];
3781 break;
3782 }
3783 }
3784
3785 if (ss) {
3786 *len = ss->sh_size;
3787 output = uwsgi_concat2n(addr + ss->sh_offset, ss->sh_size, "", 0);
3788 }
3789 }
3790 else if (addr[4] == ELFCLASS64) {
3791 // elf header
3792 Elf64_Ehdr *elfh = (Elf64_Ehdr *) addr;
3793 // first section
3794 Elf64_Shdr *sections = ((Elf64_Shdr *) (addr + elfh->e_shoff));
3795 // number of sections
3796 int ns = elfh->e_shnum;
3797 // the names table
3798 Elf64_Shdr *table = §ions[elfh->e_shstrndx];
3799 // string table session pointer
3800 char *names = addr + table->sh_offset;
3801 Elf64_Shdr *ss = NULL;
3802 int i;
3803 for (i = 0; i < ns; i++) {
3804 char *name = names + sections[i].sh_name;
3805 if (!strcmp(name, s)) {
3806 ss = §ions[i];
3807 break;
3808 }
3809 }
3810
3811 if (ss) {
3812 *len = ss->sh_size;
3813 output = uwsgi_concat2n(addr + ss->sh_offset, ss->sh_size, "", 0);
3814 }
3815 }
3816
3817
3818 clear:
3819 close(fd);
3820 munmap(addr, st.st_size);
3821 return output;
3822 }
3823 #endif
3824
uwsgi_thread_run(void * arg)3825 static void *uwsgi_thread_run(void *arg) {
3826 struct uwsgi_thread *ut = (struct uwsgi_thread *) arg;
3827 // block all signals
3828 sigset_t smask;
3829 sigfillset(&smask);
3830 pthread_sigmask(SIG_BLOCK, &smask, NULL);
3831
3832 ut->queue = event_queue_init();
3833 event_queue_add_fd_read(ut->queue, ut->pipe[1]);
3834
3835 ut->func(ut);
3836 return NULL;
3837 }
3838
uwsgi_thread_new_with_data(void (* func)(struct uwsgi_thread *),void * data)3839 struct uwsgi_thread *uwsgi_thread_new_with_data(void (*func) (struct uwsgi_thread *), void *data) {
3840
3841 struct uwsgi_thread *ut = uwsgi_calloc(sizeof(struct uwsgi_thread));
3842
3843 #if defined(SOCK_SEQPACKET) && defined(__linux__)
3844 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ut->pipe)) {
3845 #else
3846 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ut->pipe)) {
3847 #endif
3848 free(ut);
3849 return NULL;
3850 }
3851
3852 uwsgi_socket_nb(ut->pipe[0]);
3853 uwsgi_socket_nb(ut->pipe[1]);
3854
3855 ut->func = func;
3856 ut->data = data;
3857
3858 pthread_attr_init(&ut->tattr);
3859 pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED);
3860 // 512K should be enough...
3861 pthread_attr_setstacksize(&ut->tattr, 512 * 1024);
3862
3863 if (pthread_create(&ut->tid, &ut->tattr, uwsgi_thread_run, ut)) {
3864 uwsgi_error("pthread_create()");
3865 goto error;
3866 }
3867
3868 return ut;
3869 error:
3870 close(ut->pipe[0]);
3871 close(ut->pipe[1]);
3872 free(ut);
3873 return NULL;
3874 }
3875
3876 struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
3877 return uwsgi_thread_new_with_data(func, NULL);
3878 }
3879
3880 int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, int kv_separator, ...) {
3881 size_t i;
3882 va_list ap;
3883 struct uwsgi_string_list *itemlist = NULL;
3884
3885 char *buf = uwsgi_calloc(len + 1);
3886
3887 // ok let's start splitting the string
3888 int escaped = 0;
3889 char *base = buf;
3890 char *ptr = buf;
3891 for (i = 0; i < len; i++) {
3892 if (src[i] == list_separator && !escaped) {
3893 *ptr++ = 0;
3894 uwsgi_string_new_list(&itemlist, base);
3895 base = ptr;
3896 }
3897 else if (src[i] == '\\' && !escaped) {
3898 escaped = 1;
3899 }
3900 else if (escaped) {
3901 *ptr++ = src[i];
3902 escaped = 0;
3903 }
3904 else {
3905 *ptr++ = src[i];
3906 }
3907 }
3908
3909 if (ptr > base) {
3910 uwsgi_string_new_list(&itemlist, base);
3911 }
3912
3913 struct uwsgi_string_list *usl = itemlist;
3914 while (usl) {
3915 len = strlen(usl->value);
3916 char *item_buf = uwsgi_calloc(len + 1);
3917 base = item_buf;
3918 ptr = item_buf;
3919 escaped = 0;
3920 for (i = 0; i < len; i++) {
3921 if (usl->value[i] == kv_separator && !escaped) {
3922 *ptr++ = 0;
3923 va_start(ap, kv_separator);
3924 for (;;) {
3925 char *p = va_arg(ap, char *);
3926 if (!p)
3927 break;
3928 char **pp = va_arg(ap, char **);
3929 if (!pp)
3930 break;
3931 if (!strcmp(p, base)) {
3932 *pp = uwsgi_str(usl->value + i + 1);
3933 }
3934 }
3935 va_end(ap);
3936 base = ptr;
3937 break;
3938 }
3939 else if (usl->value[i] == '\\' && !escaped) {
3940 escaped = 1;
3941 }
3942 else if (escaped) {
3943 escaped = 0;
3944 }
3945 else {
3946 *ptr++ = usl->value[i];
3947 }
3948 }
3949 free(item_buf);
3950 usl = usl->next;
3951 }
3952
3953 // destroy the list (no need to destroy the value as it is a pointer to buf)
3954 usl = itemlist;
3955 while (usl) {
3956 struct uwsgi_string_list *tmp_usl = usl;
3957 usl = usl->next;
3958 free(tmp_usl);
3959 }
3960
3961 free(buf);
3962 return 0;
3963 }
3964
3965 int uwsgi_send_http_stats(int fd) {
3966
3967 char buf[4096];
3968
3969 int ret = uwsgi_waitfd(fd, uwsgi.socket_timeout);
3970 if (ret <= 0)
3971 return -1;
3972
3973 if (read(fd, buf, 4096) <= 0)
3974 return -1;
3975
3976 struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
3977 if (!ub)
3978 return -1;
3979
3980 if (uwsgi_buffer_append(ub, "HTTP/1.0 200 OK\r\n", 17))
3981 goto error;
3982 if (uwsgi_buffer_append(ub, "Connection: close\r\n", 19))
3983 goto error;
3984 if (uwsgi_buffer_append(ub, "Access-Control-Allow-Origin: *\r\n", 32))
3985 goto error;
3986 if (uwsgi_buffer_append(ub, "Content-Type: application/json\r\n", 32))
3987 goto error;
3988 if (uwsgi_buffer_append(ub, "\r\n", 2))
3989 goto error;
3990
3991 if (uwsgi_buffer_send(ub, fd))
3992 goto error;
3993 uwsgi_buffer_destroy(ub);
3994 return 0;
3995
3996 error:
3997 uwsgi_buffer_destroy(ub);
3998 return -1;
3999 }
4000
4001 int uwsgi_call_symbol(char *symbol) {
4002 void (*func) (void) = dlsym(RTLD_DEFAULT, symbol);
4003 if (!func)
4004 return -1;
4005 func();
4006 return 0;
4007 }
4008
4009 int uwsgi_plugin_modifier1(char *plugin) {
4010 int ret = -1;
4011 char *symbol_name = uwsgi_concat2(plugin, "_plugin");
4012 struct uwsgi_plugin *up = dlsym(RTLD_DEFAULT, symbol_name);
4013 if (!up)
4014 goto end;
4015 ret = up->modifier1;
4016 end:
4017 free(symbol_name);
4018 return ret;
4019 }
4020
4021 char *uwsgi_strip(char *src) {
4022 char *dst = src;
4023 size_t len = strlen(src);
4024 int i;
4025
4026 for (i = 0; i < (ssize_t) len; i++) {
4027 if (src[i] == ' ' || src[i] == '\t') {
4028 dst++;
4029 }
4030 }
4031
4032 len -= (dst - src);
4033
4034 for (i = len; i >= 0; i--) {
4035 if (dst[i] == ' ' || dst[i] == '\t') {
4036 dst[i] = 0;
4037 }
4038 else {
4039 break;
4040 }
4041 }
4042
4043 return dst;
4044 }
4045
4046 void uwsgi_uuid(char *buf) {
4047 #ifdef UWSGI_UUID
4048 uuid_t uuid_value;
4049 uuid_generate(uuid_value);
4050 uuid_unparse(uuid_value, buf);
4051 #else
4052 int i, r[11];
4053 if (!uwsgi_file_exists("/dev/urandom"))
4054 goto fallback;
4055 int fd = open("/dev/urandom", O_RDONLY);
4056 if (fd < 0)
4057 goto fallback;
4058 for (i = 0; i < 11; i++) {
4059 if (read(fd, &r[i], 4) != 4) {
4060 close(fd);
4061 goto fallback;
4062 }
4063 }
4064 close(fd);
4065 goto done;
4066 fallback:
4067 for (i = 0; i < 11; i++) {
4068 r[i] = rand();
4069 }
4070 done:
4071 snprintf(buf, 37, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10]);
4072 #endif
4073 }
4074
4075 int uwsgi_uuid_cmp(char *x, char *y) {
4076 int i;
4077 for (i = 0; i < 36; i++) {
4078 if (x[i] != y[i]) {
4079 if (x[i] > y[i]) {
4080 return 1;
4081 }
4082 return 0;
4083 }
4084 }
4085 return 0;
4086 }
4087
4088 void uwsgi_additional_header_add(struct wsgi_request *wsgi_req, char *hh, uint16_t hh_len) {
4089 // will be freed on request's end
4090 char *header = uwsgi_concat2n(hh, hh_len, "", 0);
4091 uwsgi_string_new_list(&wsgi_req->additional_headers, header);
4092 }
4093
4094 void uwsgi_remove_header(struct wsgi_request *wsgi_req, char *hh, uint16_t hh_len) {
4095 char *header = uwsgi_concat2n(hh, hh_len, "", 0);
4096 uwsgi_string_new_list(&wsgi_req->remove_headers, header);
4097 }
4098
4099 // based on nginx implementation
4100
4101 static uint8_t b64_table64[] = {
4102 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4103 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4104 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
4105 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
4106 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
4107 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
4108 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
4109 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
4110
4111 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4112 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4113 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4114 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4115 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4116 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4117 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
4118 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
4119 };
4120
4121 static char b64_table64_2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4122
4123 char *uwsgi_base64_decode(char *buf, size_t len, size_t * d_len) {
4124
4125 // find the real size and check for invalid values
4126 size_t i;
4127 for (i = 0; i < len; i++) {
4128 if (buf[i] == '=')
4129 break;
4130
4131 // check for invalid content
4132 if (b64_table64[(uint8_t) buf[i]] == 77) {
4133 return NULL;
4134 }
4135 }
4136
4137 // check for invalid size
4138 if (i % 4 == 1)
4139 return NULL;
4140
4141 // compute the new size
4142 *d_len = (((len + 3) / 4) * 3);
4143 char *dst = uwsgi_malloc(*d_len + 1);
4144
4145 char *ptr = dst;
4146 uint8_t *src = (uint8_t *) buf;
4147 while (i > 3) {
4148 *ptr++ = (char) (b64_table64[src[0]] << 2 | b64_table64[src[1]] >> 4);
4149 *ptr++ = (char) (b64_table64[src[1]] << 4 | b64_table64[src[2]] >> 2);
4150 *ptr++ = (char) (b64_table64[src[2]] << 6 | b64_table64[src[3]]);
4151
4152 src += 4;
4153 i -= 4;
4154 }
4155
4156 if (i > 1) {
4157 *ptr++ = (char) (b64_table64[src[0]] << 2 | b64_table64[src[1]] >> 4);
4158 }
4159
4160 if (i > 2) {
4161 *ptr++ = (char) (b64_table64[src[1]] << 4 | b64_table64[src[2]] >> 2);
4162 }
4163
4164 *d_len = (ptr - dst);
4165 *ptr++ = 0;
4166
4167 return dst;
4168
4169 }
4170
4171 char *uwsgi_base64_encode(char *buf, size_t len, size_t * d_len) {
4172 *d_len = ((len * 4) / 3) + 5;
4173 uint8_t *src = (uint8_t *) buf;
4174 char *dst = uwsgi_malloc(*d_len);
4175 char *ptr = dst;
4176 while (len >= 3) {
4177 *ptr++ = b64_table64_2[src[0] >> 2];
4178 *ptr++ = b64_table64_2[((src[0] << 4) & 0x30) | (src[1] >> 4)];
4179 *ptr++ = b64_table64_2[((src[1] << 2) & 0x3C) | (src[2] >> 6)];
4180 *ptr++ = b64_table64_2[src[2] & 0x3F];
4181 src += 3;
4182 len -= 3;
4183 }
4184
4185 if (len > 0) {
4186 *ptr++ = b64_table64_2[src[0] >> 2];
4187 uint8_t tmp = (src[0] << 4) & 0x30;
4188 if (len > 1)
4189 tmp |= src[1] >> 4;
4190 *ptr++ = b64_table64_2[tmp];
4191 if (len < 2) {
4192 *ptr++ = '=';
4193 }
4194 else {
4195 *ptr++ = b64_table64_2[(src[1] << 2) & 0x3C];
4196 }
4197 *ptr++ = '=';
4198 }
4199
4200 *ptr = 0;
4201 *d_len = ((char *) ptr - dst);
4202
4203 return dst;
4204 }
4205
4206 uint16_t uwsgi_be16(char *buf) {
4207 uint16_t *src = (uint16_t *) buf;
4208 uint16_t ret = 0;
4209 uint8_t *ptr = (uint8_t *) & ret;
4210 ptr[0] = (uint8_t) ((*src >> 8) & 0xff);
4211 ptr[1] = (uint8_t) (*src & 0xff);
4212 return ret;
4213 }
4214
4215 uint32_t uwsgi_be32(char *buf) {
4216 uint32_t *src = (uint32_t *) buf;
4217 uint32_t ret = 0;
4218 uint8_t *ptr = (uint8_t *) & ret;
4219 ptr[0] = (uint8_t) ((*src >> 24) & 0xff);
4220 ptr[1] = (uint8_t) ((*src >> 16) & 0xff);
4221 ptr[2] = (uint8_t) ((*src >> 8) & 0xff);
4222 ptr[3] = (uint8_t) (*src & 0xff);
4223 return ret;
4224 }
4225
4226 uint64_t uwsgi_be64(char *buf) {
4227 uint64_t *src = (uint64_t *) buf;
4228 uint64_t ret = 0;
4229 uint8_t *ptr = (uint8_t *) & ret;
4230 ptr[0] = (uint8_t) ((*src >> 56) & 0xff);
4231 ptr[1] = (uint8_t) ((*src >> 48) & 0xff);
4232 ptr[2] = (uint8_t) ((*src >> 40) & 0xff);
4233 ptr[3] = (uint8_t) ((*src >> 32) & 0xff);
4234 ptr[4] = (uint8_t) ((*src >> 24) & 0xff);
4235 ptr[5] = (uint8_t) ((*src >> 16) & 0xff);
4236 ptr[6] = (uint8_t) ((*src >> 8) & 0xff);
4237 ptr[7] = (uint8_t) (*src & 0xff);
4238 return ret;
4239 }
4240
4241 char *uwsgi_get_header(struct wsgi_request *wsgi_req, char *hh, uint16_t len, uint16_t * rlen) {
4242 char *key = uwsgi_malloc(len + 6);
4243 uint16_t key_len = len;
4244 char *ptr = key;
4245 *rlen = 0;
4246 if (uwsgi_strncmp(hh, len, "Content-Length", 14) && uwsgi_strncmp(hh, len, "Content-Type", 12)) {
4247 memcpy(ptr, "HTTP_", 5);
4248 ptr += 5;
4249 key_len += 5;
4250 }
4251
4252 uint16_t i;
4253 for (i = 0; i < len; i++) {
4254 if (hh[i] == '-') {
4255 *ptr++ = '_';
4256 }
4257 else {
4258 *ptr++ = toupper((int) hh[i]);
4259 }
4260 }
4261
4262 char *value = uwsgi_get_var(wsgi_req, key, key_len, rlen);
4263 free(key);
4264 return value;
4265
4266 }
4267
4268 static char *uwsgi_hex_table[] = {
4269 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
4270 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
4271 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
4272 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
4273 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
4274 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
4275 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
4276 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
4277 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
4278 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
4279 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
4280 "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
4281 "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
4282 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
4283 "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
4284 "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
4285 };
4286
4287 char *uwsgi_str_to_hex(char *src, size_t slen) {
4288 char *dst = uwsgi_malloc(slen * 2);
4289 char *ptr = dst;
4290 size_t i;
4291 for (i = 0; i < slen; i++) {
4292 uint8_t pos = (uint8_t) src[i];
4293 memcpy(ptr, uwsgi_hex_table[pos], 2);
4294 ptr += 2;
4295 }
4296 return dst;
4297 }
4298
4299 // dst has to be 3 times buf size (USE IT ONLY FOR PATH_INFO !!!)
4300 void http_url_encode(char *buf, uint16_t * len, char *dst) {
4301
4302 uint16_t i;
4303 char *ptr = dst;
4304 for (i = 0; i < *len; i++) {
4305 if ((buf[i] >= 'A' && buf[i] <= 'Z') || (buf[i] >= 'a' && buf[i] <= 'z') || (buf[i] >= '0' && buf[i] <= '9') || buf[i] == '-' || buf[i] == '_' || buf[i] == '.' || buf[i] == '~' || buf[i] == '/') {
4306 *ptr++ = buf[i];
4307 }
4308 else {
4309 char *h = uwsgi_hex_table[(int) buf[i]];
4310 *ptr++ = '%';
4311 *ptr++ = h[0];
4312 *ptr++ = h[1];
4313 }
4314 }
4315
4316 *len = ptr - dst;
4317
4318 }
4319
4320 void uwsgi_takeover() {
4321 if (uwsgi.i_am_a_spooler) {
4322 uwsgi_spooler_run();
4323 }
4324 else if (uwsgi.muleid) {
4325 uwsgi_mule_run();
4326 }
4327 else {
4328 uwsgi_worker_run();
4329 }
4330 }
4331
4332 // create a message pipe
4333 void create_msg_pipe(int *fd, int bufsize) {
4334
4335 #if defined(SOCK_SEQPACKET) && defined(__linux__)
4336 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd)) {
4337 #else
4338 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
4339 #endif
4340 uwsgi_error("create_msg_pipe()/socketpair()");
4341 exit(1);
4342 }
4343
4344 uwsgi_socket_nb(fd[0]);
4345 uwsgi_socket_nb(fd[1]);
4346
4347 if (bufsize) {
4348 if (setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
4349 uwsgi_error("create_msg_pipe()/setsockopt()");
4350 }
4351 if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
4352 uwsgi_error("create_msg_pipe()/setsockopt()");
4353 }
4354
4355 if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
4356 uwsgi_error("create_msg_pipe()/setsockopt()");
4357 }
4358 if (setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
4359 uwsgi_error("create_msg_pipe()/setsockopt()");
4360 }
4361 }
4362 }
4363
4364 char *uwsgi_binary_path() {
4365 return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
4366 }
4367
4368 void uwsgi_envdir(char *edir) {
4369 DIR *d = opendir(edir);
4370 if (!d) {
4371 uwsgi_error("[uwsgi-envdir] opendir()");
4372 exit(1);
4373 }
4374 struct dirent *de;
4375 while ((de = readdir(d)) != NULL) {
4376 // skip hidden files
4377 if (de->d_name[0] == '.')
4378 continue;
4379 struct stat st;
4380 char *filename = uwsgi_concat3(edir, "/", de->d_name);
4381 if (stat(filename, &st)) {
4382 uwsgi_log("[uwsgi-envdir] error stating %s\n", filename);
4383 uwsgi_error("[uwsgi-envdir] stat()");
4384 exit(1);
4385 }
4386
4387 if (!S_ISREG(st.st_mode)) {
4388 free(filename);
4389 continue;
4390 }
4391
4392 // unsetenv
4393 if (st.st_size == 0) {
4394 #ifdef UNSETENV_VOID
4395 unsetenv(de->d_name);
4396 #else
4397 if (unsetenv(de->d_name)) {
4398 uwsgi_log("[uwsgi-envdir] unable to unset %s\n", de->d_name);
4399 uwsgi_error("[uwsgi-envdir] unsetenv");
4400 exit(1);
4401 }
4402 #endif
4403 free(filename);
4404 continue;
4405 }
4406
4407 // read the content of the file
4408 size_t size = 0;
4409 char *content = uwsgi_open_and_read(filename, &size, 1, NULL);
4410 if (!content) {
4411 uwsgi_log("[uwsgi-envdir] unable to open %s\n", filename);
4412 uwsgi_error_open(filename);
4413 exit(1);
4414 }
4415 free(filename);
4416
4417 // HACK, envdir states we only need to strip the end of the string ....
4418 uwsgi_chomp2(content);
4419 // ... and substitute 0 with \n
4420 size_t slen = strlen(content);
4421 size_t i;
4422 for (i = 0; i < slen; i++) {
4423 if (content[i] == 0) {
4424 content[i] = '\n';
4425 }
4426 }
4427
4428 if (setenv(de->d_name, content, 1)) {
4429 uwsgi_log("[uwsgi-envdir] unable to set %s\n", de->d_name);
4430 uwsgi_error("[uwsgi-envdir] setenv");
4431 exit(1);
4432 }
4433
4434 free(content);
4435 }
4436 closedir(d);
4437 }
4438
4439 void uwsgi_envdirs(struct uwsgi_string_list *envdirs) {
4440 struct uwsgi_string_list *usl = envdirs;
4441 while (usl) {
4442 uwsgi_envdir(usl->value);
4443 usl = usl->next;
4444 }
4445 }
4446
4447 void uwsgi_opt_envdir(char *opt, char *value, void *foobar) {
4448 uwsgi_envdir(value);
4449 }
4450
4451 void uwsgi_exit(int status) {
4452 uwsgi.last_exit_code = status;
4453 // disable macro expansion
4454 (exit) (status);
4455 }
4456
4457 int uwsgi_base128(struct uwsgi_buffer *ub, uint64_t l, int first) {
4458 if (l > 127) {
4459 if (uwsgi_base128(ub, l / 128, 0))
4460 return -1;
4461 }
4462 l %= 128;
4463 if (first) {
4464 if (uwsgi_buffer_u8(ub, (uint8_t) l))
4465 return -1;
4466 }
4467 else {
4468 if (uwsgi_buffer_u8(ub, 0x80 | (uint8_t) l))
4469 return -1;
4470 }
4471 return 0;
4472 }
4473
4474 #ifdef __linux__
4475 void uwsgi_setns(char *path) {
4476 int (*u_setns) (int, int) = (int (*)(int, int)) dlsym(RTLD_DEFAULT, "setns");
4477 if (!u_setns) {
4478 uwsgi_log("your system misses setns() syscall !!!\n");
4479 exit(1);
4480 }
4481
4482 // cound be overwritten
4483 int count = 64;
4484
4485 uwsgi_log("joining namespaces from %s ...\n", path);
4486 for (;;) {
4487 int ns_fd = uwsgi_connect(path, 30, 0);
4488 if (ns_fd < 0) {
4489 uwsgi_error("uwsgi_setns()/uwsgi_connect()");
4490 sleep(1);
4491 continue;
4492 }
4493 int *fds = uwsgi_attach_fd(ns_fd, &count, "uwsgi-setns", 11);
4494 if (fds && count > 0) {
4495 int i;
4496 for (i = 0; i < count; i++) {
4497 if (fds[i] > -1) {
4498 if (u_setns(fds[i], 0) < 0) {
4499 uwsgi_error("uwsgi_setns()/setns()");
4500 exit(1);
4501 }
4502 close(fds[i]);
4503 }
4504 }
4505 free(fds);
4506 close(ns_fd);
4507 break;
4508 }
4509 if (fds)
4510 free(fds);
4511 close(ns_fd);
4512 sleep(1);
4513 }
4514 }
4515 #endif
4516
4517 mode_t uwsgi_mode_t(char *value, int *error) {
4518 mode_t mode = 0;
4519 *error = 0;
4520
4521 if (strlen(value) < 3) {
4522 *error = 1;
4523 return mode;
4524 }
4525
4526 if (strlen(value) == 3) {
4527 mode = (mode << 3) + (value[0] - '0');
4528 mode = (mode << 3) + (value[1] - '0');
4529 mode = (mode << 3) + (value[2] - '0');
4530 }
4531 else {
4532 mode = (mode << 3) + (value[1] - '0');
4533 mode = (mode << 3) + (value[2] - '0');
4534 mode = (mode << 3) + (value[3] - '0');
4535 }
4536
4537 return mode;
4538 }
4539
4540
4541 int uwsgi_wait_for_mountpoint(char *mountpoint) {
4542 if (!uwsgi.wait_for_fs_timeout) {
4543 uwsgi.wait_for_fs_timeout = 60;
4544 }
4545 uwsgi_log("waiting for %s (max %d seconds) ...\n", mountpoint, uwsgi.wait_for_fs_timeout);
4546 int counter = 0;
4547 for (;;) {
4548 if (counter > uwsgi.wait_for_fs_timeout) {
4549 uwsgi_log("%s unavailable after %d seconds\n", mountpoint, counter);
4550 return -1;
4551 }
4552 struct stat st0;
4553 struct stat st1;
4554 if (stat(mountpoint, &st0)) goto retry;
4555 if (!S_ISDIR(st0.st_mode)) goto retry;
4556 char *relative = uwsgi_concat2(mountpoint, "/../");
4557 if (stat(relative, &st1)) {
4558 free(relative);
4559 goto retry;
4560 }
4561 free(relative);
4562 // useless :P
4563 if (!S_ISDIR(st1.st_mode)) goto retry;
4564 if (st0.st_dev == st1.st_dev) goto retry;
4565 uwsgi_log_verbose("%s mounted\n", mountpoint);
4566 return 0;
4567 retry:
4568 sleep(1);
4569 counter++;
4570 }
4571 return -1;
4572 }
4573
4574 // type -> 1 file, 2 dir, 0 both
4575 int uwsgi_wait_for_fs(char *filename, int type) {
4576 if (!uwsgi.wait_for_fs_timeout) {
4577 uwsgi.wait_for_fs_timeout = 60;
4578 }
4579 uwsgi_log("waiting for %s (max %d seconds) ...\n", filename, uwsgi.wait_for_fs_timeout);
4580 int counter = 0;
4581 for (;;) {
4582 if (counter > uwsgi.wait_for_fs_timeout) {
4583 uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
4584 return -1;
4585 }
4586 struct stat st;
4587 if (stat(filename, &st)) goto retry;
4588 if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
4589 if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
4590 uwsgi_log_verbose("%s found\n", filename);
4591 return 0;
4592 retry:
4593 sleep(1);
4594 counter++;
4595 }
4596 return -1;
4597 }
4598
4599 int uwsgi_wait_for_socket(char *socket_name) {
4600 if (!uwsgi.wait_for_socket_timeout) {
4601 uwsgi.wait_for_socket_timeout = 60;
4602 }
4603 uwsgi_log("waiting for %s (max %d seconds) ...\n", socket_name, uwsgi.wait_for_socket_timeout);
4604 int counter = 0;
4605 for (;;) {
4606 if (counter > uwsgi.wait_for_socket_timeout) {
4607 uwsgi_log("%s unavailable after %d seconds\n", socket_name, counter);
4608 return -1;
4609 }
4610 // wait for 1 second to respect uwsgi.wait_for_fs_timeout
4611 int fd = uwsgi_connect(socket_name, 1, 0);
4612 if (fd < 0) goto retry;
4613 close(fd);
4614 uwsgi_log_verbose("%s ready\n", socket_name);
4615 return 0;
4616 retry:
4617 sleep(1);
4618 counter++;
4619 }
4620 return -1;
4621 }
4622
4623 void uwsgi_fix_range_for_size(enum uwsgi_range* parsed, int64_t* from, int64_t* to, int64_t size) {
4624 if (*parsed != UWSGI_RANGE_PARSED) {
4625 return;
4626 }
4627 if (*from < 0) {
4628 *from = size + *from;
4629 }
4630 if (*to > size-1) {
4631 *to = size-1;
4632 }
4633 if (*from == 0 && *to == size-1) {
4634 /* we have a right to reset to 200 OK answer */
4635 *parsed = UWSGI_RANGE_NOT_PARSED;
4636 }
4637 else if (*to >= *from) {
4638 *parsed = UWSGI_RANGE_VALID;
4639 }
4640 else { /* case *from > size-1 is also handled here */
4641 *parsed = UWSGI_RANGE_INVALID;
4642 *from = 0;
4643 *to = 0;
4644 }
4645 }
4646