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(&params[i], usl->value)) {
488 				uwsgi_error("jailparam_init()");
489 				exit(1);
490 			}
491 			if (equal) {
492 				jailparam_import(&params[i], equal + 1);
493 				*equal = '=';
494 			}
495 			else {
496 				jailparam_import(&params[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, &regexp, &regexp_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 = &sections[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 = &sections[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 = &sections[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 = &sections[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