56
56
57
57
static int le_proc_open ;
58
58
59
+ /* {{{ _php_array_to_envp */
60
+ static php_process_env_t _php_array_to_envp (zval * environment , int is_persistent TSRMLS_DC )
61
+ {
62
+ zval * * element ;
63
+ php_process_env_t env ;
64
+ char * string_key , * data ;
65
+ #ifndef PHP_WIN32
66
+ char * * ep ;
67
+ #endif
68
+ char * p ;
69
+ uint string_length , cnt , l , sizeenv = 0 , el_len ;
70
+ ulong num_key ;
71
+ HashTable * target_hash ;
72
+ HashPosition pos ;
73
+
74
+ memset (& env , 0 , sizeof (env ));
75
+
76
+ if (!environment ) {
77
+ return env ;
78
+ }
79
+
80
+ cnt = zend_hash_num_elements (Z_ARRVAL_P (environment ));
81
+
82
+ if (cnt < 1 ) {
83
+ return env ;
84
+ }
85
+
86
+ target_hash = HASH_OF (environment );
87
+ if (!target_hash ) {
88
+ return env ;
89
+ }
90
+
91
+ /* first, we have to get the size of all the elements in the hash */
92
+ for (zend_hash_internal_pointer_reset_ex (target_hash , & pos );
93
+ zend_hash_get_current_data_ex (target_hash , (void * * ) & element , & pos ) == SUCCESS ;
94
+ zend_hash_move_forward_ex (target_hash , & pos )) {
95
+
96
+ convert_to_string_ex (element );
97
+ el_len = Z_STRLEN_PP (element );
98
+ if (el_len == 0 ) {
99
+ continue ;
100
+ }
101
+
102
+ sizeenv += el_len + 1 ;
103
+
104
+ switch (zend_hash_get_current_key_ex (target_hash , & string_key , & string_length , & num_key , 0 , & pos )) {
105
+ case HASH_KEY_IS_STRING :
106
+ if (string_length == 0 ) {
107
+ continue ;
108
+ }
109
+ sizeenv += string_length + 1 ;
110
+ break ;
111
+ }
112
+ }
113
+
114
+ #ifndef PHP_WIN32
115
+ ep = env .envarray = (char * * ) pecalloc (cnt + 1 , sizeof (char * ), is_persistent );
116
+ #endif
117
+ p = env .envp = (char * ) pecalloc (sizeenv + 4 , 1 , is_persistent );
118
+
119
+ for (zend_hash_internal_pointer_reset_ex (target_hash , & pos );
120
+ zend_hash_get_current_data_ex (target_hash , (void * * ) & element , & pos ) == SUCCESS ;
121
+ zend_hash_move_forward_ex (target_hash , & pos )) {
122
+
123
+ convert_to_string_ex (element );
124
+ el_len = Z_STRLEN_PP (element );
125
+
126
+ if (el_len == 0 ) {
127
+ continue ;
128
+ }
129
+
130
+ data = Z_STRVAL_PP (element );
131
+ switch (zend_hash_get_current_key_ex (target_hash , & string_key , & string_length , & num_key , 0 , & pos )) {
132
+ case HASH_KEY_IS_STRING :
133
+ if (string_length == 0 ) {
134
+ continue ;
135
+ }
136
+ l = string_length + el_len + 1 ;
137
+ memcpy (p , string_key , string_length );
138
+ strcat (p , "=" );
139
+ strcat (p , data );
140
+
141
+ if (PG (magic_quotes_gpc )) {
142
+ php_stripslashes (p , & l TSRMLS_CC );
143
+ }
144
+ #ifndef PHP_WIN32
145
+ * ep = p ;
146
+ ++ ep ;
147
+ #endif
148
+ p += l ;
149
+ break ;
150
+ case HASH_KEY_IS_LONG :
151
+ memcpy (p ,data ,el_len );
152
+ if (PG (magic_quotes_gpc )) {
153
+ php_stripslashes (p , & el_len TSRMLS_CC );
154
+ }
155
+ #ifndef PHP_WIN32
156
+ * ep = p ;
157
+ ++ ep ;
158
+ #endif
159
+ p += el_len + 1 ;
160
+ break ;
161
+ case HASH_KEY_NON_EXISTANT :
162
+ break ;
163
+ }
164
+ }
165
+
166
+ assert (p - env .envp <= sizeenv );
167
+
168
+ zend_hash_internal_pointer_reset_ex (target_hash , & pos );
169
+
170
+ return env ;
171
+ }
172
+ /* }}} */
173
+
174
+ /* {{{ _php_free_envp */
175
+ static void _php_free_envp (php_process_env_t env , int is_persistent )
176
+ {
177
+ #ifndef PHP_WIN32
178
+ if (env .envarray ) {
179
+ pefree (env .envarray , is_persistent );
180
+ }
181
+ #endif
182
+ if (env .envp ) {
183
+ pefree (env .envp , is_persistent );
184
+ }
185
+ }
186
+ /* }}} */
187
+
188
+
59
189
static void proc_open_rsrc_dtor (zend_rsrc_list_entry * rsrc TSRMLS_DC )
60
190
{
61
191
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)
98
228
#else
99
229
FG (pclose_ret ) = -1 ;
100
230
#endif
101
-
231
+ _php_free_envp ( proc -> env , proc -> is_persistent );
102
232
pefree (proc -> command , proc -> is_persistent );
103
233
pefree (proc , proc -> is_persistent );
104
234
@@ -166,8 +296,6 @@ static int php_make_safe_mode_command(char *cmd, char **safecmd, int is_persiste
166
296
}
167
297
/* }}} */
168
298
169
-
170
-
171
299
PHP_MINIT_FUNCTION (proc_open )
172
300
{
173
301
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 {
321
449
};
322
450
/* }}} */
323
451
324
- /* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes)
452
+ /* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes [, string cwd [, array env]] )
325
453
Run a process with more control over it's file descriptors */
326
454
PHP_FUNCTION (proc_open )
327
455
{
328
456
329
- char * command ;
330
- long command_len ;
457
+ char * command , * cwd = NULL ;
458
+ long command_len , cwd_len ;
331
459
zval * descriptorspec ;
332
460
zval * pipes ;
461
+ zval * environment = NULL ;
462
+ php_process_env_t env ;
333
463
int ndesc = 0 ;
334
464
int i ;
335
465
zval * * descitem = NULL ;
@@ -346,8 +476,8 @@ PHP_FUNCTION(proc_open)
346
476
struct php_process_handle * proc ;
347
477
int is_persistent = 0 ; /* TODO: ensure that persistent procs will work */
348
478
349
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "saz/" , & command ,
350
- & command_len , & descriptorspec , & pipes ) == FAILURE ) {
479
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "saz/|sa! " , & command ,
480
+ & command_len , & descriptorspec , & pipes , & cwd , & cwd_len , & environment ) == FAILURE ) {
351
481
RETURN_FALSE ;
352
482
}
353
483
@@ -357,6 +487,12 @@ PHP_FUNCTION(proc_open)
357
487
358
488
command_len = strlen (command );
359
489
490
+ if (environment ) {
491
+ env = _php_array_to_envp (environment , is_persistent TSRMLS_CC );
492
+ } else {
493
+ memset (& env , 0 , sizeof (env ));
494
+ }
495
+
360
496
memset (descriptors , 0 , sizeof (descriptors ));
361
497
362
498
#ifdef PHP_WIN32
@@ -538,7 +674,7 @@ PHP_FUNCTION(proc_open)
538
674
539
675
command_with_cmd = emalloc (command_len + sizeof (COMSPEC_9X ) + 1 + sizeof (" /c " ));
540
676
sprintf (command_with_cmd , "%s /c %s" , GetVersion () < 0x80000000 ? COMSPEC_NT : COMSPEC_9X , command );
541
- newprocok = CreateProcess (NULL , command_with_cmd , & security , & security , TRUE, NORMAL_PRIORITY_CLASS , NULL , NULL , & si , & pi );
677
+ newprocok = CreateProcess (NULL , command_with_cmd , & security , & security , TRUE, NORMAL_PRIORITY_CLASS , env . envp , cwd , & si , & pi );
542
678
efree (command_with_cmd );
543
679
544
680
if (FALSE == newprocok ) {
@@ -551,7 +687,6 @@ PHP_FUNCTION(proc_open)
551
687
552
688
#elif HAVE_FORK
553
689
/* the unix way */
554
-
555
690
child = fork ();
556
691
557
692
if (child == 0 ) {
@@ -571,8 +706,15 @@ PHP_FUNCTION(proc_open)
571
706
if (descriptors [i ].childend != descriptors [i ].index )
572
707
close (descriptors [i ].childend );
573
708
}
574
-
575
- execl ("/bin/sh" , "sh" , "-c" , command , NULL );
709
+ if (cwd ) {
710
+ chdir (cwd );
711
+ }
712
+
713
+ if (env .envarray ) {
714
+ execle ("/bin/sh" , "sh" , "-c" , command , NULL , env .envarray );
715
+ } else {
716
+ execl ("/bin/sh" , "sh" , "-c" , command , NULL );
717
+ }
576
718
_exit (127 );
577
719
578
720
} else if (child < 0 ) {
@@ -599,6 +741,7 @@ PHP_FUNCTION(proc_open)
599
741
proc -> command = command ;
600
742
proc -> npipes = ndesc ;
601
743
proc -> child = child ;
744
+ proc -> env = env ;
602
745
603
746
array_init (pipes );
604
747
@@ -657,6 +800,7 @@ PHP_FUNCTION(proc_open)
657
800
return ;
658
801
659
802
exit_fail :
803
+ _php_free_envp (env , is_persistent );
660
804
pefree (command , is_persistent );
661
805
RETURN_FALSE ;
662
806
0 commit comments