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