wez             Sun Feb 16 10:38:54 2003 EDT

  Modified files:              
    /php4/ext/standard  proc_open.c proc_open.h 
  Log:
  Integrate Shanes patch that allows specifying the cwd and environment
  for the child process created by proc_open().
  
  
Index: php4/ext/standard/proc_open.c
diff -u php4/ext/standard/proc_open.c:1.5 php4/ext/standard/proc_open.c:1.6
--- php4/ext/standard/proc_open.c:1.5   Sat Feb 15 12:33:11 2003
+++ php4/ext/standard/proc_open.c       Sun Feb 16 10:38:54 2003
@@ -15,7 +15,7 @@
    | Author: Wez Furlong <[EMAIL PROTECTED]>                           |
    +----------------------------------------------------------------------+
  */
-/* $Id: proc_open.c,v 1.5 2003/02/15 17:33:11 wez Exp $ */
+/* $Id: proc_open.c,v 1.6 2003/02/16 15:38:54 wez Exp $ */
 
 #include <stdio.h>
 #include "php.h"
@@ -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 @@
 #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 @@
 }
 /* }}} */
 
-
-
 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 @@
 };
 /* }}} */
 
-/* {{{ 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 @@
        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 @@
 
        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 @@
        
        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 @@
 
 #elif HAVE_FORK
        /* the unix way */
-
        child = fork();
 
        if (child == 0) {
@@ -571,8 +706,15 @@
                        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 @@
        proc->command = command;
        proc->npipes = ndesc;
        proc->child = child;
+       proc->env = env;
 
        array_init(pipes);
 
@@ -657,6 +800,7 @@
        return;
 
 exit_fail:
+       _php_free_envp(env, is_persistent);
        pefree(command, is_persistent);
        RETURN_FALSE;
 
Index: php4/ext/standard/proc_open.h
diff -u php4/ext/standard/proc_open.h:1.1 php4/ext/standard/proc_open.h:1.2
--- php4/ext/standard/proc_open.h:1.1   Wed Jan 15 13:54:03 2003
+++ php4/ext/standard/proc_open.h       Sun Feb 16 10:38:54 2003
@@ -15,7 +15,7 @@
    | Author: Wez Furlong <[EMAIL PROTECTED]>                           |
    +----------------------------------------------------------------------+
  */
-/* $Id: proc_open.h,v 1.1 2003/01/15 18:54:03 wez Exp $ */
+/* $Id: proc_open.h,v 1.2 2003/02/16 15:38:54 wez Exp $ */
 
 #ifdef PHP_WIN32
 typedef HANDLE php_file_descriptor_t;
@@ -27,11 +27,23 @@
 
 #define PHP_PROC_OPEN_MAX_DESCRIPTORS  16
 
+/* Environment block under win32 is a NUL terminated sequence of NUL terminated
+ * name=value strings.
+ * Under unix, it is an argv style array.
+ * */
+typedef struct _php_process_env {
+       char *envp;
+#ifndef PHP_WIN32
+       char **envarray;
+#endif
+} php_process_env_t;
+
 struct php_process_handle {
        php_process_id_t        child;
        int npipes;
        long pipes[PHP_PROC_OPEN_MAX_DESCRIPTORS];
        char *command;
        int is_persistent;
+       php_process_env_t env;
 };
 



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to