xref: /PHP-8.1/ext/standard/basic_functions.c (revision b4208c8f)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Andi Gutmans <andi@php.net>                                 |
14    |          Zeev Suraski <zeev@php.net>                                 |
15    +----------------------------------------------------------------------+
16  */
17 
18 #include "php.h"
19 #include "php_streams.h"
20 #include "php_main.h"
21 #include "php_globals.h"
22 #include "php_variables.h"
23 #include "php_ini.h"
24 #include "php_standard.h"
25 #include "php_math.h"
26 #include "php_http.h"
27 #include "php_incomplete_class.h"
28 #include "php_getopt.h"
29 #include "ext/standard/info.h"
30 #include "ext/session/php_session.h"
31 #include "zend_exceptions.h"
32 #include "zend_operators.h"
33 #include "ext/standard/php_dns.h"
34 #include "ext/standard/php_uuencode.h"
35 #include "ext/standard/php_mt_rand.h"
36 #include "ext/standard/crc32_x86.h"
37 
38 #ifdef PHP_WIN32
39 #include "win32/php_win32_globals.h"
40 #include "win32/time.h"
41 #include "win32/ioutil.h"
42 #endif
43 
44 typedef struct yy_buffer_state *YY_BUFFER_STATE;
45 
46 #include "zend.h"
47 #include "zend_ini_scanner.h"
48 #include "zend_language_scanner.h"
49 #include <zend_language_parser.h>
50 
51 #include "zend_portability.h"
52 
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <math.h>
56 #include <time.h>
57 #include <stdio.h>
58 
59 #ifndef PHP_WIN32
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #endif
63 
64 #ifndef PHP_WIN32
65 # include <netdb.h>
66 #else
67 #include "win32/inet.h"
68 #endif
69 
70 #if HAVE_ARPA_INET_H
71 # include <arpa/inet.h>
72 #endif
73 
74 #if HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77 
78 #include <string.h>
79 #include <locale.h>
80 
81 #if HAVE_SYS_MMAN_H
82 # include <sys/mman.h>
83 #endif
84 
85 #if HAVE_SYS_LOADAVG_H
86 # include <sys/loadavg.h>
87 #endif
88 
89 #ifdef PHP_WIN32
90 # include "win32/unistd.h"
91 #endif
92 
93 #ifndef INADDR_NONE
94 #define INADDR_NONE ((zend_ulong) -1)
95 #endif
96 
97 #include "zend_globals.h"
98 #include "php_globals.h"
99 #include "SAPI.h"
100 #include "php_ticks.h"
101 
102 #ifdef ZTS
103 PHPAPI int basic_globals_id;
104 #else
105 PHPAPI php_basic_globals basic_globals;
106 #endif
107 
108 #include "php_fopen_wrappers.h"
109 #include "streamsfuncs.h"
110 #include "basic_functions_arginfo.h"
111 
112 typedef struct _user_tick_function_entry {
113 	zend_fcall_info fci;
114 	zend_fcall_info_cache fci_cache;
115 	bool calling;
116 } user_tick_function_entry;
117 
118 #if HAVE_PUTENV
119 typedef struct {
120 	char *putenv_string;
121 	char *previous_value;
122 	zend_string *key;
123 } putenv_entry;
124 #endif
125 
126 /* some prototypes for local functions */
127 static void user_shutdown_function_dtor(zval *zv);
128 static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
129 
130 static const zend_module_dep standard_deps[] = { /* {{{ */
131 	ZEND_MOD_OPTIONAL("session")
132 	ZEND_MOD_END
133 };
134 /* }}} */
135 
136 zend_module_entry basic_functions_module = { /* {{{ */
137 	STANDARD_MODULE_HEADER_EX,
138 	NULL,
139 	standard_deps,
140 	"standard",					/* extension name */
141 	ext_functions,				/* function list */
142 	PHP_MINIT(basic),			/* process startup */
143 	PHP_MSHUTDOWN(basic),		/* process shutdown */
144 	PHP_RINIT(basic),			/* request startup */
145 	PHP_RSHUTDOWN(basic),		/* request shutdown */
146 	PHP_MINFO(basic),			/* extension info */
147 	PHP_STANDARD_VERSION,		/* extension version */
148 	STANDARD_MODULE_PROPERTIES
149 };
150 /* }}} */
151 
152 #if defined(HAVE_PUTENV)
php_putenv_destructor(zval * zv)153 static void php_putenv_destructor(zval *zv) /* {{{ */
154 {
155 	putenv_entry *pe = Z_PTR_P(zv);
156 
157 	if (pe->previous_value) {
158 # if defined(PHP_WIN32)
159 		/* MSVCRT has a bug in putenv() when setting a variable that
160 		 * is already set; if the SetEnvironmentVariable() API call
161 		 * fails, the Crt will double free() a string.
162 		 * We try to avoid this by setting our own value first */
163 		SetEnvironmentVariable(ZSTR_VAL(pe->key), "bugbug");
164 # endif
165 		putenv(pe->previous_value);
166 # if defined(PHP_WIN32)
167 		efree(pe->previous_value);
168 # endif
169 	} else {
170 # if HAVE_UNSETENV
171 		unsetenv(ZSTR_VAL(pe->key));
172 # elif defined(PHP_WIN32)
173 		SetEnvironmentVariable(ZSTR_VAL(pe->key), NULL);
174 # ifndef ZTS
175 		_putenv_s(ZSTR_VAL(pe->key), "");
176 # endif
177 # else
178 		char **env;
179 
180 		for (env = environ; env != NULL && *env != NULL; env++) {
181 			if (!strncmp(*env, ZSTR_VAL(pe->key), ZSTR_LEN(pe->key))
182 					&& (*env)[ZSTR_LEN(pe->key)] == '=') {	/* found it */
183 				*env = "";
184 				break;
185 			}
186 		}
187 # endif
188 	}
189 #ifdef HAVE_TZSET
190 	/* don't forget to reset the various libc globals that
191 	 * we might have changed by an earlier call to tzset(). */
192 	if (zend_string_equals_literal_ci(pe->key, "TZ")) {
193 		tzset();
194 	}
195 #endif
196 
197 	free(pe->putenv_string);
198 	zend_string_release(pe->key);
199 	efree(pe);
200 }
201 /* }}} */
202 #endif
203 
basic_globals_ctor(php_basic_globals * basic_globals_p)204 static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */
205 {
206 	BG(mt_rand_is_seeded) = 0;
207 	BG(mt_rand_mode) = MT_RAND_MT19937;
208 	BG(umask) = -1;
209 	BG(next) = NULL;
210 	BG(left) = -1;
211 	BG(user_tick_functions) = NULL;
212 	BG(user_filter_map) = NULL;
213 	BG(serialize_lock) = 0;
214 
215 	memset(&BG(serialize), 0, sizeof(BG(serialize)));
216 	memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
217 
218 	memset(&BG(url_adapt_session_ex), 0, sizeof(BG(url_adapt_session_ex)));
219 	memset(&BG(url_adapt_output_ex), 0, sizeof(BG(url_adapt_output_ex)));
220 
221 	BG(url_adapt_session_ex).type = 1;
222 	BG(url_adapt_output_ex).type  = 0;
223 
224 	zend_hash_init(&BG(url_adapt_session_hosts_ht), 0, NULL, NULL, 1);
225 	zend_hash_init(&BG(url_adapt_output_hosts_ht), 0, NULL, NULL, 1);
226 
227 #if defined(_REENTRANT)
228 	memset(&BG(mblen_state), 0, sizeof(BG(mblen_state)));
229 #endif
230 
231 	BG(page_uid) = -1;
232 	BG(page_gid) = -1;
233 
234 	BG(syslog_device) = NULL;
235 }
236 /* }}} */
237 
basic_globals_dtor(php_basic_globals * basic_globals_p)238 static void basic_globals_dtor(php_basic_globals *basic_globals_p) /* {{{ */
239 {
240 	if (basic_globals_p->url_adapt_session_ex.tags) {
241 		zend_hash_destroy(basic_globals_p->url_adapt_session_ex.tags);
242 		free(basic_globals_p->url_adapt_session_ex.tags);
243 	}
244 	if (basic_globals_p->url_adapt_output_ex.tags) {
245 		zend_hash_destroy(basic_globals_p->url_adapt_output_ex.tags);
246 		free(basic_globals_p->url_adapt_output_ex.tags);
247 	}
248 
249 	zend_hash_destroy(&basic_globals_p->url_adapt_session_hosts_ht);
250 	zend_hash_destroy(&basic_globals_p->url_adapt_output_hosts_ht);
251 }
252 /* }}} */
253 
php_get_nan(void)254 PHPAPI double php_get_nan(void) /* {{{ */
255 {
256 	return ZEND_NAN;
257 }
258 /* }}} */
259 
php_get_inf(void)260 PHPAPI double php_get_inf(void) /* {{{ */
261 {
262 	return ZEND_INFINITY;
263 }
264 /* }}} */
265 
266 #define BASIC_MINIT_SUBMODULE(module) \
267 	if (PHP_MINIT(module)(INIT_FUNC_ARGS_PASSTHRU) != SUCCESS) {\
268 		return FAILURE; \
269 	}
270 
271 #define BASIC_RINIT_SUBMODULE(module) \
272 	PHP_RINIT(module)(INIT_FUNC_ARGS_PASSTHRU);
273 
274 #define BASIC_MINFO_SUBMODULE(module) \
275 	PHP_MINFO(module)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
276 
277 #define BASIC_RSHUTDOWN_SUBMODULE(module) \
278 	PHP_RSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
279 
280 #define BASIC_MSHUTDOWN_SUBMODULE(module) \
281 	PHP_MSHUTDOWN(module)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
282 
PHP_MINIT_FUNCTION(basic)283 PHP_MINIT_FUNCTION(basic) /* {{{ */
284 {
285 #ifdef ZTS
286 	ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
287 #ifdef PHP_WIN32
288 	ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, (ts_allocate_dtor)php_win32_core_globals_dtor );
289 #endif
290 #else
291 	basic_globals_ctor(&basic_globals);
292 #ifdef PHP_WIN32
293 	php_win32_core_globals_ctor(&the_php_win32_core_globals);
294 #endif
295 #endif
296 
297 	php_ce_incomplete_class = register_class___PHP_Incomplete_Class();
298 	php_register_incomplete_class_handlers();
299 
300 	assertion_error_ce = register_class_AssertionError(zend_ce_error);
301 
302 	REGISTER_LONG_CONSTANT("CONNECTION_ABORTED", PHP_CONNECTION_ABORTED, CONST_CS | CONST_PERSISTENT);
303 	REGISTER_LONG_CONSTANT("CONNECTION_NORMAL",  PHP_CONNECTION_NORMAL,  CONST_CS | CONST_PERSISTENT);
304 	REGISTER_LONG_CONSTANT("CONNECTION_TIMEOUT", PHP_CONNECTION_TIMEOUT, CONST_CS | CONST_PERSISTENT);
305 
306 	REGISTER_LONG_CONSTANT("INI_USER",   ZEND_INI_USER,   CONST_CS | CONST_PERSISTENT);
307 	REGISTER_LONG_CONSTANT("INI_PERDIR", ZEND_INI_PERDIR, CONST_CS | CONST_PERSISTENT);
308 	REGISTER_LONG_CONSTANT("INI_SYSTEM", ZEND_INI_SYSTEM, CONST_CS | CONST_PERSISTENT);
309 	REGISTER_LONG_CONSTANT("INI_ALL",    ZEND_INI_ALL,    CONST_CS | CONST_PERSISTENT);
310 
311 	REGISTER_LONG_CONSTANT("INI_SCANNER_NORMAL", ZEND_INI_SCANNER_NORMAL, CONST_CS | CONST_PERSISTENT);
312 	REGISTER_LONG_CONSTANT("INI_SCANNER_RAW",    ZEND_INI_SCANNER_RAW,    CONST_CS | CONST_PERSISTENT);
313 	REGISTER_LONG_CONSTANT("INI_SCANNER_TYPED",  ZEND_INI_SCANNER_TYPED,  CONST_CS | CONST_PERSISTENT);
314 
315 	REGISTER_LONG_CONSTANT("PHP_URL_SCHEME", PHP_URL_SCHEME, CONST_CS | CONST_PERSISTENT);
316 	REGISTER_LONG_CONSTANT("PHP_URL_HOST", PHP_URL_HOST, CONST_CS | CONST_PERSISTENT);
317 	REGISTER_LONG_CONSTANT("PHP_URL_PORT", PHP_URL_PORT, CONST_CS | CONST_PERSISTENT);
318 	REGISTER_LONG_CONSTANT("PHP_URL_USER", PHP_URL_USER, CONST_CS | CONST_PERSISTENT);
319 	REGISTER_LONG_CONSTANT("PHP_URL_PASS", PHP_URL_PASS, CONST_CS | CONST_PERSISTENT);
320 	REGISTER_LONG_CONSTANT("PHP_URL_PATH", PHP_URL_PATH, CONST_CS | CONST_PERSISTENT);
321 	REGISTER_LONG_CONSTANT("PHP_URL_QUERY", PHP_URL_QUERY, CONST_CS | CONST_PERSISTENT);
322 	REGISTER_LONG_CONSTANT("PHP_URL_FRAGMENT", PHP_URL_FRAGMENT, CONST_CS | CONST_PERSISTENT);
323 	REGISTER_LONG_CONSTANT("PHP_QUERY_RFC1738", PHP_QUERY_RFC1738, CONST_CS | CONST_PERSISTENT);
324 	REGISTER_LONG_CONSTANT("PHP_QUERY_RFC3986", PHP_QUERY_RFC3986, CONST_CS | CONST_PERSISTENT);
325 
326 #define REGISTER_MATH_CONSTANT(x)  REGISTER_DOUBLE_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
327 	REGISTER_MATH_CONSTANT(M_E);
328 	REGISTER_MATH_CONSTANT(M_LOG2E);
329 	REGISTER_MATH_CONSTANT(M_LOG10E);
330 	REGISTER_MATH_CONSTANT(M_LN2);
331 	REGISTER_MATH_CONSTANT(M_LN10);
332 	REGISTER_MATH_CONSTANT(M_PI);
333 	REGISTER_MATH_CONSTANT(M_PI_2);
334 	REGISTER_MATH_CONSTANT(M_PI_4);
335 	REGISTER_MATH_CONSTANT(M_1_PI);
336 	REGISTER_MATH_CONSTANT(M_2_PI);
337 	REGISTER_MATH_CONSTANT(M_SQRTPI);
338 	REGISTER_MATH_CONSTANT(M_2_SQRTPI);
339 	REGISTER_MATH_CONSTANT(M_LNPI);
340 	REGISTER_MATH_CONSTANT(M_EULER);
341 	REGISTER_MATH_CONSTANT(M_SQRT2);
342 	REGISTER_MATH_CONSTANT(M_SQRT1_2);
343 	REGISTER_MATH_CONSTANT(M_SQRT3);
344 	REGISTER_DOUBLE_CONSTANT("INF", ZEND_INFINITY, CONST_CS | CONST_PERSISTENT);
345 	REGISTER_DOUBLE_CONSTANT("NAN", ZEND_NAN, CONST_CS | CONST_PERSISTENT);
346 
347 	REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_UP", PHP_ROUND_HALF_UP, CONST_CS | CONST_PERSISTENT);
348 	REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_DOWN", PHP_ROUND_HALF_DOWN, CONST_CS | CONST_PERSISTENT);
349 	REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_EVEN", PHP_ROUND_HALF_EVEN, CONST_CS | CONST_PERSISTENT);
350 	REGISTER_LONG_CONSTANT("PHP_ROUND_HALF_ODD", PHP_ROUND_HALF_ODD, CONST_CS | CONST_PERSISTENT);
351 
352 #if ENABLE_TEST_CLASS
353 	test_class_startup();
354 #endif
355 
356 	register_phpinfo_constants(INIT_FUNC_ARGS_PASSTHRU);
357 	register_html_constants(INIT_FUNC_ARGS_PASSTHRU);
358 	register_string_constants(INIT_FUNC_ARGS_PASSTHRU);
359 
360 	BASIC_MINIT_SUBMODULE(var)
361 	BASIC_MINIT_SUBMODULE(file)
362 	BASIC_MINIT_SUBMODULE(pack)
363 	BASIC_MINIT_SUBMODULE(browscap)
364 	BASIC_MINIT_SUBMODULE(standard_filters)
365 	BASIC_MINIT_SUBMODULE(user_filters)
366 	BASIC_MINIT_SUBMODULE(password)
367 	BASIC_MINIT_SUBMODULE(mt_rand)
368 
369 #if defined(ZTS)
370 	BASIC_MINIT_SUBMODULE(localeconv)
371 #endif
372 
373 #if defined(HAVE_NL_LANGINFO)
374 	BASIC_MINIT_SUBMODULE(nl_langinfo)
375 #endif
376 
377 #if ZEND_INTRIN_SSE4_2_FUNC_PTR
378 	BASIC_MINIT_SUBMODULE(string_intrin)
379 #endif
380 
381 #if ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PTR
382 	BASIC_MINIT_SUBMODULE(crc32_x86_intrin)
383 #endif
384 
385 #if ZEND_INTRIN_AVX2_FUNC_PTR || ZEND_INTRIN_SSSE3_FUNC_PTR
386 	BASIC_MINIT_SUBMODULE(base64_intrin)
387 #endif
388 
389 	BASIC_MINIT_SUBMODULE(crypt)
390 	BASIC_MINIT_SUBMODULE(lcg)
391 
392 	BASIC_MINIT_SUBMODULE(dir)
393 #ifdef HAVE_SYSLOG_H
394 	BASIC_MINIT_SUBMODULE(syslog)
395 #endif
396 	BASIC_MINIT_SUBMODULE(array)
397 	BASIC_MINIT_SUBMODULE(assert)
398 	BASIC_MINIT_SUBMODULE(url_scanner_ex)
399 #ifdef PHP_CAN_SUPPORT_PROC_OPEN
400 	BASIC_MINIT_SUBMODULE(proc_open)
401 #endif
402 	BASIC_MINIT_SUBMODULE(exec)
403 
404 	BASIC_MINIT_SUBMODULE(user_streams)
405 	BASIC_MINIT_SUBMODULE(imagetypes)
406 
407 	php_register_url_stream_wrapper("php", &php_stream_php_wrapper);
408 	php_register_url_stream_wrapper("file", &php_plain_files_wrapper);
409 #ifdef HAVE_GLOB
410 	php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper);
411 #endif
412 	php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper);
413 	php_register_url_stream_wrapper("http", &php_stream_http_wrapper);
414 	php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper);
415 
416 #if defined(PHP_WIN32) || HAVE_DNS_SEARCH_FUNC
417 # if defined(PHP_WIN32) || HAVE_FULL_DNS_FUNCS
418 	BASIC_MINIT_SUBMODULE(dns)
419 # endif
420 #endif
421 
422 	BASIC_MINIT_SUBMODULE(random)
423 
424 	BASIC_MINIT_SUBMODULE(hrtime)
425 
426 	return SUCCESS;
427 }
428 /* }}} */
429 
PHP_MSHUTDOWN_FUNCTION(basic)430 PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
431 {
432 #ifdef ZTS
433 	ts_free_id(basic_globals_id);
434 #ifdef PHP_WIN32
435 	ts_free_id(php_win32_core_globals_id);
436 #endif
437 #else
438 	basic_globals_dtor(&basic_globals);
439 #ifdef PHP_WIN32
440 	php_win32_core_globals_dtor(&the_php_win32_core_globals);
441 #endif
442 #endif
443 
444 	php_unregister_url_stream_wrapper("php");
445 	php_unregister_url_stream_wrapper("http");
446 	php_unregister_url_stream_wrapper("ftp");
447 
448 	BASIC_MSHUTDOWN_SUBMODULE(browscap)
449 	BASIC_MSHUTDOWN_SUBMODULE(array)
450 	BASIC_MSHUTDOWN_SUBMODULE(assert)
451 	BASIC_MSHUTDOWN_SUBMODULE(url_scanner_ex)
452 	BASIC_MSHUTDOWN_SUBMODULE(file)
453 	BASIC_MSHUTDOWN_SUBMODULE(standard_filters)
454 #if defined(ZTS)
455 	BASIC_MSHUTDOWN_SUBMODULE(localeconv)
456 #endif
457 	BASIC_MSHUTDOWN_SUBMODULE(crypt)
458 	BASIC_MSHUTDOWN_SUBMODULE(random)
459 	BASIC_MSHUTDOWN_SUBMODULE(password)
460 
461 	return SUCCESS;
462 }
463 /* }}} */
464 
PHP_RINIT_FUNCTION(basic)465 PHP_RINIT_FUNCTION(basic) /* {{{ */
466 {
467 	memset(BG(strtok_table), 0, 256);
468 
469 	BG(serialize_lock) = 0;
470 	memset(&BG(serialize), 0, sizeof(BG(serialize)));
471 	memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
472 
473 	BG(strtok_string) = NULL;
474 	BG(strtok_last) = NULL;
475 	BG(ctype_string) = NULL;
476 	BG(locale_changed) = 0;
477 	BG(user_compare_fci) = empty_fcall_info;
478 	BG(user_compare_fci_cache) = empty_fcall_info_cache;
479 	BG(page_uid) = -1;
480 	BG(page_gid) = -1;
481 	BG(page_inode) = -1;
482 	BG(page_mtime) = -1;
483 #ifdef HAVE_PUTENV
484 	zend_hash_init(&BG(putenv_ht), 1, NULL, php_putenv_destructor, 0);
485 #endif
486 	BG(user_shutdown_function_names) = NULL;
487 
488 	PHP_RINIT(filestat)(INIT_FUNC_ARGS_PASSTHRU);
489 	BASIC_RINIT_SUBMODULE(dir)
490 	BASIC_RINIT_SUBMODULE(url_scanner_ex)
491 
492 	/* Setup default context */
493 	FG(default_context) = NULL;
494 
495 	/* Default to global wrappers only */
496 	FG(stream_wrappers) = NULL;
497 
498 	/* Default to global filters only */
499 	FG(stream_filters) = NULL;
500 
501 	return SUCCESS;
502 }
503 /* }}} */
504 
PHP_RSHUTDOWN_FUNCTION(basic)505 PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
506 {
507 	if (BG(strtok_string)) {
508 		zend_string_release(BG(strtok_string));
509 		BG(strtok_string) = NULL;
510 	}
511 #ifdef HAVE_PUTENV
512 	tsrm_env_lock();
513 	zend_hash_destroy(&BG(putenv_ht));
514 	tsrm_env_unlock();
515 #endif
516 
517 	BG(mt_rand_is_seeded) = 0;
518 
519 	if (BG(umask) != -1) {
520 		umask(BG(umask));
521 	}
522 
523 	/* Check if locale was changed and change it back
524 	 * to the value in startup environment */
525 	if (BG(locale_changed)) {
526 		setlocale(LC_ALL, "C");
527 		zend_reset_lc_ctype_locale();
528 		zend_update_current_locale();
529 		if (BG(ctype_string)) {
530 			zend_string_release_ex(BG(ctype_string), 0);
531 			BG(ctype_string) = NULL;
532 		}
533 	}
534 
535 	/* FG(stream_wrappers) and FG(stream_filters) are destroyed
536 	 * during php_request_shutdown() */
537 
538 	PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
539 #ifdef HAVE_SYSLOG_H
540 	BASIC_RSHUTDOWN_SUBMODULE(syslog);
541 #endif
542 	BASIC_RSHUTDOWN_SUBMODULE(assert)
543 	BASIC_RSHUTDOWN_SUBMODULE(url_scanner_ex)
544 	BASIC_RSHUTDOWN_SUBMODULE(streams)
545 #ifdef PHP_WIN32
546 	BASIC_RSHUTDOWN_SUBMODULE(win32_core_globals)
547 #endif
548 
549 	if (BG(user_tick_functions)) {
550 		zend_llist_destroy(BG(user_tick_functions));
551 		efree(BG(user_tick_functions));
552 		BG(user_tick_functions) = NULL;
553 	}
554 
555 	BASIC_RSHUTDOWN_SUBMODULE(user_filters)
556 	BASIC_RSHUTDOWN_SUBMODULE(browscap)
557 
558 	BG(page_uid) = -1;
559 	BG(page_gid) = -1;
560 	return SUCCESS;
561 }
562 /* }}} */
563 
PHP_MINFO_FUNCTION(basic)564 PHP_MINFO_FUNCTION(basic) /* {{{ */
565 {
566 	php_info_print_table_start();
567 	BASIC_MINFO_SUBMODULE(dl)
568 	BASIC_MINFO_SUBMODULE(mail)
569 	php_info_print_table_end();
570 	BASIC_MINFO_SUBMODULE(assert)
571 }
572 /* }}} */
573 
574 /* {{{ Given the name of a constant this function will return the constant's associated value */
PHP_FUNCTION(constant)575 PHP_FUNCTION(constant)
576 {
577 	zend_string *const_name;
578 	zval *c;
579 	zend_class_entry *scope;
580 
581 	ZEND_PARSE_PARAMETERS_START(1, 1)
582 		Z_PARAM_STR(const_name)
583 	ZEND_PARSE_PARAMETERS_END();
584 
585 	scope = zend_get_executed_scope();
586 	c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_EXCEPTION);
587 	if (!c) {
588 		RETURN_THROWS();
589 	}
590 
591 	ZVAL_COPY_OR_DUP(return_value, c);
592 	if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
593 		if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) {
594 			RETURN_THROWS();
595 		}
596 	}
597 }
598 /* }}} */
599 
600 #ifdef HAVE_INET_NTOP
601 /* {{{ Converts a packed inet address to a human readable IP address string */
PHP_FUNCTION(inet_ntop)602 PHP_FUNCTION(inet_ntop)
603 {
604 	char *address;
605 	size_t address_len;
606 	int af = AF_INET;
607 	char buffer[40];
608 
609 	ZEND_PARSE_PARAMETERS_START(1, 1)
610 		Z_PARAM_STRING(address, address_len)
611 	ZEND_PARSE_PARAMETERS_END();
612 
613 #ifdef HAVE_IPV6
614 	if (address_len == 16) {
615 		af = AF_INET6;
616 	} else
617 #endif
618 	if (address_len != 4) {
619 		RETURN_FALSE;
620 	}
621 
622 	if (!inet_ntop(af, address, buffer, sizeof(buffer))) {
623 		RETURN_FALSE;
624 	}
625 
626 	RETURN_STRING(buffer);
627 }
628 /* }}} */
629 #endif /* HAVE_INET_NTOP */
630 
631 #ifdef HAVE_INET_PTON
632 /* {{{ Converts a human readable IP address to a packed binary string */
PHP_FUNCTION(inet_pton)633 PHP_FUNCTION(inet_pton)
634 {
635 	int ret, af = AF_INET;
636 	char *address;
637 	size_t address_len;
638 	char buffer[17];
639 
640 	ZEND_PARSE_PARAMETERS_START(1, 1)
641 		Z_PARAM_STRING(address, address_len)
642 	ZEND_PARSE_PARAMETERS_END();
643 
644 	memset(buffer, 0, sizeof(buffer));
645 
646 #ifdef HAVE_IPV6
647 	if (strchr(address, ':')) {
648 		af = AF_INET6;
649 	} else
650 #endif
651 	if (!strchr(address, '.')) {
652 		RETURN_FALSE;
653 	}
654 
655 	ret = inet_pton(af, address, buffer);
656 
657 	if (ret <= 0) {
658 		RETURN_FALSE;
659 	}
660 
661 	RETURN_STRINGL(buffer, af == AF_INET ? 4 : 16);
662 }
663 /* }}} */
664 #endif /* HAVE_INET_PTON */
665 
666 /* {{{ Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address */
PHP_FUNCTION(ip2long)667 PHP_FUNCTION(ip2long)
668 {
669 	char *addr;
670 	size_t addr_len;
671 #ifdef HAVE_INET_PTON
672 	struct in_addr ip;
673 #else
674 	zend_ulong ip;
675 #endif
676 
677 	ZEND_PARSE_PARAMETERS_START(1, 1)
678 		Z_PARAM_STRING(addr, addr_len)
679 	ZEND_PARSE_PARAMETERS_END();
680 
681 #ifdef HAVE_INET_PTON
682 	if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) {
683 		RETURN_FALSE;
684 	}
685 	RETURN_LONG(ntohl(ip.s_addr));
686 #else
687 	if (addr_len == 0 || (ip = inet_addr(addr)) == INADDR_NONE) {
688 		/* The only special case when we should return -1 ourselves,
689 		 * because inet_addr() considers it wrong. We return 0xFFFFFFFF and
690 		 * not -1 or ~0 because of 32/64bit issues. */
691 		if (addr_len == sizeof("255.255.255.255") - 1 &&
692 			!memcmp(addr, "255.255.255.255", sizeof("255.255.255.255") - 1)
693 		) {
694 			RETURN_LONG(0xFFFFFFFF);
695 		}
696 		RETURN_FALSE;
697 	}
698 	RETURN_LONG(ntohl(ip));
699 #endif
700 }
701 /* }}} */
702 
703 /* {{{ Converts an (IPv4) Internet network address into a string in Internet standard dotted format */
PHP_FUNCTION(long2ip)704 PHP_FUNCTION(long2ip)
705 {
706 	zend_ulong ip;
707 	zend_long sip;
708 	struct in_addr myaddr;
709 #ifdef HAVE_INET_PTON
710 	char str[40];
711 #endif
712 
713 	ZEND_PARSE_PARAMETERS_START(1, 1)
714 		Z_PARAM_LONG(sip)
715 	ZEND_PARSE_PARAMETERS_END();
716 
717 	/* autoboxes on 32bit platforms, but that's expected */
718 	ip = (zend_ulong)sip;
719 
720 	myaddr.s_addr = htonl(ip);
721 #ifdef HAVE_INET_PTON
722 	if (inet_ntop(AF_INET, &myaddr, str, sizeof(str))) {
723 		RETURN_STRING(str);
724 	} else {
725 		RETURN_FALSE;
726 	}
727 #else
728 	RETURN_STRING(inet_ntoa(myaddr));
729 #endif
730 }
731 /* }}} */
732 
733 /********************
734  * System Functions *
735  ********************/
736 
php_getenv(const char * str,size_t str_len)737 PHPAPI zend_string *php_getenv(const char *str, size_t str_len) {
738 #ifdef PHP_WIN32
739 	{
740 		wchar_t *keyw = php_win32_cp_conv_any_to_w(str, str_len, PHP_WIN32_CP_IGNORE_LEN_P);
741 		if (!keyw) {
742 			return NULL;
743 		}
744 
745 		SetLastError(0);
746 		/* If the given buffer is not large enough to hold the data, the return value is
747 		 * the buffer size,  in characters, required to hold the string and its terminating
748 		 * null character. We use this return value to alloc the final buffer. */
749 		wchar_t dummybuf;
750 		DWORD size = GetEnvironmentVariableW(keyw, &dummybuf, 0);
751 		if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
752 			/* The environment variable doesn't exist. */
753 			free(keyw);
754 			return NULL;
755 		}
756 
757 		if (size == 0) {
758 			/* env exists, but it is empty */
759 			free(keyw);
760 			return ZSTR_EMPTY_ALLOC();
761 		}
762 
763 		wchar_t *valw = emalloc((size + 1) * sizeof(wchar_t));
764 		size = GetEnvironmentVariableW(keyw, valw, size);
765 		if (size == 0) {
766 			/* has been removed between the two calls */
767 			free(keyw);
768 			efree(valw);
769 			return ZSTR_EMPTY_ALLOC();
770 		} else {
771 			char *ptr = php_win32_cp_w_to_any(valw);
772 			zend_string *result = zend_string_init(ptr, strlen(ptr), 0);
773 			free(ptr);
774 			free(keyw);
775 			efree(valw);
776 			return result;
777 		}
778 	}
779 #else
780 	tsrm_env_lock();
781 
782 	/* system method returns a const */
783 	char *ptr = getenv(str);
784 	zend_string *result = NULL;
785 	if (ptr) {
786 		result = zend_string_init(ptr, strlen(ptr), 0);
787 	}
788 
789 	tsrm_env_unlock();
790 	return result;
791 #endif
792 }
793 
794 /* {{{ Get the value of an environment variable or every available environment variable
795    if no varname is present  */
PHP_FUNCTION(getenv)796 PHP_FUNCTION(getenv)
797 {
798 	char *str = NULL;
799 	size_t str_len;
800 	bool local_only = 0;
801 
802 	ZEND_PARSE_PARAMETERS_START(0, 2)
803 		Z_PARAM_OPTIONAL
804 		Z_PARAM_STRING_OR_NULL(str, str_len)
805 		Z_PARAM_BOOL(local_only)
806 	ZEND_PARSE_PARAMETERS_END();
807 
808 	if (!str) {
809 		array_init(return_value);
810 		php_import_environment_variables(return_value);
811 		return;
812 	}
813 
814 	if (!local_only) {
815 		/* SAPI method returns an emalloc()'d string */
816 		char *ptr = sapi_getenv(str, str_len);
817 		if (ptr) {
818 			// TODO: avoid reallocation ???
819 			RETVAL_STRING(ptr);
820 			efree(ptr);
821 			return;
822 		}
823 	}
824 
825 	zend_string *res = php_getenv(str, str_len);
826 	if (res) {
827 		RETURN_STR(res);
828 	}
829 	RETURN_FALSE;
830 }
831 /* }}} */
832 
833 #ifdef HAVE_PUTENV
834 /* {{{ Set the value of an environment variable */
PHP_FUNCTION(putenv)835 PHP_FUNCTION(putenv)
836 {
837 	char *setting;
838 	size_t setting_len;
839 	char *p, **env;
840 	putenv_entry pe;
841 #ifdef PHP_WIN32
842 	const char *value = NULL;
843 	int error_code;
844 #endif
845 
846 	ZEND_PARSE_PARAMETERS_START(1, 1)
847 		Z_PARAM_STRING(setting, setting_len)
848 	ZEND_PARSE_PARAMETERS_END();
849 
850 	if (setting_len == 0 || setting[0] == '=') {
851 		zend_argument_value_error(1, "must have a valid syntax");
852 		RETURN_THROWS();
853 	}
854 
855 	pe.putenv_string = zend_strndup(setting, setting_len);
856 	if ((p = strchr(setting, '='))) {
857 		pe.key = zend_string_init(setting, p - setting, 0);
858 #ifdef PHP_WIN32
859 		value = p + 1;
860 #endif
861 	} else {
862 		pe.key = zend_string_init(setting, setting_len, 0);
863 	}
864 
865 	tsrm_env_lock();
866 	zend_hash_del(&BG(putenv_ht), pe.key);
867 
868 	/* find previous value */
869 	pe.previous_value = NULL;
870 	for (env = environ; env != NULL && *env != NULL; env++) {
871 		if (!strncmp(*env, ZSTR_VAL(pe.key), ZSTR_LEN(pe.key))
872 				&& (*env)[ZSTR_LEN(pe.key)] == '=') {	/* found it */
873 #if defined(PHP_WIN32)
874 			/* must copy previous value because MSVCRT's putenv can free the string without notice */
875 			pe.previous_value = estrdup(*env);
876 #else
877 			pe.previous_value = *env;
878 #endif
879 			break;
880 		}
881 	}
882 
883 #if HAVE_UNSETENV
884 	if (!p) { /* no '=' means we want to unset it */
885 		unsetenv(pe.putenv_string);
886 	}
887 	if (!p || putenv(pe.putenv_string) == 0) { /* success */
888 #else
889 # ifndef PHP_WIN32
890 	if (putenv(pe.putenv_string) == 0) { /* success */
891 # else
892 		wchar_t *keyw, *valw = NULL;
893 
894 		keyw = php_win32_cp_any_to_w(ZSTR_VAL(pe.key));
895 		if (value) {
896 			valw = php_win32_cp_any_to_w(value);
897 		}
898 		/* valw may be NULL, but the failed conversion still needs to be checked. */
899 		if (!keyw || !valw && value) {
900 			tsrm_env_unlock();
901 			free(pe.putenv_string);
902 			zend_string_release(pe.key);
903 			free(keyw);
904 			free(valw);
905 			RETURN_FALSE;
906 		}
907 
908 	error_code = SetEnvironmentVariableW(keyw, valw);
909 
910 	if (error_code != 0
911 # ifndef ZTS
912 	/* We need both SetEnvironmentVariable and _putenv here as some
913 		dependency lib could use either way to read the environment.
914 		Obviously the CRT version will be useful more often. But
915 		generally, doing both brings us on the safe track at least
916 		in NTS build. */
917 	&& _wputenv_s(keyw, valw ? valw : L"") == 0
918 # endif
919 	) { /* success */
920 # endif
921 #endif
922 		zend_hash_add_mem(&BG(putenv_ht), pe.key, &pe, sizeof(putenv_entry));
923 #ifdef HAVE_TZSET
924 		if (zend_string_equals_literal_ci(pe.key, "TZ")) {
925 			tzset();
926 		}
927 #endif
928 		tsrm_env_unlock();
929 #if defined(PHP_WIN32)
930 		free(keyw);
931 		free(valw);
932 #endif
933 		RETURN_TRUE;
934 	} else {
935 		free(pe.putenv_string);
936 		zend_string_release(pe.key);
937 #if defined(PHP_WIN32)
938 		free(keyw);
939 		free(valw);
940 #endif
941 		RETURN_FALSE;
942 	}
943 }
944 /* }}} */
945 #endif
946 
947 /* {{{ free_argv()
948    Free the memory allocated to an argv array. */
949 static void free_argv(char **argv, int argc)
950 {
951 	int i;
952 
953 	if (argv) {
954 		for (i = 0; i < argc; i++) {
955 			if (argv[i]) {
956 				efree(argv[i]);
957 			}
958 		}
959 		efree(argv);
960 	}
961 }
962 /* }}} */
963 
964 /* {{{ free_longopts()
965    Free the memory allocated to an longopt array. */
966 static void free_longopts(opt_struct *longopts)
967 {
968 	opt_struct *p;
969 
970 	if (longopts) {
971 		for (p = longopts; p && p->opt_char != '-'; p++) {
972 			if (p->opt_name != NULL) {
973 				efree((char *)(p->opt_name));
974 			}
975 		}
976 	}
977 }
978 /* }}} */
979 
980 /* {{{ parse_opts()
981    Convert the typical getopt input characters to the php_getopt struct array */
982 static int parse_opts(char * opts, opt_struct ** result)
983 {
984 	opt_struct * paras = NULL;
985 	unsigned int i, count = 0;
986 	unsigned int opts_len = (unsigned int)strlen(opts);
987 
988 	for (i = 0; i < opts_len; i++) {
989 		if ((opts[i] >= 48 && opts[i] <= 57) ||
990 			(opts[i] >= 65 && opts[i] <= 90) ||
991 			(opts[i] >= 97 && opts[i] <= 122)
992 		) {
993 			count++;
994 		}
995 	}
996 
997 	paras = safe_emalloc(sizeof(opt_struct), count, 0);
998 	memset(paras, 0, sizeof(opt_struct) * count);
999 	*result = paras;
1000 	while ( (*opts >= 48 && *opts <= 57) || /* 0 - 9 */
1001 			(*opts >= 65 && *opts <= 90) || /* A - Z */
1002 			(*opts >= 97 && *opts <= 122)   /* a - z */
1003 	) {
1004 		paras->opt_char = *opts;
1005 		paras->need_param = *(++opts) == ':';
1006 		paras->opt_name = NULL;
1007 		if (paras->need_param == 1) {
1008 			opts++;
1009 			if (*opts == ':') {
1010 				paras->need_param++;
1011 				opts++;
1012 			}
1013 		}
1014 		paras++;
1015 	}
1016 	return count;
1017 }
1018 /* }}} */
1019 
1020 /* {{{ Get options from the command line argument list */
1021 PHP_FUNCTION(getopt)
1022 {
1023 	char *options = NULL, **argv = NULL;
1024 	char opt[2] = { '\0' };
1025 	char *optname;
1026 	int argc = 0, o;
1027 	size_t options_len = 0, len;
1028 	char *php_optarg = NULL;
1029 	int php_optind = 1;
1030 	zval val, *args = NULL, *p_longopts = NULL;
1031 	zval *zoptind = NULL;
1032 	size_t optname_len = 0;
1033 	opt_struct *opts, *orig_opts;
1034 
1035 	ZEND_PARSE_PARAMETERS_START(1, 3)
1036 		Z_PARAM_STRING(options, options_len)
1037 		Z_PARAM_OPTIONAL
1038 		Z_PARAM_ARRAY(p_longopts)
1039 		Z_PARAM_ZVAL(zoptind)
1040 	ZEND_PARSE_PARAMETERS_END();
1041 
1042 	/* Init zoptind to 1 */
1043 	if (zoptind) {
1044 		ZEND_TRY_ASSIGN_REF_LONG(zoptind, 1);
1045 	}
1046 
1047 	/* Get argv from the global symbol table. We calculate argc ourselves
1048 	 * in order to be on the safe side, even though it is also available
1049 	 * from the symbol table. */
1050 	if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER))) &&
1051 		((args = zend_hash_find_ex_ind(Z_ARRVAL_P(&PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL ||
1052 		(args = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL)
1053 	) {
1054 		int pos = 0;
1055 		zval *entry;
1056 
1057 		if (Z_TYPE_P(args) != IS_ARRAY) {
1058 			RETURN_FALSE;
1059 		}
1060 		argc = zend_hash_num_elements(Z_ARRVAL_P(args));
1061 
1062 		/* Attempt to allocate enough memory to hold all of the arguments
1063 		 * and a trailing NULL */
1064 		argv = (char **) safe_emalloc(sizeof(char *), (argc + 1), 0);
1065 
1066 		/* Iterate over the hash to construct the argv array. */
1067 		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), entry) {
1068 			zend_string *tmp_arg_str;
1069 			zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
1070 
1071 			argv[pos++] = estrdup(ZSTR_VAL(arg_str));
1072 
1073 			zend_tmp_string_release(tmp_arg_str);
1074 		} ZEND_HASH_FOREACH_END();
1075 
1076 		/* The C Standard requires argv[argc] to be NULL - this might
1077 		 * keep some getopt implementations happy. */
1078 		argv[argc] = NULL;
1079 	} else {
1080 		/* Return false if we can't find argv. */
1081 		RETURN_FALSE;
1082 	}
1083 
1084 	len = parse_opts(options, &opts);
1085 
1086 	if (p_longopts) {
1087 		int count;
1088 		zval *entry;
1089 
1090 		count = zend_hash_num_elements(Z_ARRVAL_P(p_longopts));
1091 
1092 		/* the first <len> slots are filled by the one short ops
1093 		 * we now extend our array and jump to the new added structs */
1094 		opts = (opt_struct *) erealloc(opts, sizeof(opt_struct) * (len + count + 1));
1095 		orig_opts = opts;
1096 		opts += len;
1097 
1098 		memset(opts, 0, count * sizeof(opt_struct));
1099 
1100 		/* Iterate over the hash to construct the argv array. */
1101 		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(p_longopts), entry) {
1102 			zend_string *tmp_arg_str;
1103 			zend_string *arg_str = zval_get_tmp_string(entry, &tmp_arg_str);
1104 
1105 			opts->need_param = 0;
1106 			opts->opt_name = estrdup(ZSTR_VAL(arg_str));
1107 			len = strlen(opts->opt_name);
1108 			if ((len > 0) && (opts->opt_name[len - 1] == ':')) {
1109 				opts->need_param++;
1110 				opts->opt_name[len - 1] = '\0';
1111 				if ((len > 1) && (opts->opt_name[len - 2] == ':')) {
1112 					opts->need_param++;
1113 					opts->opt_name[len - 2] = '\0';
1114 				}
1115 			}
1116 			opts->opt_char = 0;
1117 			opts++;
1118 
1119 			zend_tmp_string_release(tmp_arg_str);
1120 		} ZEND_HASH_FOREACH_END();
1121 	} else {
1122 		opts = (opt_struct*) erealloc(opts, sizeof(opt_struct) * (len + 1));
1123 		orig_opts = opts;
1124 		opts += len;
1125 	}
1126 
1127 	/* php_getopt want to identify the last param */
1128 	opts->opt_char   = '-';
1129 	opts->need_param = 0;
1130 	opts->opt_name   = NULL;
1131 
1132 	/* Initialize the return value as an array. */
1133 	array_init(return_value);
1134 
1135 	/* after our pointer arithmetic jump back to the first element */
1136 	opts = orig_opts;
1137 
1138 	while ((o = php_getopt(argc, argv, opts, &php_optarg, &php_optind, 0, 1)) != -1) {
1139 		/* Skip unknown arguments. */
1140 		if (o == PHP_GETOPT_INVALID_ARG) {
1141 			continue;
1142 		}
1143 
1144 		/* Prepare the option character and the argument string. */
1145 		if (o == 0) {
1146 			optname = opts[php_optidx].opt_name;
1147 		} else {
1148 			if (o == 1) {
1149 				o = '-';
1150 			}
1151 			opt[0] = o;
1152 			optname = opt;
1153 		}
1154 
1155 		if (php_optarg != NULL) {
1156 			/* keep the arg as binary, since the encoding is not known */
1157 			ZVAL_STRING(&val, php_optarg);
1158 		} else {
1159 			ZVAL_FALSE(&val);
1160 		}
1161 
1162 		/* Add this option / argument pair to the result hash. */
1163 		optname_len = strlen(optname);
1164 		if (!(optname_len > 1 && optname[0] == '0') && is_numeric_string(optname, optname_len, NULL, NULL, 0) == IS_LONG) {
1165 			/* numeric string */
1166 			int optname_int = atoi(optname);
1167 			if ((args = zend_hash_index_find(Z_ARRVAL_P(return_value), optname_int)) != NULL) {
1168 				if (Z_TYPE_P(args) != IS_ARRAY) {
1169 					convert_to_array(args);
1170 				}
1171 				zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1172 			} else {
1173 				zend_hash_index_update(Z_ARRVAL_P(return_value), optname_int, &val);
1174 			}
1175 		} else {
1176 			/* other strings */
1177 			if ((args = zend_hash_str_find(Z_ARRVAL_P(return_value), optname, strlen(optname))) != NULL) {
1178 				if (Z_TYPE_P(args) != IS_ARRAY) {
1179 					convert_to_array(args);
1180 				}
1181 				zend_hash_next_index_insert(Z_ARRVAL_P(args), &val);
1182 			} else {
1183 				zend_hash_str_add(Z_ARRVAL_P(return_value), optname, strlen(optname), &val);
1184 			}
1185 		}
1186 
1187 		php_optarg = NULL;
1188 	}
1189 
1190 	/* Set zoptind to php_optind */
1191 	if (zoptind) {
1192 		ZEND_TRY_ASSIGN_REF_LONG(zoptind, php_optind);
1193 	}
1194 
1195 	free_longopts(orig_opts);
1196 	efree(orig_opts);
1197 	free_argv(argv, argc);
1198 }
1199 /* }}} */
1200 
1201 /* {{{ Flush the output buffer */
1202 PHP_FUNCTION(flush)
1203 {
1204 	ZEND_PARSE_PARAMETERS_NONE();
1205 
1206 	sapi_flush();
1207 }
1208 /* }}} */
1209 
1210 /* {{{ Delay for a given number of seconds */
1211 PHP_FUNCTION(sleep)
1212 {
1213 	zend_long num;
1214 
1215 	ZEND_PARSE_PARAMETERS_START(1, 1)
1216 		Z_PARAM_LONG(num)
1217 	ZEND_PARSE_PARAMETERS_END();
1218 
1219 	if (num < 0) {
1220 		zend_argument_value_error(1, "must be greater than or equal to 0");
1221 		RETURN_THROWS();
1222 	}
1223 
1224 	RETURN_LONG(php_sleep((unsigned int)num));
1225 }
1226 /* }}} */
1227 
1228 /* {{{ Delay for a given number of micro seconds */
1229 PHP_FUNCTION(usleep)
1230 {
1231 	zend_long num;
1232 
1233 	ZEND_PARSE_PARAMETERS_START(1, 1)
1234 		Z_PARAM_LONG(num)
1235 	ZEND_PARSE_PARAMETERS_END();
1236 
1237 	if (num < 0) {
1238 		zend_argument_value_error(1, "must be greater than or equal to 0");
1239 		RETURN_THROWS();
1240 	}
1241 
1242 #if HAVE_USLEEP
1243 	usleep((unsigned int)num);
1244 #endif
1245 }
1246 /* }}} */
1247 
1248 #if HAVE_NANOSLEEP
1249 /* {{{ Delay for a number of seconds and nano seconds */
1250 PHP_FUNCTION(time_nanosleep)
1251 {
1252 	zend_long tv_sec, tv_nsec;
1253 	struct timespec php_req, php_rem;
1254 
1255 	ZEND_PARSE_PARAMETERS_START(2, 2)
1256 		Z_PARAM_LONG(tv_sec)
1257 		Z_PARAM_LONG(tv_nsec)
1258 	ZEND_PARSE_PARAMETERS_END();
1259 
1260 	if (tv_sec < 0) {
1261 		zend_argument_value_error(1, "must be greater than or equal to 0");
1262 		RETURN_THROWS();
1263 	}
1264 	if (tv_nsec < 0) {
1265 		zend_argument_value_error(2, "must be greater than or equal to 0");
1266 		RETURN_THROWS();
1267 	}
1268 
1269 	php_req.tv_sec = (time_t) tv_sec;
1270 	php_req.tv_nsec = (long)tv_nsec;
1271 	if (!nanosleep(&php_req, &php_rem)) {
1272 		RETURN_TRUE;
1273 	} else if (errno == EINTR) {
1274 		array_init(return_value);
1275 		add_assoc_long_ex(return_value, "seconds", sizeof("seconds")-1, php_rem.tv_sec);
1276 		add_assoc_long_ex(return_value, "nanoseconds", sizeof("nanoseconds")-1, php_rem.tv_nsec);
1277 		return;
1278 	} else if (errno == EINVAL) {
1279 		zend_value_error("Nanoseconds was not in the range 0 to 999 999 999 or seconds was negative");
1280 		RETURN_THROWS();
1281 	}
1282 
1283 	RETURN_FALSE;
1284 }
1285 /* }}} */
1286 
1287 /* {{{ Make the script sleep until the specified time */
1288 PHP_FUNCTION(time_sleep_until)
1289 {
1290 	double target_secs;
1291 	struct timeval tm;
1292 	struct timespec php_req, php_rem;
1293 	uint64_t current_ns, target_ns, diff_ns;
1294 	const uint64_t ns_per_sec = 1000000000;
1295 
1296 	ZEND_PARSE_PARAMETERS_START(1, 1)
1297 		Z_PARAM_DOUBLE(target_secs)
1298 	ZEND_PARSE_PARAMETERS_END();
1299 
1300 	if (gettimeofday((struct timeval *) &tm, NULL) != 0) {
1301 		RETURN_FALSE;
1302 	}
1303 
1304 	target_ns = (uint64_t) (target_secs * ns_per_sec);
1305 	current_ns = ((uint64_t) tm.tv_sec) * ns_per_sec + ((uint64_t) tm.tv_usec) * 1000;
1306 	if (target_ns < current_ns) {
1307 		php_error_docref(NULL, E_WARNING, "Argument #1 ($timestamp) must be greater than or equal to the current time");
1308 		RETURN_FALSE;
1309 	}
1310 
1311 	diff_ns = target_ns - current_ns;
1312 	php_req.tv_sec = (time_t) (diff_ns / ns_per_sec);
1313 	php_req.tv_nsec = (long) (diff_ns % ns_per_sec);
1314 
1315 	while (nanosleep(&php_req, &php_rem)) {
1316 		if (errno == EINTR) {
1317 			php_req.tv_sec = php_rem.tv_sec;
1318 			php_req.tv_nsec = php_rem.tv_nsec;
1319 		} else {
1320 			RETURN_FALSE;
1321 		}
1322 	}
1323 
1324 	RETURN_TRUE;
1325 }
1326 /* }}} */
1327 #endif
1328 
1329 /* {{{ Get the name of the owner of the current PHP script */
1330 PHP_FUNCTION(get_current_user)
1331 {
1332 	ZEND_PARSE_PARAMETERS_NONE();
1333 
1334 	RETURN_STRING(php_get_current_user());
1335 }
1336 /* }}} */
1337 
1338 #define ZVAL_SET_INI_STR(zv, val) do { \
1339 	if (ZSTR_IS_INTERNED(val)) { \
1340 		ZVAL_INTERNED_STR(zv, val); \
1341 	} else if (ZSTR_LEN(val) == 0) { \
1342 		ZVAL_EMPTY_STRING(zv); \
1343 	} else if (ZSTR_LEN(val) == 1) { \
1344 		ZVAL_CHAR(zv, ZSTR_VAL(val)[0]); \
1345 	} else if (!(GC_FLAGS(val) & GC_PERSISTENT)) { \
1346 		ZVAL_NEW_STR(zv, zend_string_copy(val)); \
1347 	} else { \
1348 		ZVAL_NEW_STR(zv, zend_string_init(ZSTR_VAL(val), ZSTR_LEN(val), 0)); \
1349 	} \
1350 } while (0)
1351 
1352 static void add_config_entries(HashTable *hash, zval *return_value);
1353 
1354 /* {{{ add_config_entry */
1355 static void add_config_entry(zend_ulong h, zend_string *key, zval *entry, zval *retval)
1356 {
1357 	if (Z_TYPE_P(entry) == IS_STRING) {
1358 		zval str_zv;
1359 		ZVAL_SET_INI_STR(&str_zv, Z_STR_P(entry));
1360 		if (key) {
1361 			add_assoc_zval_ex(retval, ZSTR_VAL(key), ZSTR_LEN(key), &str_zv);
1362 		} else {
1363 			add_index_zval(retval, h, &str_zv);
1364 		}
1365 	} else if (Z_TYPE_P(entry) == IS_ARRAY) {
1366 		zval tmp;
1367 		array_init(&tmp);
1368 		add_config_entries(Z_ARRVAL_P(entry), &tmp);
1369 		zend_hash_update(Z_ARRVAL_P(retval), key, &tmp);
1370 	}
1371 }
1372 /* }}} */
1373 
1374 /* {{{ add_config_entries */
1375 static void add_config_entries(HashTable *hash, zval *return_value) /* {{{ */
1376 {
1377 	zend_ulong h;
1378 	zend_string *key;
1379 	zval *zv;
1380 
1381 	ZEND_HASH_FOREACH_KEY_VAL(hash, h, key, zv)
1382 		add_config_entry(h, key, zv, return_value);
1383 	ZEND_HASH_FOREACH_END();
1384 }
1385 /* }}} */
1386 
1387 /* {{{ Get the value of a PHP configuration option */
1388 PHP_FUNCTION(get_cfg_var)
1389 {
1390 	zend_string *varname;
1391 
1392 	ZEND_PARSE_PARAMETERS_START(1, 1)
1393 		Z_PARAM_STR(varname)
1394 	ZEND_PARSE_PARAMETERS_END();
1395 
1396 	zval *retval = cfg_get_entry_ex(varname);
1397 
1398 	if (retval) {
1399 		if (Z_TYPE_P(retval) == IS_ARRAY) {
1400 			array_init(return_value);
1401 			add_config_entries(Z_ARRVAL_P(retval), return_value);
1402 			return;
1403 		} else {
1404 			ZVAL_SET_INI_STR(return_value, Z_STR_P(retval));
1405 		}
1406 	} else {
1407 		RETURN_FALSE;
1408 	}
1409 }
1410 /* }}} */
1411 
1412 /*
1413 	1st arg = error message
1414 	2nd arg = error option
1415 	3rd arg = optional parameters (email address or tcp address)
1416 	4th arg = used for additional headers if email
1417 
1418 error options:
1419 	0 = send to php_error_log (uses syslog or file depending on ini setting)
1420 	1 = send via email to 3rd parameter 4th option = additional headers
1421 	2 = send via tcp/ip to 3rd parameter (name or ip:port)
1422 	3 = save to file in 3rd parameter
1423 	4 = send to SAPI logger directly
1424 */
1425 
1426 /* {{{ Send an error message somewhere */
1427 PHP_FUNCTION(error_log)
1428 {
1429 	char *message, *opt = NULL, *headers = NULL;
1430 	size_t message_len, opt_len = 0, headers_len = 0;
1431 	zend_long erropt = 0;
1432 
1433 	ZEND_PARSE_PARAMETERS_START(1, 4)
1434 		Z_PARAM_STRING(message, message_len)
1435 		Z_PARAM_OPTIONAL
1436 		Z_PARAM_LONG(erropt)
1437 		Z_PARAM_PATH_OR_NULL(opt, opt_len)
1438 		Z_PARAM_STRING_OR_NULL(headers, headers_len)
1439 	ZEND_PARSE_PARAMETERS_END();
1440 
1441 	if (_php_error_log_ex((int) erropt, message, message_len, opt, headers) == FAILURE) {
1442 		RETURN_FALSE;
1443 	}
1444 
1445 	RETURN_TRUE;
1446 }
1447 /* }}} */
1448 
1449 /* For BC (not binary-safe!) */
1450 PHPAPI int _php_error_log(int opt_err, const char *message, const char *opt, const char *headers) /* {{{ */
1451 {
1452 	return _php_error_log_ex(opt_err, message, (opt_err == 3) ? strlen(message) : 0, opt, headers);
1453 }
1454 /* }}} */
1455 
1456 PHPAPI int _php_error_log_ex(int opt_err, const char *message, size_t message_len, const char *opt, const char *headers) /* {{{ */
1457 {
1458 	php_stream *stream = NULL;
1459 	size_t nbytes;
1460 
1461 	switch (opt_err)
1462 	{
1463 		case 1:		/*send an email */
1464 			if (!php_mail(opt, "PHP error_log message", message, headers, NULL)) {
1465 				return FAILURE;
1466 			}
1467 			break;
1468 
1469 		case 2:		/*send to an address */
1470 			zend_value_error("TCP/IP option is not available for error logging");
1471 			return FAILURE;
1472 
1473 		case 3:		/*save to a file */
1474 			stream = php_stream_open_wrapper(opt, "a", REPORT_ERRORS, NULL);
1475 			if (!stream) {
1476 				return FAILURE;
1477 			}
1478 			nbytes = php_stream_write(stream, message, message_len);
1479 			php_stream_close(stream);
1480 			if (nbytes != message_len) {
1481 				return FAILURE;
1482 			}
1483 			break;
1484 
1485 		case 4: /* send to SAPI */
1486 			if (sapi_module.log_message) {
1487 				sapi_module.log_message(message, -1);
1488 			} else {
1489 				return FAILURE;
1490 			}
1491 			break;
1492 
1493 		default:
1494 			php_log_err_with_severity(message, LOG_NOTICE);
1495 			break;
1496 	}
1497 	return SUCCESS;
1498 }
1499 /* }}} */
1500 
1501 /* {{{ Get the last occurred error as associative array. Returns NULL if there hasn't been an error yet. */
1502 PHP_FUNCTION(error_get_last)
1503 {
1504 	ZEND_PARSE_PARAMETERS_NONE();
1505 
1506 	if (PG(last_error_message)) {
1507 		zval tmp;
1508 		array_init(return_value);
1509 
1510 		ZVAL_LONG(&tmp, PG(last_error_type));
1511 		zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
1512 
1513 		ZVAL_STR_COPY(&tmp, PG(last_error_message));
1514 		zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
1515 
1516 		ZVAL_STR_COPY(&tmp, PG(last_error_file));
1517 		zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
1518 
1519 		ZVAL_LONG(&tmp, PG(last_error_lineno));
1520 		zend_hash_update(Z_ARR_P(return_value), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
1521 	}
1522 }
1523 /* }}} */
1524 
1525 /* {{{ Clear the last occurred error. */
1526 PHP_FUNCTION(error_clear_last)
1527 {
1528 	ZEND_PARSE_PARAMETERS_NONE();
1529 
1530 	if (PG(last_error_message)) {
1531 		PG(last_error_type) = 0;
1532 		PG(last_error_lineno) = 0;
1533 
1534 		zend_string_release(PG(last_error_message));
1535 		PG(last_error_message) = NULL;
1536 
1537 		if (PG(last_error_file)) {
1538 			zend_string_release(PG(last_error_file));
1539 			PG(last_error_file) = NULL;
1540 		}
1541 	}
1542 }
1543 /* }}} */
1544 
1545 /* {{{ Call a user function which is the first parameter
1546    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1547 PHP_FUNCTION(call_user_func)
1548 {
1549 	zval retval;
1550 	zend_fcall_info fci;
1551 	zend_fcall_info_cache fci_cache;
1552 
1553 	ZEND_PARSE_PARAMETERS_START(1, -1)
1554 		Z_PARAM_FUNC(fci, fci_cache)
1555 		Z_PARAM_VARIADIC_WITH_NAMED(fci.params, fci.param_count, fci.named_params)
1556 	ZEND_PARSE_PARAMETERS_END();
1557 
1558 	fci.retval = &retval;
1559 
1560 	if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1561 		if (Z_ISREF(retval)) {
1562 			zend_unwrap_reference(&retval);
1563 		}
1564 		ZVAL_COPY_VALUE(return_value, &retval);
1565 	}
1566 }
1567 /* }}} */
1568 
1569 /* {{{ Call a user function which is the first parameter with the arguments contained in array
1570    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
1571 PHP_FUNCTION(call_user_func_array)
1572 {
1573 	zval retval;
1574 	HashTable *params;
1575 	zend_fcall_info fci;
1576 	zend_fcall_info_cache fci_cache;
1577 
1578 	ZEND_PARSE_PARAMETERS_START(2, 2)
1579 		Z_PARAM_FUNC(fci, fci_cache)
1580 		Z_PARAM_ARRAY_HT(params)
1581 	ZEND_PARSE_PARAMETERS_END();
1582 
1583 	fci.named_params = params;
1584 	fci.retval = &retval;
1585 
1586 	if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1587 		if (Z_ISREF(retval)) {
1588 			zend_unwrap_reference(&retval);
1589 		}
1590 		ZVAL_COPY_VALUE(return_value, &retval);
1591 	}
1592 }
1593 /* }}} */
1594 
1595 /* {{{ Call a user function which is the first parameter */
1596 PHP_FUNCTION(forward_static_call)
1597 {
1598 	zval retval;
1599 	zend_fcall_info fci;
1600 	zend_fcall_info_cache fci_cache;
1601 	zend_class_entry *called_scope;
1602 
1603 	ZEND_PARSE_PARAMETERS_START(1, -1)
1604 		Z_PARAM_FUNC(fci, fci_cache)
1605 		Z_PARAM_VARIADIC('*', fci.params, fci.param_count)
1606 	ZEND_PARSE_PARAMETERS_END();
1607 
1608 	if (!EX(prev_execute_data)->func->common.scope) {
1609 		zend_throw_error(NULL, "Cannot call forward_static_call() when no class scope is active");
1610 		RETURN_THROWS();
1611 	}
1612 
1613 	fci.retval = &retval;
1614 
1615 	called_scope = zend_get_called_scope(execute_data);
1616 	if (called_scope && fci_cache.calling_scope &&
1617 		instanceof_function(called_scope, fci_cache.calling_scope)) {
1618 			fci_cache.called_scope = called_scope;
1619 	}
1620 
1621 	if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1622 		if (Z_ISREF(retval)) {
1623 			zend_unwrap_reference(&retval);
1624 		}
1625 		ZVAL_COPY_VALUE(return_value, &retval);
1626 	}
1627 }
1628 /* }}} */
1629 
1630 /* {{{ Call a static method which is the first parameter with the arguments contained in array */
1631 PHP_FUNCTION(forward_static_call_array)
1632 {
1633 	zval *params, retval;
1634 	zend_fcall_info fci;
1635 	zend_fcall_info_cache fci_cache;
1636 	zend_class_entry *called_scope;
1637 
1638 	ZEND_PARSE_PARAMETERS_START(2, 2)
1639 		Z_PARAM_FUNC(fci, fci_cache)
1640 		Z_PARAM_ARRAY(params)
1641 	ZEND_PARSE_PARAMETERS_END();
1642 
1643 	zend_fcall_info_args(&fci, params);
1644 	fci.retval = &retval;
1645 
1646 	called_scope = zend_get_called_scope(execute_data);
1647 	if (called_scope && fci_cache.calling_scope &&
1648 		instanceof_function(called_scope, fci_cache.calling_scope)) {
1649 			fci_cache.called_scope = called_scope;
1650 	}
1651 
1652 	if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
1653 		if (Z_ISREF(retval)) {
1654 			zend_unwrap_reference(&retval);
1655 		}
1656 		ZVAL_COPY_VALUE(return_value, &retval);
1657 	}
1658 
1659 	zend_fcall_info_args_clear(&fci, 1);
1660 }
1661 /* }}} */
1662 
1663 static void fci_addref(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
1664 {
1665 	Z_TRY_ADDREF(fci->function_name);
1666 	if (fci_cache->object) {
1667 		GC_ADDREF(fci_cache->object);
1668 	}
1669 }
1670 
1671 static void fci_release(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
1672 {
1673 	zval_ptr_dtor(&fci->function_name);
1674 	if (fci_cache->object) {
1675 		zend_object_release(fci_cache->object);
1676 	}
1677 }
1678 
1679 void user_shutdown_function_dtor(zval *zv) /* {{{ */
1680 {
1681 	php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1682 
1683 	zend_fcall_info_args_clear(&shutdown_function_entry->fci, true);
1684 	fci_release(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
1685 	efree(shutdown_function_entry);
1686 }
1687 /* }}} */
1688 
1689 void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
1690 {
1691 	zend_fcall_info_args_clear(&tick_function_entry->fci, true);
1692 	fci_release(&tick_function_entry->fci, &tick_function_entry->fci_cache);
1693 }
1694 /* }}} */
1695 
1696 static int user_shutdown_function_call(zval *zv) /* {{{ */
1697 {
1698 	php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1699 	zval retval;
1700 	zend_result call_status;
1701 
1702 	/* set retval zval for FCI struct */
1703 	shutdown_function_entry->fci.retval = &retval;
1704 	call_status = zend_call_function(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
1705 	ZEND_ASSERT(call_status == SUCCESS);
1706 	zval_ptr_dtor(&retval);
1707 
1708 	return 0;
1709 }
1710 /* }}} */
1711 
1712 static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
1713 {
1714 	/* Prevent re-entrant calls to the same user ticks function */
1715 	if (!tick_fe->calling) {
1716 		zval tmp;
1717 
1718 		/* set tmp zval */
1719 		tick_fe->fci.retval = &tmp;
1720 
1721 		tick_fe->calling = true;
1722 		zend_call_function(&tick_fe->fci, &tick_fe->fci_cache);
1723 
1724 		/* Destroy return value */
1725 		zval_ptr_dtor(&tmp);
1726 		tick_fe->calling = false;
1727 	}
1728 }
1729 /* }}} */
1730 
1731 static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
1732 {
1733 	zend_llist_apply(BG(user_tick_functions), (llist_apply_func_t) user_tick_function_call);
1734 }
1735 /* }}} */
1736 
1737 static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_tick_function_entry * tick_fe2) /* {{{ */
1738 {
1739 	zval *func1 = &tick_fe1->fci.function_name;
1740 	zval *func2 = &tick_fe2->fci.function_name;
1741 	int ret;
1742 
1743 	if (Z_TYPE_P(func1) == IS_STRING && Z_TYPE_P(func2) == IS_STRING) {
1744 		ret = zend_binary_zval_strcmp(func1, func2) == 0;
1745 	} else if (Z_TYPE_P(func1) == IS_ARRAY && Z_TYPE_P(func2) == IS_ARRAY) {
1746 		ret = zend_compare_arrays(func1, func2) == 0;
1747 	} else if (Z_TYPE_P(func1) == IS_OBJECT && Z_TYPE_P(func2) == IS_OBJECT) {
1748 		ret = zend_compare_objects(func1, func2) == 0;
1749 	} else {
1750 		ret = 0;
1751 	}
1752 
1753 	if (ret && tick_fe1->calling) {
1754 		zend_throw_error(NULL, "Registered tick function cannot be unregistered while it is being executed");
1755 		return 0;
1756 	}
1757 	return ret;
1758 }
1759 /* }}} */
1760 
1761 PHPAPI void php_call_shutdown_functions(void) /* {{{ */
1762 {
1763 	if (BG(user_shutdown_function_names)) {
1764 		zend_try {
1765 			zend_hash_apply(BG(user_shutdown_function_names), user_shutdown_function_call);
1766 		} zend_end_try();
1767 	}
1768 }
1769 /* }}} */
1770 
1771 PHPAPI void php_free_shutdown_functions(void) /* {{{ */
1772 {
1773 	if (BG(user_shutdown_function_names))
1774 		zend_try {
1775 			zend_hash_destroy(BG(user_shutdown_function_names));
1776 			FREE_HASHTABLE(BG(user_shutdown_function_names));
1777 			BG(user_shutdown_function_names) = NULL;
1778 		} zend_catch {
1779 			/* maybe shutdown method call exit, we just ignore it */
1780 			FREE_HASHTABLE(BG(user_shutdown_function_names));
1781 			BG(user_shutdown_function_names) = NULL;
1782 		} zend_end_try();
1783 }
1784 /* }}} */
1785 
1786 /* {{{ Register a user-level function to be called on request termination */
1787 PHP_FUNCTION(register_shutdown_function)
1788 {
1789 	php_shutdown_function_entry entry;
1790 	zval *params = NULL;
1791 	uint32_t param_count = 0;
1792 	bool status;
1793 
1794 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &entry.fci, &entry.fci_cache, &params, &param_count) == FAILURE) {
1795 		RETURN_THROWS();
1796 	}
1797 
1798 	fci_addref(&entry.fci, &entry.fci_cache);
1799 	zend_fcall_info_argp(&entry.fci, param_count, params);
1800 
1801 	status = append_user_shutdown_function(&entry);
1802 	ZEND_ASSERT(status);
1803 }
1804 /* }}} */
1805 
1806 PHPAPI bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1807 {
1808 	if (!BG(user_shutdown_function_names)) {
1809 		ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1810 		zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1811 	}
1812 
1813 	zend_hash_str_update_mem(BG(user_shutdown_function_names), function_name, function_len, shutdown_function_entry, sizeof(php_shutdown_function_entry));
1814 	return 1;
1815 }
1816 /* }}} */
1817 
1818 PHPAPI bool remove_user_shutdown_function(const char *function_name, size_t function_len) /* {{{ */
1819 {
1820 	if (BG(user_shutdown_function_names)) {
1821 		return zend_hash_str_del(BG(user_shutdown_function_names), function_name, function_len) != FAILURE;
1822 	}
1823 
1824 	return 0;
1825 }
1826 /* }}} */
1827 
1828 PHPAPI bool append_user_shutdown_function(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
1829 {
1830 	if (!BG(user_shutdown_function_names)) {
1831 		ALLOC_HASHTABLE(BG(user_shutdown_function_names));
1832 		zend_hash_init(BG(user_shutdown_function_names), 0, NULL, user_shutdown_function_dtor, 0);
1833 	}
1834 
1835 	return zend_hash_next_index_insert_mem(BG(user_shutdown_function_names), shutdown_function_entry, sizeof(php_shutdown_function_entry)) != NULL;
1836 }
1837 /* }}} */
1838 
1839 ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
1840 {
1841 	syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment");
1842 	syntax_highlighter_ini->highlight_default = INI_STR("highlight.default");
1843 	syntax_highlighter_ini->highlight_html    = INI_STR("highlight.html");
1844 	syntax_highlighter_ini->highlight_keyword = INI_STR("highlight.keyword");
1845 	syntax_highlighter_ini->highlight_string  = INI_STR("highlight.string");
1846 }
1847 /* }}} */
1848 
1849 /* {{{ Syntax highlight a source file */
1850 PHP_FUNCTION(highlight_file)
1851 {
1852 	char *filename;
1853 	size_t filename_len;
1854 	int ret;
1855 	zend_syntax_highlighter_ini syntax_highlighter_ini;
1856 	bool i = 0;
1857 
1858 	ZEND_PARSE_PARAMETERS_START(1, 2)
1859 		Z_PARAM_PATH(filename, filename_len)
1860 		Z_PARAM_OPTIONAL
1861 		Z_PARAM_BOOL(i)
1862 	ZEND_PARSE_PARAMETERS_END();
1863 
1864 	if (php_check_open_basedir(filename)) {
1865 		RETURN_FALSE;
1866 	}
1867 
1868 	if (i) {
1869 		php_output_start_default();
1870 	}
1871 
1872 	php_get_highlight_struct(&syntax_highlighter_ini);
1873 
1874 	ret = highlight_file(filename, &syntax_highlighter_ini);
1875 
1876 	if (ret == FAILURE) {
1877 		if (i) {
1878 			php_output_end();
1879 		}
1880 		RETURN_FALSE;
1881 	}
1882 
1883 	if (i) {
1884 		php_output_get_contents(return_value);
1885 		php_output_discard();
1886 		ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1887 	} else {
1888 		RETURN_TRUE;
1889 	}
1890 }
1891 /* }}} */
1892 
1893 /* {{{ Return source with stripped comments and whitespace */
1894 PHP_FUNCTION(php_strip_whitespace)
1895 {
1896 	zend_string *filename;
1897 	zend_lex_state original_lex_state;
1898 	zend_file_handle file_handle;
1899 
1900 	ZEND_PARSE_PARAMETERS_START(1, 1)
1901 		Z_PARAM_PATH_STR(filename)
1902 	ZEND_PARSE_PARAMETERS_END();
1903 
1904 	php_output_start_default();
1905 
1906 	zend_stream_init_filename_ex(&file_handle, filename);
1907 	zend_save_lexical_state(&original_lex_state);
1908 	if (open_file_for_scanning(&file_handle) == FAILURE) {
1909 		zend_restore_lexical_state(&original_lex_state);
1910 		php_output_end();
1911 		zend_destroy_file_handle(&file_handle);
1912 		RETURN_EMPTY_STRING();
1913 	}
1914 
1915 	zend_strip();
1916 
1917 	zend_restore_lexical_state(&original_lex_state);
1918 
1919 	php_output_get_contents(return_value);
1920 	php_output_discard();
1921 	zend_destroy_file_handle(&file_handle);
1922 }
1923 /* }}} */
1924 
1925 /* {{{ Syntax highlight a string or optionally return it */
1926 PHP_FUNCTION(highlight_string)
1927 {
1928 	zend_string *str;
1929 	zend_syntax_highlighter_ini syntax_highlighter_ini;
1930 	char *hicompiled_string_description;
1931 	bool i = 0;
1932 	int old_error_reporting = EG(error_reporting);
1933 
1934 	ZEND_PARSE_PARAMETERS_START(1, 2)
1935 		Z_PARAM_STR(str)
1936 		Z_PARAM_OPTIONAL
1937 		Z_PARAM_BOOL(i)
1938 	ZEND_PARSE_PARAMETERS_END();
1939 
1940 	if (i) {
1941 		php_output_start_default();
1942 	}
1943 
1944 	EG(error_reporting) = E_ERROR;
1945 
1946 	php_get_highlight_struct(&syntax_highlighter_ini);
1947 
1948 	hicompiled_string_description = zend_make_compiled_string_description("highlighted code");
1949 
1950 	highlight_string(str, &syntax_highlighter_ini, hicompiled_string_description);
1951 	efree(hicompiled_string_description);
1952 
1953 	EG(error_reporting) = old_error_reporting;
1954 
1955 	if (i) {
1956 		php_output_get_contents(return_value);
1957 		php_output_discard();
1958 		ZEND_ASSERT(Z_TYPE_P(return_value) == IS_STRING);
1959 	} else {
1960 		// TODO Make this function void?
1961 		RETURN_TRUE;
1962 	}
1963 }
1964 /* }}} */
1965 
1966 /* {{{ Get a configuration option */
1967 PHP_FUNCTION(ini_get)
1968 {
1969 	zend_string *varname, *val;
1970 
1971 	ZEND_PARSE_PARAMETERS_START(1, 1)
1972 		Z_PARAM_STR(varname)
1973 	ZEND_PARSE_PARAMETERS_END();
1974 
1975 	val = zend_ini_get_value(varname);
1976 
1977 	if (!val) {
1978 		RETURN_FALSE;
1979 	}
1980 
1981 	ZVAL_SET_INI_STR(return_value, val);
1982 }
1983 /* }}} */
1984 
1985 /* {{{ Get all configuration options */
1986 PHP_FUNCTION(ini_get_all)
1987 {
1988 	char *extname = NULL;
1989 	size_t extname_len = 0, module_number = 0;
1990 	zend_module_entry *module;
1991 	bool details = 1;
1992 	zend_string *key;
1993 	zend_ini_entry *ini_entry;
1994 
1995 
1996 	ZEND_PARSE_PARAMETERS_START(0, 2)
1997 		Z_PARAM_OPTIONAL
1998 		Z_PARAM_STRING_OR_NULL(extname, extname_len)
1999 		Z_PARAM_BOOL(details)
2000 	ZEND_PARSE_PARAMETERS_END();
2001 
2002 	zend_ini_sort_entries();
2003 
2004 	if (extname) {
2005 		if ((module = zend_hash_str_find_ptr(&module_registry, extname, extname_len)) == NULL) {
2006 			php_error_docref(NULL, E_WARNING, "Extension \"%s\" cannot be found", extname);
2007 			RETURN_FALSE;
2008 		}
2009 		module_number = module->module_number;
2010 	}
2011 
2012 	array_init(return_value);
2013 	ZEND_HASH_FOREACH_STR_KEY_PTR(EG(ini_directives), key, ini_entry) {
2014 		zval option;
2015 
2016 		if (module_number != 0 && ini_entry->module_number != module_number) {
2017 			continue;
2018 		}
2019 
2020 		if (key == NULL || ZSTR_VAL(key)[0] != 0) {
2021 			if (details) {
2022 				array_init(&option);
2023 
2024 				if (ini_entry->orig_value) {
2025 					add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->orig_value));
2026 				} else if (ini_entry->value) {
2027 					add_assoc_str(&option, "global_value", zend_string_copy(ini_entry->value));
2028 				} else {
2029 					add_assoc_null(&option, "global_value");
2030 				}
2031 
2032 				if (ini_entry->value) {
2033 					add_assoc_str(&option, "local_value", zend_string_copy(ini_entry->value));
2034 				} else {
2035 					add_assoc_null(&option, "local_value");
2036 				}
2037 
2038 				add_assoc_long(&option, "access", ini_entry->modifiable);
2039 
2040 				zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &option);
2041 			} else {
2042 				if (ini_entry->value) {
2043 					zval zv;
2044 
2045 					ZVAL_STR_COPY(&zv, ini_entry->value);
2046 					zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &zv);
2047 				} else {
2048 					zend_symtable_update(Z_ARRVAL_P(return_value), ini_entry->name, &EG(uninitialized_zval));
2049 				}
2050 			}
2051 		}
2052 	} ZEND_HASH_FOREACH_END();
2053 }
2054 /* }}} */
2055 
2056 static int php_ini_check_path(char *option_name, size_t option_len, char *new_option_name, size_t new_option_len) /* {{{ */
2057 {
2058 	if (option_len + 1 != new_option_len) {
2059 		return 0;
2060 	}
2061 
2062 	return !strncmp(option_name, new_option_name, option_len);
2063 }
2064 /* }}} */
2065 
2066 /* {{{ Set a configuration option, returns false on error and the old value of the configuration option on success */
2067 PHP_FUNCTION(ini_set)
2068 {
2069 	zend_string *varname;
2070 	zval *new_value;
2071 	zend_string *val;
2072 
2073 	ZEND_PARSE_PARAMETERS_START(2, 2)
2074 		Z_PARAM_STR(varname)
2075 		Z_PARAM_ZVAL(new_value)
2076 	ZEND_PARSE_PARAMETERS_END();
2077 
2078 	if (Z_TYPE_P(new_value) > IS_STRING) {
2079 		zend_argument_type_error(2, "must be of type string|int|float|bool|null");
2080 		RETURN_THROWS();
2081 	}
2082 
2083 	val = zend_ini_get_value(varname);
2084 
2085 	if (val) {
2086 		ZVAL_SET_INI_STR(return_value, val);
2087 	} else {
2088 		RETVAL_FALSE;
2089 	}
2090 
2091 	zend_string *new_value_tmp_str;
2092 	zend_string *new_value_str = zval_get_tmp_string(new_value, &new_value_tmp_str);
2093 
2094 #define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini))
2095 	/* open basedir check */
2096 	if (PG(open_basedir)) {
2097 		if (_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "error_log") ||
2098 			_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.class.path") ||
2099 			_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.home") ||
2100 			_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "mail.log") ||
2101 			_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.library.path") ||
2102 			_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "vpopmail.directory")) {
2103 			if (php_check_open_basedir(ZSTR_VAL(new_value_str))) {
2104 				zval_ptr_dtor_str(return_value);
2105 				zend_tmp_string_release(new_value_tmp_str);
2106 				RETURN_FALSE;
2107 			}
2108 		}
2109 	}
2110 #undef _CHECK_PATH
2111 
2112 	if (zend_alter_ini_entry_ex(varname, new_value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2113 		zval_ptr_dtor_str(return_value);
2114 		RETVAL_FALSE;
2115 	}
2116 	zend_tmp_string_release(new_value_tmp_str);
2117 }
2118 /* }}} */
2119 
2120 /* {{{ Restore the value of a configuration option specified by varname */
2121 PHP_FUNCTION(ini_restore)
2122 {
2123 	zend_string *varname;
2124 
2125 	ZEND_PARSE_PARAMETERS_START(1, 1)
2126 		Z_PARAM_STR(varname)
2127 	ZEND_PARSE_PARAMETERS_END();
2128 
2129 	zend_restore_ini_entry(varname, PHP_INI_STAGE_RUNTIME);
2130 }
2131 /* }}} */
2132 
2133 /* {{{ Sets the include_path configuration option */
2134 PHP_FUNCTION(set_include_path)
2135 {
2136 	zend_string *new_value;
2137 	char *old_value;
2138 	zend_string *key;
2139 
2140 	ZEND_PARSE_PARAMETERS_START(1, 1)
2141 		Z_PARAM_PATH_STR(new_value)
2142 	ZEND_PARSE_PARAMETERS_END();
2143 
2144 	old_value = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
2145 	/* copy to return here, because alter might free it! */
2146 	if (old_value) {
2147 		RETVAL_STRING(old_value);
2148 	} else {
2149 		RETVAL_FALSE;
2150 	}
2151 
2152 	key = zend_string_init("include_path", sizeof("include_path") - 1, 0);
2153 	if (zend_alter_ini_entry_ex(key, new_value, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) {
2154 		zend_string_release_ex(key, 0);
2155 		zval_ptr_dtor_str(return_value);
2156 		RETURN_FALSE;
2157 	}
2158 	zend_string_release_ex(key, 0);
2159 }
2160 /* }}} */
2161 
2162 /* {{{ Get the current include_path configuration option */
2163 PHP_FUNCTION(get_include_path)
2164 {
2165 	char *str;
2166 
2167 	ZEND_PARSE_PARAMETERS_NONE();
2168 
2169 	str = zend_ini_string("include_path", sizeof("include_path") - 1, 0);
2170 
2171 	if (str == NULL) {
2172 		RETURN_FALSE;
2173 	}
2174 
2175 	RETURN_STRING(str);
2176 }
2177 /* }}} */
2178 
2179 /* {{{ Prints out or returns information about the specified variable */
2180 PHP_FUNCTION(print_r)
2181 {
2182 	zval *var;
2183 	bool do_return = 0;
2184 
2185 	ZEND_PARSE_PARAMETERS_START(1, 2)
2186 		Z_PARAM_ZVAL(var)
2187 		Z_PARAM_OPTIONAL
2188 		Z_PARAM_BOOL(do_return)
2189 	ZEND_PARSE_PARAMETERS_END();
2190 
2191 	if (do_return) {
2192 		RETURN_STR(zend_print_zval_r_to_str(var, 0));
2193 	} else {
2194 		zend_print_zval_r(var, 0);
2195 		RETURN_TRUE;
2196 	}
2197 }
2198 /* }}} */
2199 
2200 /* {{{ Returns true if client disconnected */
2201 PHP_FUNCTION(connection_aborted)
2202 {
2203 	ZEND_PARSE_PARAMETERS_NONE();
2204 
2205 	RETURN_LONG(PG(connection_status) & PHP_CONNECTION_ABORTED);
2206 }
2207 /* }}} */
2208 
2209 /* {{{ Returns the connection status bitfield */
2210 PHP_FUNCTION(connection_status)
2211 {
2212 	ZEND_PARSE_PARAMETERS_NONE();
2213 
2214 	RETURN_LONG(PG(connection_status));
2215 }
2216 /* }}} */
2217 
2218 /* {{{ Set whether we want to ignore a user abort event or not */
2219 PHP_FUNCTION(ignore_user_abort)
2220 {
2221 	bool arg = 0;
2222 	bool arg_is_null = 1;
2223 	int old_setting;
2224 
2225 	ZEND_PARSE_PARAMETERS_START(0, 1)
2226 		Z_PARAM_OPTIONAL
2227 		Z_PARAM_BOOL_OR_NULL(arg, arg_is_null)
2228 	ZEND_PARSE_PARAMETERS_END();
2229 
2230 	old_setting = (unsigned short)PG(ignore_user_abort);
2231 
2232 	if (!arg_is_null) {
2233 		zend_string *key = zend_string_init("ignore_user_abort", sizeof("ignore_user_abort") - 1, 0);
2234 		zend_alter_ini_entry_chars(key, arg ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
2235 		zend_string_release_ex(key, 0);
2236 	}
2237 
2238 	RETURN_LONG(old_setting);
2239 }
2240 /* }}} */
2241 
2242 #if HAVE_GETSERVBYNAME
2243 /* {{{ Returns port associated with service. Protocol must be "tcp" or "udp" */
2244 PHP_FUNCTION(getservbyname)
2245 {
2246 	zend_string *name;
2247 	char *proto;
2248 	size_t proto_len;
2249 	struct servent *serv;
2250 
2251 	ZEND_PARSE_PARAMETERS_START(2, 2)
2252 		Z_PARAM_STR(name)
2253 		Z_PARAM_STRING(proto, proto_len)
2254 	ZEND_PARSE_PARAMETERS_END();
2255 
2256 
2257 /* empty string behaves like NULL on windows implementation of
2258    getservbyname. Let be portable instead. */
2259 #ifdef PHP_WIN32
2260 	if (proto_len == 0) {
2261 		RETURN_FALSE;
2262 	}
2263 #endif
2264 
2265 	serv = getservbyname(ZSTR_VAL(name), proto);
2266 
2267 #if defined(_AIX)
2268 	/*
2269         On AIX, imap is only known as imap2 in /etc/services, while on Linux imap is an alias for imap2.
2270         If a request for imap gives no result, we try again with imap2.
2271         */
2272 	if (serv == NULL && zend_string_equals_literal(name, "imap")) {
2273 		serv = getservbyname("imap2", proto);
2274 	}
2275 #endif
2276 	if (serv == NULL) {
2277 		RETURN_FALSE;
2278 	}
2279 
2280 	RETURN_LONG(ntohs(serv->s_port));
2281 }
2282 /* }}} */
2283 #endif
2284 
2285 #if HAVE_GETSERVBYPORT
2286 /* {{{ Returns service name associated with port. Protocol must be "tcp" or "udp" */
2287 PHP_FUNCTION(getservbyport)
2288 {
2289 	char *proto;
2290 	size_t proto_len;
2291 	zend_long port;
2292 	struct servent *serv;
2293 
2294 	ZEND_PARSE_PARAMETERS_START(2, 2)
2295 		Z_PARAM_LONG(port)
2296 		Z_PARAM_STRING(proto, proto_len)
2297 	ZEND_PARSE_PARAMETERS_END();
2298 
2299 	serv = getservbyport(htons((unsigned short) port), proto);
2300 
2301 	if (serv == NULL) {
2302 		RETURN_FALSE;
2303 	}
2304 
2305 	RETURN_STRING(serv->s_name);
2306 }
2307 /* }}} */
2308 #endif
2309 
2310 #if HAVE_GETPROTOBYNAME
2311 /* {{{ Returns protocol number associated with name as per /etc/protocols */
2312 PHP_FUNCTION(getprotobyname)
2313 {
2314 	char *name;
2315 	size_t name_len;
2316 	struct protoent *ent;
2317 
2318 	ZEND_PARSE_PARAMETERS_START(1, 1)
2319 		Z_PARAM_STRING(name, name_len)
2320 	ZEND_PARSE_PARAMETERS_END();
2321 
2322 	ent = getprotobyname(name);
2323 
2324 	if (ent == NULL) {
2325 		RETURN_FALSE;
2326 	}
2327 
2328 	RETURN_LONG(ent->p_proto);
2329 }
2330 /* }}} */
2331 #endif
2332 
2333 #if HAVE_GETPROTOBYNUMBER
2334 /* {{{ Returns protocol name associated with protocol number proto */
2335 PHP_FUNCTION(getprotobynumber)
2336 {
2337 	zend_long proto;
2338 	struct protoent *ent;
2339 
2340 	ZEND_PARSE_PARAMETERS_START(1, 1)
2341 		Z_PARAM_LONG(proto)
2342 	ZEND_PARSE_PARAMETERS_END();
2343 
2344 	ent = getprotobynumber((int)proto);
2345 
2346 	if (ent == NULL) {
2347 		RETURN_FALSE;
2348 	}
2349 
2350 	RETURN_STRING(ent->p_name);
2351 }
2352 /* }}} */
2353 #endif
2354 
2355 /* {{{ Registers a tick callback function */
2356 PHP_FUNCTION(register_tick_function)
2357 {
2358 	user_tick_function_entry tick_fe;
2359 	zval *params = NULL;
2360 	uint32_t param_count = 0;
2361 
2362 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &tick_fe.fci, &tick_fe.fci_cache, &params, &param_count) == FAILURE) {
2363 		RETURN_THROWS();
2364 	}
2365 
2366 	tick_fe.calling = false;
2367 	fci_addref(&tick_fe.fci, &tick_fe.fci_cache);
2368 	zend_fcall_info_argp(&tick_fe.fci, param_count, params);
2369 
2370 	if (!BG(user_tick_functions)) {
2371 		BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
2372 		zend_llist_init(BG(user_tick_functions),
2373 						sizeof(user_tick_function_entry),
2374 						(llist_dtor_func_t) user_tick_function_dtor, 0);
2375 		php_add_tick_function(run_user_tick_functions, NULL);
2376 	}
2377 
2378 	zend_llist_add_element(BG(user_tick_functions), &tick_fe);
2379 
2380 	RETURN_TRUE;
2381 }
2382 /* }}} */
2383 
2384 /* {{{ Unregisters a tick callback function */
2385 PHP_FUNCTION(unregister_tick_function)
2386 {
2387 	user_tick_function_entry tick_fe;
2388 
2389 	ZEND_PARSE_PARAMETERS_START(1, 1)
2390 		Z_PARAM_FUNC(tick_fe.fci, tick_fe.fci_cache)
2391 	ZEND_PARSE_PARAMETERS_END();
2392 
2393 	if (!BG(user_tick_functions)) {
2394 		return;
2395 	}
2396 
2397 	zend_llist_del_element(BG(user_tick_functions), &tick_fe, (int (*)(void *, void *)) user_tick_function_compare);
2398 }
2399 /* }}} */
2400 
2401 /* {{{ Check if file was created by rfc1867 upload */
2402 PHP_FUNCTION(is_uploaded_file)
2403 {
2404 	char *path;
2405 	size_t path_len;
2406 
2407 	ZEND_PARSE_PARAMETERS_START(1, 1)
2408 		Z_PARAM_PATH(path, path_len)
2409 	ZEND_PARSE_PARAMETERS_END();
2410 
2411 	if (!SG(rfc1867_uploaded_files)) {
2412 		RETURN_FALSE;
2413 	}
2414 
2415 	if (zend_hash_str_exists(SG(rfc1867_uploaded_files), path, path_len)) {
2416 		RETURN_TRUE;
2417 	} else {
2418 		RETURN_FALSE;
2419 	}
2420 }
2421 /* }}} */
2422 
2423 /* {{{ Move a file if and only if it was created by an upload */
2424 PHP_FUNCTION(move_uploaded_file)
2425 {
2426 	char *path, *new_path;
2427 	size_t path_len, new_path_len;
2428 	bool successful = 0;
2429 
2430 #ifndef PHP_WIN32
2431 	int oldmask; int ret;
2432 #endif
2433 
2434 	ZEND_PARSE_PARAMETERS_START(2, 2)
2435 		Z_PARAM_STRING(path, path_len)
2436 		Z_PARAM_PATH(new_path, new_path_len)
2437 	ZEND_PARSE_PARAMETERS_END();
2438 
2439 	if (!SG(rfc1867_uploaded_files)) {
2440 		RETURN_FALSE;
2441 	}
2442 
2443 	if (!zend_hash_str_exists(SG(rfc1867_uploaded_files), path, path_len)) {
2444 		RETURN_FALSE;
2445 	}
2446 
2447 	if (php_check_open_basedir(new_path)) {
2448 		RETURN_FALSE;
2449 	}
2450 
2451 	if (VCWD_RENAME(path, new_path) == 0) {
2452 		successful = 1;
2453 #ifndef PHP_WIN32
2454 		oldmask = umask(077);
2455 		umask(oldmask);
2456 
2457 		ret = VCWD_CHMOD(new_path, 0666 & ~oldmask);
2458 
2459 		if (ret == -1) {
2460 			php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
2461 		}
2462 #endif
2463 	} else if (php_copy_file_ex(path, new_path, STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) {
2464 		VCWD_UNLINK(path);
2465 		successful = 1;
2466 	}
2467 
2468 	if (successful) {
2469 		zend_hash_str_del(SG(rfc1867_uploaded_files), path, path_len);
2470 	} else {
2471 		php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", path, new_path);
2472 	}
2473 
2474 	RETURN_BOOL(successful);
2475 }
2476 /* }}} */
2477 
2478 /* {{{ php_simple_ini_parser_cb */
2479 static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2480 {
2481 	switch (callback_type) {
2482 
2483 		case ZEND_INI_PARSER_ENTRY:
2484 			if (!arg2) {
2485 				/* bare string - nothing to do */
2486 				break;
2487 			}
2488 			Z_TRY_ADDREF_P(arg2);
2489 			zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), arg2);
2490 			break;
2491 
2492 		case ZEND_INI_PARSER_POP_ENTRY:
2493 		{
2494 			zval hash, *find_hash;
2495 
2496 			if (!arg2) {
2497 				/* bare string - nothing to do */
2498 				break;
2499 			}
2500 
2501 			if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) {
2502 				zend_ulong key = (zend_ulong) zend_atol(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
2503 				if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
2504 					array_init(&hash);
2505 					find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash);
2506 				}
2507 			} else {
2508 				if ((find_hash = zend_hash_find(Z_ARRVAL_P(arr), Z_STR_P(arg1))) == NULL) {
2509 					array_init(&hash);
2510 					find_hash = zend_hash_add_new(Z_ARRVAL_P(arr), Z_STR_P(arg1), &hash);
2511 				}
2512 			}
2513 
2514 			if (Z_TYPE_P(find_hash) != IS_ARRAY) {
2515 				zval_ptr_dtor_nogc(find_hash);
2516 				array_init(find_hash);
2517 			}
2518 
2519 			if (!arg3 || (Z_TYPE_P(arg3) == IS_STRING && Z_STRLEN_P(arg3) == 0)) {
2520 				Z_TRY_ADDREF_P(arg2);
2521 				add_next_index_zval(find_hash, arg2);
2522 			} else {
2523 				array_set_zval_key(Z_ARRVAL_P(find_hash), arg3, arg2);
2524 			}
2525 		}
2526 		break;
2527 
2528 		case ZEND_INI_PARSER_SECTION:
2529 			break;
2530 	}
2531 }
2532 /* }}} */
2533 
2534 /* {{{ php_ini_parser_cb_with_sections */
2535 static void php_ini_parser_cb_with_sections(zval *arg1, zval *arg2, zval *arg3, int callback_type, zval *arr)
2536 {
2537 	if (callback_type == ZEND_INI_PARSER_SECTION) {
2538 		array_init(&BG(active_ini_file_section));
2539 		zend_symtable_update(Z_ARRVAL_P(arr), Z_STR_P(arg1), &BG(active_ini_file_section));
2540 	} else if (arg2) {
2541 		zval *active_arr;
2542 
2543 		if (Z_TYPE(BG(active_ini_file_section)) != IS_UNDEF) {
2544 			active_arr = &BG(active_ini_file_section);
2545 		} else {
2546 			active_arr = arr;
2547 		}
2548 
2549 		php_simple_ini_parser_cb(arg1, arg2, arg3, callback_type, active_arr);
2550 	}
2551 }
2552 /* }}} */
2553 
2554 /* {{{ Parse configuration file */
2555 PHP_FUNCTION(parse_ini_file)
2556 {
2557 	zend_string *filename = NULL;
2558 	bool process_sections = 0;
2559 	zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2560 	zend_file_handle fh;
2561 	zend_ini_parser_cb_t ini_parser_cb;
2562 
2563 	ZEND_PARSE_PARAMETERS_START(1, 3)
2564 		Z_PARAM_PATH_STR(filename)
2565 		Z_PARAM_OPTIONAL
2566 		Z_PARAM_BOOL(process_sections)
2567 		Z_PARAM_LONG(scanner_mode)
2568 	ZEND_PARSE_PARAMETERS_END();
2569 
2570 	if (ZSTR_LEN(filename) == 0) {
2571 		zend_argument_value_error(1, "cannot be empty");
2572 		RETURN_THROWS();
2573 	}
2574 
2575 	/* Set callback function */
2576 	if (process_sections) {
2577 		ZVAL_UNDEF(&BG(active_ini_file_section));
2578 		ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2579 	} else {
2580 		ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2581 	}
2582 
2583 	/* Setup filehandle */
2584 	zend_stream_init_filename_ex(&fh, filename);
2585 
2586 	array_init(return_value);
2587 	if (zend_parse_ini_file(&fh, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2588 		zend_array_destroy(Z_ARR_P(return_value));
2589 		RETVAL_FALSE;
2590 	}
2591 	zend_destroy_file_handle(&fh);
2592 }
2593 /* }}} */
2594 
2595 /* {{{ Parse configuration string */
2596 PHP_FUNCTION(parse_ini_string)
2597 {
2598 	char *string = NULL, *str = NULL;
2599 	size_t str_len = 0;
2600 	bool process_sections = 0;
2601 	zend_long scanner_mode = ZEND_INI_SCANNER_NORMAL;
2602 	zend_ini_parser_cb_t ini_parser_cb;
2603 
2604 	ZEND_PARSE_PARAMETERS_START(1, 3)
2605 		Z_PARAM_STRING(str, str_len)
2606 		Z_PARAM_OPTIONAL
2607 		Z_PARAM_BOOL(process_sections)
2608 		Z_PARAM_LONG(scanner_mode)
2609 	ZEND_PARSE_PARAMETERS_END();
2610 
2611 	if (INT_MAX - str_len < ZEND_MMAP_AHEAD) {
2612 		RETVAL_FALSE;
2613 	}
2614 
2615 	/* Set callback function */
2616 	if (process_sections) {
2617 		ZVAL_UNDEF(&BG(active_ini_file_section));
2618 		ini_parser_cb = (zend_ini_parser_cb_t) php_ini_parser_cb_with_sections;
2619 	} else {
2620 		ini_parser_cb = (zend_ini_parser_cb_t) php_simple_ini_parser_cb;
2621 	}
2622 
2623 	/* Setup string */
2624 	string = (char *) emalloc(str_len + ZEND_MMAP_AHEAD);
2625 	memcpy(string, str, str_len);
2626 	memset(string + str_len, 0, ZEND_MMAP_AHEAD);
2627 
2628 	array_init(return_value);
2629 	if (zend_parse_ini_string(string, 0, (int)scanner_mode, ini_parser_cb, return_value) == FAILURE) {
2630 		zend_array_destroy(Z_ARR_P(return_value));
2631 		RETVAL_FALSE;
2632 	}
2633 	efree(string);
2634 }
2635 /* }}} */
2636 
2637 #if ZEND_DEBUG
2638 /* This function returns an array of ALL valid ini options with values and
2639  *  is not the same as ini_get_all() which returns only registered ini options. Only useful for devs to debug php.ini scanner/parser! */
2640 PHP_FUNCTION(config_get_hash) /* {{{ */
2641 {
2642 	ZEND_PARSE_PARAMETERS_NONE();
2643 
2644 	HashTable *hash = php_ini_get_configuration_hash();
2645 
2646 	array_init(return_value);
2647 	add_config_entries(hash, return_value);
2648 }
2649 /* }}} */
2650 #endif
2651 
2652 #ifdef HAVE_GETLOADAVG
2653 /* {{{ */
2654 PHP_FUNCTION(sys_getloadavg)
2655 {
2656 	double load[3];
2657 
2658 	ZEND_PARSE_PARAMETERS_NONE();
2659 
2660 	if (getloadavg(load, 3) == -1) {
2661 		RETURN_FALSE;
2662 	} else {
2663 		array_init(return_value);
2664 		add_index_double(return_value, 0, load[0]);
2665 		add_index_double(return_value, 1, load[1]);
2666 		add_index_double(return_value, 2, load[2]);
2667 	}
2668 }
2669 /* }}} */
2670 #endif
2671