Shane
Index: ext/standard/proc_open.c =================================================================== RCS file: /repository/php4/ext/standard/proc_open.c,v retrieving revision 1.3 diff -u -d -u -r1.3 proc_open.c --- ext/standard/proc_open.c 24 Jan 2003 16:45:34 -0000 1.3 +++ ext/standard/proc_open.c 10 Feb 2003 07:31:43 -0000 @@ -56,6 +56,111 @@ static int le_proc_open; +/* {{{ _php_array_to_envp */ +static char *_php_array_to_envp(zval *environment, int is_persistent TSRMLS_DC) +{ + zval **element; + char *envp, *p; +#ifndef PHP_WIN32 + char **myenvp, **ep; +#endif + char *string_key, *data; + uint string_length, cnt, l, sizeenv=0, el_len; + ulong num_key; + HashTable *target_hash; + HashPosition pos; + + if (!environment) return NULL; + cnt = zend_hash_num_elements(Z_ARRVAL_P(environment)); + if (cnt < 1) return NULL; + + target_hash = HASH_OF(environment); + if (!target_hash) return NULL; + + /* 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; + } + } + +#ifndef PHP_WIN32 + ep = myenvp = (char **) calloc(cnt+1,sizeof(char *)); +#endif + p = envp = (char *) calloc(sizeenv+4,1); + + 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-envp <= sizeenv); + zend_hash_internal_pointer_reset_ex(target_hash, &pos); +#ifdef PHP_WIN32 + return envp; +#else + return (char *)myenvp; +#endif +} +/* }}} */ + +/* {{{ _php_free_envp */ +static void _php_free_envp(char *envp) +{ + if (envp) { +#ifndef PHP_WIN32 + free(*envp); +#endif + free(envp); + } +} +/* }}} */ + + 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 +203,7 @@ #else FG(pclose_ret) = -1; #endif - + _php_free_envp(proc->envp); pefree(proc->command, proc->is_persistent); pefree(proc, proc->is_persistent); @@ -166,8 +271,6 @@ } /* }}} */ - - PHP_MINIT_FUNCTION(proc_open) { le_proc_open = zend_register_list_destructors_ex(proc_open_rsrc_dtor, NULL, "process", module_number); @@ -294,15 +397,17 @@ }; /* }}} */ -/* {{{ 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; + char *envp = NULL; int ndesc = 0; int i; zval **descitem = NULL; @@ -319,8 +424,8 @@ 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; } @@ -330,6 +435,11 @@ command_len = strlen(command); + if (environment) { + envp = _php_array_to_envp(environment, is_persistent TSRMLS_CC); + } + if (cwd_len == 0) cwd = NULL; + memset(descriptors, 0, sizeof(descriptors)); #ifdef PHP_WIN32 @@ -511,7 +621,7 @@ 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, envp, cwd, &si, &pi); efree(command_with_cmd); if (FALSE == newprocok) { @@ -544,8 +654,14 @@ if (descriptors[i].childend != descriptors[i].index) close(descriptors[i].childend); } - - execl("/bin/sh", "sh", "-c", command, NULL); + if (cwd) { + chdir(cwd); + } + if (envp) { + execle("/bin/sh", "sh", "-c", command, NULL, (char **)envp); + } else { + execl("/bin/sh", "sh", "-c", command, NULL); + } _exit(127); } else if (child < 0) { @@ -572,6 +688,7 @@ proc->command = command; proc->npipes = ndesc; proc->child = child; + proc->envp = envp; array_init(pipes); @@ -630,6 +747,7 @@ return; exit_fail: + _php_free_envp(envp); pefree(command, is_persistent); RETURN_FALSE; Index: ext/standard/proc_open.h =================================================================== RCS file: /repository/php4/ext/standard/proc_open.h,v retrieving revision 1.1 diff -u -d -u -r1.1 proc_open.h --- ext/standard/proc_open.h 15 Jan 2003 18:54:03 -0000 1.1 +++ ext/standard/proc_open.h 10 Feb 2003 07:31:43 -0000 @@ -33,5 +33,6 @@ long pipes[PHP_PROC_OPEN_MAX_DESCRIPTORS]; char *command; int is_persistent; + char *envp; };
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php