38#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP
47#define USE_POSIX_SPAWN
54#ifdef PHP_CAN_SUPPORT_PROC_OPEN
59# elif defined(__FreeBSD__)
62# elif defined(__NetBSD__) || defined(__DragonFly__)
64# if defined(__NetBSD__)
65# include <sys/termios.h>
69extern int openpty(
int *,
int *,
char *,
struct termios *,
struct winsize *);
80# define HAVE_OPENPTY 1
83int openpty(
int *master,
int *slave,
char *
name,
struct termios *termp,
struct winsize *winp)
91 sd = *master = *slave = -1;
92 fd = open(
"/dev/ptmx", O_NOCTTY|O_RDWR);
97 if (grantpt(
fd) != 0 || unlockpt(
fd) != 0) {
100 slaveid = ptsname(
fd);
106 sd = open(slaveid, O_NOCTTY|O_RDONLY);
107 if (sd == -1 || ioctl(sd, I_PUSH,
"ptem") == -1) {
111 if (tcgetattr(sd, termp) < 0) {
116 if (ioctl(sd, TIOCSWINSZ, winp) == -1) {
137static int le_proc_open;
155 memset(&env, 0,
sizeof(env));
161 uint32_t cnt = zend_hash_num_elements(
Z_ARRVAL_P(environment));
176 str = zval_get_string(element);
187 zend_hash_add_ptr(env_hash,
key, str);
189 zend_hash_next_index_insert_ptr(env_hash, str);
238#ifdef HAVE_SYS_WAIT_H
241 if (proc->has_cached_exit_wait_status) {
242 *wait_status = proc->cached_exit_wait_status_value;
246 pid_t wait_pid = waitpid(proc->
child, wait_status,
options);
251 if (wait_pid > 0 && WIFEXITED(*wait_status)) {
252 proc->has_cached_exit_wait_status =
true;
253 proc->cached_exit_wait_status_value = *wait_status;
270 int waitpid_options = 0;
275 for (
int i = 0; i < proc->
npipes; i++) {
288 if (
FG(pclose_wait)) {
289 WaitForSingleObject(proc->childHandle, INFINITE);
291 GetExitCodeProcess(proc->childHandle, &wstatus);
292 if (wstatus == STILL_ACTIVE) {
295 FG(pclose_ret) = wstatus;
297 CloseHandle(proc->childHandle);
300 if (!
FG(pclose_wait)) {
304 wait_pid = waitpid_cached(proc, &wstatus, waitpid_options);
305 }
while (wait_pid == -1 &&
errno == EINTR);
310 if (WIFEXITED(wstatus)) {
311 wstatus = WEXITSTATUS(wstatus);
313 FG(pclose_ret) = wstatus;
320 _php_free_envp(proc->
env);
355 RETURN_BOOL(TerminateProcess(proc->childHandle, 255));
395 bool running = 1, signaled = 0, stopped = 0;
396 int exitcode = -1, termsig = 0, stopsig = 0;
412 GetExitCodeProcess(proc->childHandle, &wstatus);
413 running = wstatus == STILL_ACTIVE;
414 exitcode =
running ? -1 : wstatus;
423 if (wait_pid == proc->
child) {
424 if (WIFEXITED(wstatus)) {
426 exitcode = WEXITSTATUS(wstatus);
428 if (WIFSIGNALED(wstatus)) {
431 termsig = WTERMSIG(wstatus);
433 if (WIFSTOPPED(wstatus)) {
435 stopsig = WSTOPSIG(wstatus);
437 }
else if (wait_pid == -1) {
443 add_assoc_bool(
return_value,
"cached", proc->has_cached_exit_wait_status);
460SECURITY_ATTRIBUTES php_proc_open_security = {
461 .nLength =
sizeof(SECURITY_ATTRIBUTES),
462 .lpSecurityDescriptor =
NULL,
463 .bInheritHandle =
TRUE
466# define pipe(pair) (CreatePipe(&pair[0], &pair[1], &php_proc_open_security, 0) ? 0 : -1)
468# define COMSPEC_NT "cmd.exe"
470static inline HANDLE dup_handle(HANDLE src,
BOOL inherit,
BOOL closeorig)
472 HANDLE
copy, self = GetCurrentProcess();
474 if (!DuplicateHandle(self, src, self, &
copy, 0, inherit, DUPLICATE_SAME_ACCESS |
475 (closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
480static inline HANDLE dup_fd_as_handle(
int fd)
482 return dup_handle((HANDLE)_get_osfhandle(
fd),
TRUE,
FALSE);
485# define close_descriptor(fd) CloseHandle(fd)
487# define close_descriptor(fd) close(fd)
491typedef enum _descriptor_type {
493 DESCRIPTOR_TYPE_PIPE,
494 DESCRIPTOR_TYPE_SOCKET
499typedef struct _descriptorspec_item {
501 descriptor_type
type;
507} descriptorspec_item;
515 if (elem_num == 1 &&
ZSTR_LEN(str) == 0) {
517 zend_string_release(str);
522 zend_value_error(
"Command array element %d contains a null byte", elem_num);
523 zend_string_release(str);
531static void append_backslashes(
smart_str *str,
size_t num_bs)
533 for (
size_t i = 0; i < num_bs; i++) {
534 smart_str_appendc(str,
'\\');
538const char *special_chars =
"()!^\"<>&|%";
555 bool has_special_character =
false;
557 if (is_cmd_argument) {
558 has_special_character = is_special_character_present(
arg);
559 if (has_special_character) {
561 smart_str_appendc(str,
'^');
564 smart_str_appendc(str,
'"');
574 num_bs = num_bs * 2 + 1;
576 append_backslashes(str, num_bs);
577 if (has_special_character &&
strchr(special_chars, c) !=
NULL) {
579 smart_str_appendc(str,
'^');
581 smart_str_appendc(str, c);
584 append_backslashes(str, num_bs * 2);
585 if (has_special_character) {
587 smart_str_appendc(str,
'^');
589 smart_str_appendc(str,
'"');
592static bool is_executed_by_cmd(
const char *prog_name,
size_t prog_name_length)
595 WCHAR long_name[MAX_PATH];
596 WCHAR full_name[MAX_PATH];
597 LPWSTR file_part =
NULL;
599 wchar_t *prog_name_wide = php_win32_cp_conv_any_to_w(prog_name, prog_name_length, &out_len);
601 if (GetLongPathNameW(prog_name_wide, long_name, MAX_PATH) == 0) {
604 lstrcpynW(long_name, prog_name_wide, MAX_PATH);
607 free(prog_name_wide);
608 prog_name_wide =
NULL;
610 if (GetFullPathNameW(long_name, MAX_PATH, full_name, &file_part) == 0 || file_part ==
NULL) {
614 bool uses_cmd =
false;
615 if (_wcsicmp(file_part, L
"cmd.exe") == 0 || _wcsicmp(file_part, L
"cmd") == 0) {
618 const WCHAR *extension_dot = wcsrchr(file_part, L
'.');
619 if (extension_dot && (_wcsicmp(extension_dot, L
".bat") == 0 || _wcsicmp(extension_dot, L
".cmd") == 0)) {
631 bool is_prog_name =
true;
632 bool is_cmd_execution =
false;
636 zend_string *arg_str = get_valid_arg_string(arg_zv, ++elem_num);
638 smart_str_free(&str);
643 is_cmd_execution = is_executed_by_cmd(
ZSTR_VAL(arg_str),
ZSTR_LEN(arg_str));
645 smart_str_appendc(&str,
' ');
648 append_win_escaped_arg(&str, arg_str, !is_prog_name && is_cmd_execution);
651 zend_string_release(arg_str);
659static bool get_option(
zval *other_options,
char *opt_name,
size_t opt_name_len)
662 zval *item = zend_hash_str_find_deref(opt_ary, opt_name, opt_name_len);
663 return item !=
NULL &&
670static void init_startup_info(STARTUPINFOW *si, descriptorspec_item *descriptors,
int ndesc)
672 memset(si, 0,
sizeof(STARTUPINFOW));
673 si->cb =
sizeof(STARTUPINFOW);
674 si->dwFlags = STARTF_USESTDHANDLES;
676 si->hStdInput = GetStdHandle(STD_INPUT_HANDLE);
677 si->hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
678 si->hStdError = GetStdHandle(STD_ERROR_HANDLE);
681 for (
int i = 0; i < ndesc; i++) {
682 switch (descriptors[i].index) {
684 si->hStdInput = descriptors[i].childend;
687 si->hStdOutput = descriptors[i].childend;
690 si->hStdError = descriptors[i].childend;
696static void init_process_info(PROCESS_INFORMATION *
pi)
702static size_t find_comspec_nt(
wchar_t **comspec)
705 wchar_t *pathw =
NULL;
706 wchar_t *bufp =
NULL;
717 bufp =
emalloc(buflen *
sizeof(
wchar_t));
722 len = SearchPathW(pathw, L
"cmd.exe",
NULL, buflen, bufp,
NULL);
730 bufp =
erealloc(bufp, buflen *
sizeof(
wchar_t));
736 zend_string_release(path);
741 if (bufp !=
NULL && bufp != *comspec) {
747static zend_result convert_command_to_use_shell(
wchar_t **cmdw,
size_t cmdw_len)
750 size_t len = find_comspec_nt(&comspec);
755 len +=
sizeof(
" /s /c ") + cmdw_len + 3;
756 wchar_t *cmdw_shell = (
wchar_t *)malloc(
len *
sizeof(
wchar_t));
758 if (cmdw_shell ==
NULL) {
764 if (_snwprintf(cmdw_shell,
len, L
"%s /s /c \"%s\"", comspec, *cmdw) == -1) {
789 zend_string *arg_str = get_valid_arg_string(arg_zv, i + 1);
793 if (command !=
NULL) {
800 command = zend_string_copy(arg_str);
804 zend_string_release(arg_str);
811static descriptorspec_item* alloc_descriptor_array(
HashTable *descriptorspec)
813 uint32_t ndescriptors = zend_hash_num_elements(descriptorspec);
814 return ecalloc(ndescriptors,
sizeof(descriptorspec_item));
817static zend_string* get_string_parameter(
zval *array,
int index,
char *param_name)
824 return zval_try_get_string(array_item);
827static zend_result set_proc_descriptor_to_blackhole(descriptorspec_item *desc)
830 desc->childend = CreateFileA(
"nul", GENERIC_READ | GENERIC_WRITE,
831 FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0,
NULL);
832 if (desc->childend ==
NULL) {
837 desc->childend = open(
"/dev/null", O_RDWR);
838 if (desc->childend < 0) {
846static zend_result set_proc_descriptor_to_pty(descriptorspec_item *desc,
int *master_fd,
int *slave_fd)
854 if (*master_fd == -1) {
861 desc->type = DESCRIPTOR_TYPE_PIPE;
862 desc->childend = dup(*slave_fd);
863 desc->parentend = dup(*master_fd);
864 desc->mode_flags = O_RDWR;
878#if defined(F_SETFD) && defined(FD_CLOEXEC)
894 desc->type = DESCRIPTOR_TYPE_PIPE;
897 desc->parentend = newpipe[1];
898 desc->childend = newpipe[0];
899 desc->mode_flags = O_WRONLY;
901 desc->parentend = newpipe[0];
902 desc->childend = newpipe[1];
903 desc->mode_flags = O_RDONLY;
906 desc->parentend = make_descriptor_cloexec(desc->parentend);
917#define create_socketpair(socks) socketpair_win32(AF_INET, SOCK_STREAM, 0, (socks), 0)
919#define create_socketpair(socks) socketpair(AF_UNIX, SOCK_STREAM, 0, (socks))
922static zend_result set_proc_descriptor_to_socket(descriptorspec_item *desc)
926 if (create_socketpair(sock)) {
929 zend_string_release(
err);
933 desc->type = DESCRIPTOR_TYPE_SOCKET;
950 if (stream ==
NULL) {
961 desc->childend = dup_fd_as_handle((
int)
fd);
967 SetFilePointer(desc->childend, 0,
NULL, FILE_END);
988 nindex, strerror(
errno));
995static zend_result redirect_proc_descriptor(descriptorspec_item *desc,
int target,
996 descriptorspec_item *descriptors,
int ndesc,
int nindex)
1000 for (
int i = 0; i < ndesc; i++) {
1001 if (descriptors[i].index == target) {
1002 redirect_to = descriptors[i].childend;
1008 if (target < 0 || target > 2) {
1016 redirect_to = target;
1019 case 0: redirect_to = GetStdHandle(STD_INPUT_HANDLE);
break;
1020 case 1: redirect_to = GetStdHandle(STD_OUTPUT_HANDLE);
break;
1021 case 2: redirect_to = GetStdHandle(STD_ERROR_HANDLE);
break;
1027 return dup_proc_descriptor(redirect_to, &desc->childend, nindex);
1031static zend_result set_proc_descriptor_from_array(
zval *descitem, descriptorspec_item *descriptors,
1032 int ndesc,
int nindex,
int *pty_master_fd,
int *pty_slave_fd) {
1033 zend_string *
ztype = get_string_parameter(descitem, 0,
"handle qualifier");
1043 zmode = get_string_parameter(descitem, 1,
"mode parameter for 'pipe'");
1044 if (zmode ==
NULL) {
1047 retval = set_proc_descriptor_to_pipe(&descriptors[ndesc], zmode);
1050 retval = set_proc_descriptor_to_socket(&descriptors[ndesc]);
1053 if ((zfile = get_string_parameter(descitem, 1,
"file name parameter for 'file'")) ==
NULL) {
1056 if ((zmode = get_string_parameter(descitem, 2,
"mode parameter for 'file'")) ==
NULL) {
1059 retval = set_proc_descriptor_to_file(&descriptors[ndesc], zfile, zmode);
1062 zval *ztarget = zend_hash_index_find_deref(
Z_ARRVAL_P(descitem), 1);
1072 retval = redirect_proc_descriptor(
1073 &descriptors[ndesc], (
int)
Z_LVAL_P(ztarget), descriptors, ndesc, nindex);
1074 }
else if (zend_string_equals(
ztype,
ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE))) {
1076 retval = set_proc_descriptor_to_blackhole(&descriptors[ndesc]);
1079 retval = set_proc_descriptor_to_pty(&descriptors[ndesc], pty_master_fd, pty_slave_fd);
1086 if (zmode) zend_string_release(zmode);
1087 if (zfile) zend_string_release(zfile);
1088 zend_string_release(
ztype);
1092static zend_result set_proc_descriptor_from_resource(
zval *resource, descriptorspec_item *desc,
int nindex)
1097 if (stream ==
NULL) {
1112 return dup_proc_descriptor(fd_t, &desc->childend, nindex);
1116#if defined(USE_POSIX_SPAWN)
1117static zend_result close_parentends_of_pipes(posix_spawn_file_actions_t * actions, descriptorspec_item *descriptors,
int ndesc)
1120 for (
int i = 0; i < ndesc; i++) {
1121 if (descriptors[i].
type != DESCRIPTOR_TYPE_STD) {
1122 r = posix_spawn_file_actions_addclose(actions, descriptors[i].parentend);
1128 if (descriptors[i].childend != descriptors[i].index) {
1129 r = posix_spawn_file_actions_adddup2(actions, descriptors[i].childend, descriptors[i].index);
1132 "file descriptor %d: %s", descriptors[i].childend, descriptors[i].index, strerror(r));
1135 r = posix_spawn_file_actions_addclose(actions, descriptors[i].childend);
1146static zend_result close_parentends_of_pipes(descriptorspec_item *descriptors,
int ndesc)
1152 for (
int i = 0; i < ndesc; i++) {
1153 if (descriptors[i].
type != DESCRIPTOR_TYPE_STD) {
1154 close(descriptors[i].parentend);
1156 if (descriptors[i].childend != descriptors[i].index) {
1157 if (dup2(descriptors[i].childend, descriptors[i].index) < 0) {
1159 "file descriptor %d: %s", descriptors[i].childend, descriptors[i].index, strerror(
errno));
1162 close(descriptors[i].childend);
1171static void close_all_descriptors(descriptorspec_item *descriptors,
int ndesc)
1173 for (
int i = 0; i < ndesc; i++) {
1174 close_descriptor(descriptors[i].childend);
1175 if (descriptors[i].parentend)
1176 close_descriptor(descriptors[i].parentend);
1180static void efree_argv(
char **argv)
1209 descriptorspec_item *descriptors =
NULL;
1211 PROCESS_INFORMATION
pi;
1215 DWORD dwCreateFlags = 0;
1216 UINT old_error_mode;
1220 bool suppress_errors = 0;
1221 bool bypass_shell = 0;
1222 bool blocking_pipes = 0;
1223 bool create_process_group = 0;
1224 bool create_new_console = 0;
1228 int pty_master_fd = -1, pty_slave_fd = -1;
1245 uint32_t num_elems = zend_hash_num_elements(command_ht);
1246 if (num_elems == 0) {
1254 command_str = create_win_command_from_args(command_ht);
1256 command_str = get_command_from_array(command_ht, &argv, num_elems);
1266 zend_string_addref(command_str);
1270 if (other_options) {
1271 suppress_errors = get_option(other_options,
"suppress_errors",
strlen(
"suppress_errors"));
1273 bypass_shell = bypass_shell || get_option(other_options,
"bypass_shell",
strlen(
"bypass_shell"));
1274 blocking_pipes = get_option(other_options,
"blocking_pipes",
strlen(
"blocking_pipes"));
1275 create_process_group = get_option(other_options,
"create_process_group",
strlen(
"create_process_group"));
1276 create_new_console = get_option(other_options,
"create_new_console",
strlen(
"create_new_console"));
1281 env = _php_array_to_envp(environment);
1284 descriptors = alloc_descriptor_array(descriptorspec);
1293 descriptors[ndesc].index = (int)nindex;
1297 if (set_proc_descriptor_from_resource(descitem, &descriptors[ndesc], ndesc) ==
FAILURE) {
1301 if (set_proc_descriptor_from_array(descitem, descriptors, ndesc, (
int)nindex,
1302 &pty_master_fd, &pty_slave_fd) ==
FAILURE) {
1315 if (!getcwd_result) {
1327 init_startup_info(&si, descriptors, ndesc);
1328 init_process_info(&
pi);
1330 if (suppress_errors) {
1331 old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX);
1334 dwCreateFlags = NORMAL_PRIORITY_CLASS;
1336 dwCreateFlags |= CREATE_NO_WINDOW;
1338 if (create_process_group) {
1339 dwCreateFlags |= CREATE_NEW_PROCESS_GROUP;
1341 if (create_new_console) {
1342 dwCreateFlags |= CREATE_NEW_CONSOLE;
1346 dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT;
1354 cmdw = php_win32_cp_conv_any_to_w(
ZSTR_VAL(command_str),
ZSTR_LEN(command_str), &cmdw_len);
1360 if (!bypass_shell) {
1361 if (convert_command_to_use_shell(&cmdw, cmdw_len) ==
FAILURE) {
1365 newprocok = CreateProcessW(
NULL, cmdw, &php_proc_open_security,
1366 &php_proc_open_security,
TRUE, dwCreateFlags, envpw, cwdw, &si, &
pi);
1368 if (suppress_errors) {
1369 SetErrorMode(old_error_mode);
1372 if (newprocok ==
FALSE) {
1373 DWORD dw = GetLastError();
1374 close_all_descriptors(descriptors, ndesc);
1381 childHandle =
pi.hProcess;
1382 child =
pi.dwProcessId;
1383 CloseHandle(
pi.hThread);
1384#elif defined(USE_POSIX_SPAWN)
1385 posix_spawn_file_actions_t factions;
1387 posix_spawn_file_actions_init(&factions);
1389 if (close_parentends_of_pipes(&factions, descriptors, ndesc) ==
FAILURE) {
1390 posix_spawn_file_actions_destroy(&factions);
1391 close_all_descriptors(descriptors, ndesc);
1396 r = posix_spawn_file_actions_addchdir_np(&factions,
cwd);
1403 r = posix_spawnp(&child,
ZSTR_VAL(command_str), &factions,
NULL, argv, (env.envarray ? env.envarray :
environ));
1405 r = posix_spawn(&child,
"/bin/sh" , &factions,
NULL,
1406 (
char *
const[]) {
"sh",
"-c",
ZSTR_VAL(command_str),
NULL},
1407 env.envarray ? env.envarray :
environ);
1409 posix_spawn_file_actions_destroy(&factions);
1411 close_all_descriptors(descriptors, ndesc);
1415#elif defined(HAVE_FORK)
1422 if (close_parentends_of_pipes(descriptors, ndesc) ==
FAILURE) {
1438 execvp(
ZSTR_VAL(command_str), argv);
1441 execle(
"/bin/sh",
"sh",
"-c",
ZSTR_VAL(command_str),
NULL, env.envarray);
1443 execl(
"/bin/sh",
"sh",
"-c",
ZSTR_VAL(command_str),
NULL);
1451 }
else if (child < 0) {
1453 close_all_descriptors(descriptors, ndesc);
1458# error You lose (configure should not have let you get here)
1463 pipes = zend_try_array_init(pipes);
1469 proc->
command = zend_string_copy(command_str);
1472 proc->
child = child;
1474 proc->childHandle = childHandle;
1477#ifdef HAVE_SYS_WAIT_H
1478 proc->has_cached_exit_wait_status =
false;
1483 for (i = 0; i < ndesc; i++) {
1486 close_descriptor(descriptors[i].childend);
1488 if (descriptors[i].
type == DESCRIPTOR_TYPE_PIPE) {
1489 char *mode_string =
NULL;
1491 switch (descriptors[i].mode_flags) {
1513 descriptors[i].mode_flags), mode_string,
NULL);
1518 }
else if (descriptors[i].
type == DESCRIPTOR_TYPE_SOCKET) {
1531 add_index_zval(pipes, descriptors[i].index, &retfp);
1542 _php_free_envp(env);
1555 if (pty_master_fd != -1) {
1556 close(pty_master_fd);
1558 if (pty_slave_fd != -1) {
1559 close(pty_slave_fd);
SAPI_API sapi_module_struct sapi_module
PHPAPI zend_string * php_getenv(const char *str, size_t str_len)
proc_open(array|string $command, array $descriptor_spec, &$pipes, ?string $cwd=null, ?array $env_vars=null, ?array $options=null)
proc_get_status($process)
sizeof(Countable|array $value, int $mode=COUNT_NORMAL)
proc_terminate($process, int $signal=15)
copy(string $from, string $to, $context=null)
assert(mixed $assertion, Throwable|string|null $description=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
PW32CP wchar_t * php_win32_cp_env_any_to_w(const char *env)
#define php_win32_cp_any_to_w(in)
memset(ptr, 0, type->size)
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
PHPAPI zend_string * php_socket_error_str(long err)
#define PHP_MINIT_FUNCTION
#define php_ignore_value(x)
PHP_JSON_API size_t int options
#define php_stream_sock_open_from_socket(socket, persistent)
#define php_socket_errno()
php_output_handler * running
unsigned char key[REFLECTION_KEY_LEN]
#define php_stream_fopen_from_fd(fd, mode, persistent_id)
#define php_stream_cast(stream, as, ret, show_err)
struct _php_stream php_stream
#define PHP_STREAM_CAST_RELEASE
#define PHP_STREAM_FLAG_NO_SEEK
#define php_stream_to_zval(stream, zval)
#define php_stream_open_wrapper(path, mode, options, opened)
#define php_stream_set_option(stream, option, value, ptrvalue)
#define PHP_STREAM_OPTION_PIPE_BLOCKING
PHPAPI int php_file_le_stream(void)
int php_file_descriptor_t
struct _php_process_env php_process_env
struct _php_process_handle php_process_handle
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
ZEND_API const char * zend_zval_value_name(const zval *arg)
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
#define Z_PARAM_ARRAY_OR_NULL(dest)
#define ZEND_PARSE_PARAMETERS_END()
#define Z_PARAM_RESOURCE(dest)
#define Z_PARAM_STRING_OR_NULL(dest, dest_len)
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
#define Z_PARAM_ARRAY_HT_OR_STR(dest_ht, dest_str)
#define Z_PARAM_LONG(dest)
#define Z_PARAM_ARRAY_HT(dest)
#define Z_PARAM_ZVAL(dest)
#define ecalloc(nmemb, size)
#define FREE_HASHTABLE(ht)
#define erealloc(ptr, size)
#define safe_emalloc(nmemb, size, offset)
#define ALLOC_HASHTABLE(ht)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val)
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
ZEND_API void * zend_fetch_resource(zend_resource *res, const char *resource_type_name, int resource_type)
ZEND_API zend_resource * zend_register_resource(void *rsrc_pointer, int rsrc_type)
ZEND_API void ZEND_FASTCALL zend_list_close(zend_resource *res)
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
struct _zend_string zend_string
#define EMPTY_SWITCH_DEFAULT_CASE()
#define zend_string_equals_literal(str, literal)
#define zend_string_starts_with_literal(str, prefix)
#define Z_ARRVAL_P(zval_p)
struct _zend_resource zend_resource
struct _zend_array HashTable
ZEND_RESULT_CODE zend_result
#define VCWD_GETCWD(buff, size)