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