The attached patch adds 2 optional parameters to proc_open(). The first, cwd, and the second is an array for executing with a custom environment. I've tested this on w2k and osx. Comments, fixes, changes, and testing on Linux, would be appreciated.

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

Reply via email to