diff options
author | Wez Furlong <wez@php.net> | 2003-02-16 15:38:54 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-02-16 15:38:54 +0000 |
commit | 7e92f636ef142d4200138b05e6be69863a491b2d (patch) | |
tree | f1c3dc425b3a34c01be64f911bc88f34e795c342 /ext/standard/proc_open.c | |
parent | c40eff35dae89f1f32376be48d652cf483a33140 (diff) | |
download | php-git-7e92f636ef142d4200138b05e6be69863a491b2d.tar.gz |
Integrate Shanes patch that allows specifying the cwd and environment
for the child process created by proc_open().
Diffstat (limited to 'ext/standard/proc_open.c')
-rw-r--r-- | ext/standard/proc_open.c | 168 |
1 files changed, 156 insertions, 12 deletions
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 367d4dded8..5e91fec7f8 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -56,6 +56,136 @@ static int le_proc_open; +/* {{{ _php_array_to_envp */ +static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent TSRMLS_DC) +{ + zval **element; + php_process_env_t env; + char *string_key, *data; +#ifndef PHP_WIN32 + char **ep; +#endif + char *p; + uint string_length, cnt, l, sizeenv=0, el_len; + ulong num_key; + HashTable *target_hash; + HashPosition pos; + + memset(&env, 0, sizeof(env)); + + if (!environment) { + return env; + } + + cnt = zend_hash_num_elements(Z_ARRVAL_P(environment)); + + if (cnt < 1) { + return env; + } + + target_hash = HASH_OF(environment); + if (!target_hash) { + return env; + } + + /* first, we have to get the size of all the elements in the hash */ + for (zend_hash_internal_pointer_reset_ex(target_hash, &pos); + zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS; + zend_hash_move_forward_ex(target_hash, &pos)) { + + convert_to_string_ex(element); + el_len = Z_STRLEN_PP(element); + if (el_len == 0) { + continue; + } + + sizeenv += el_len+1; + + switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, &pos)) { + case HASH_KEY_IS_STRING: + if (string_length == 0) { + continue; + } + sizeenv += string_length+1; + break; + } + } + +#ifndef PHP_WIN32 + ep = env.envarray = (char **) pecalloc(cnt + 1, sizeof(char *), is_persistent); +#endif + p = env.envp = (char *) pecalloc(sizeenv + 4, 1, is_persistent); + + for (zend_hash_internal_pointer_reset_ex(target_hash, &pos); + zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS; + zend_hash_move_forward_ex(target_hash, &pos)) { + + convert_to_string_ex(element); + el_len = Z_STRLEN_PP(element); + + if (el_len == 0) { + continue; + } + + data = Z_STRVAL_PP(element); + switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, &pos)) { + case HASH_KEY_IS_STRING: + if (string_length == 0) { + continue; + } + l = string_length + el_len + 1; + memcpy(p, string_key, string_length); + strcat(p, "="); + strcat(p, data); + + if (PG(magic_quotes_gpc)) { + php_stripslashes(p, &l TSRMLS_CC); + } +#ifndef PHP_WIN32 + *ep = p; + ++ep; +#endif + p += l; + break; + case HASH_KEY_IS_LONG: + memcpy(p,data,el_len); + if (PG(magic_quotes_gpc)) { + php_stripslashes(p, &el_len TSRMLS_CC); + } +#ifndef PHP_WIN32 + *ep = p; + ++ep; +#endif + p += el_len + 1; + break; + case HASH_KEY_NON_EXISTANT: + break; + } + } + + assert(p - env.envp <= sizeenv); + + zend_hash_internal_pointer_reset_ex(target_hash, &pos); + + return env; +} +/* }}} */ + +/* {{{ _php_free_envp */ +static void _php_free_envp(php_process_env_t env, int is_persistent) +{ +#ifndef PHP_WIN32 + if (env.envarray) { + pefree(env.envarray, is_persistent); + } +#endif + if (env.envp) { + pefree(env.envp, is_persistent); + } +} +/* }}} */ + + static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { struct php_process_handle *proc = (struct php_process_handle*)rsrc->ptr; @@ -98,7 +228,7 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) #else FG(pclose_ret) = -1; #endif - + _php_free_envp(proc->env, proc->is_persistent); pefree(proc->command, proc->is_persistent); pefree(proc, proc->is_persistent); @@ -166,8 +296,6 @@ static int php_make_safe_mode_command(char *cmd, char **safecmd, int is_persiste } /* }}} */ - - PHP_MINIT_FUNCTION(proc_open) { le_proc_open = zend_register_list_destructors_ex(proc_open_rsrc_dtor, NULL, "process", module_number); @@ -321,15 +449,17 @@ struct php_proc_open_descriptor_item { }; /* }}} */ -/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes) +/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes [, string cwd [, array env]]) Run a process with more control over it's file descriptors */ PHP_FUNCTION(proc_open) { - char *command; - long command_len; + char *command, *cwd=NULL; + long command_len, cwd_len; zval *descriptorspec; zval *pipes; + zval *environment = NULL; + php_process_env_t env; int ndesc = 0; int i; zval **descitem = NULL; @@ -346,8 +476,8 @@ PHP_FUNCTION(proc_open) struct php_process_handle *proc; int is_persistent = 0; /* TODO: ensure that persistent procs will work */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saz/", &command, - &command_len, &descriptorspec, &pipes) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saz/|sa!", &command, + &command_len, &descriptorspec, &pipes, &cwd, &cwd_len, &environment) == FAILURE) { RETURN_FALSE; } @@ -357,6 +487,12 @@ PHP_FUNCTION(proc_open) command_len = strlen(command); + if (environment) { + env = _php_array_to_envp(environment, is_persistent TSRMLS_CC); + } else { + memset(&env, 0, sizeof(env)); + } + memset(descriptors, 0, sizeof(descriptors)); #ifdef PHP_WIN32 @@ -538,7 +674,7 @@ PHP_FUNCTION(proc_open) command_with_cmd = emalloc(command_len + sizeof(COMSPEC_9X) + 1 + sizeof(" /c ")); sprintf(command_with_cmd, "%s /c %s", GetVersion() < 0x80000000 ? COMSPEC_NT : COMSPEC_9X, command); - newprocok = CreateProcess(NULL, command_with_cmd, &security, &security, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); + newprocok = CreateProcess(NULL, command_with_cmd, &security, &security, TRUE, NORMAL_PRIORITY_CLASS, env.envp, cwd, &si, &pi); efree(command_with_cmd); if (FALSE == newprocok) { @@ -551,7 +687,6 @@ PHP_FUNCTION(proc_open) #elif HAVE_FORK /* the unix way */ - child = fork(); if (child == 0) { @@ -571,8 +706,15 @@ PHP_FUNCTION(proc_open) if (descriptors[i].childend != descriptors[i].index) close(descriptors[i].childend); } - - execl("/bin/sh", "sh", "-c", command, NULL); + if (cwd) { + chdir(cwd); + } + + if (env.envarray) { + execle("/bin/sh", "sh", "-c", command, NULL, env.envarray); + } else { + execl("/bin/sh", "sh", "-c", command, NULL); + } _exit(127); } else if (child < 0) { @@ -599,6 +741,7 @@ PHP_FUNCTION(proc_open) proc->command = command; proc->npipes = ndesc; proc->child = child; + proc->env = env; array_init(pipes); @@ -657,6 +800,7 @@ PHP_FUNCTION(proc_open) return; exit_fail: + _php_free_envp(env, is_persistent); pefree(command, is_persistent); RETURN_FALSE; |