36
36
#include <fcntl.h>
37
37
#endif
38
38
39
+ #ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP
40
+ /* Only defined on glibc >= 2.29, FreeBSD CURRENT, musl >= 1.1.24,
41
+ * MacOS Catalina or later..
42
+ * It should be posible to modify this so it is also
43
+ * used in older systems when $cwd == NULL but care must be taken
44
+ * as at least glibc < 2.24 has a legacy implementation known
45
+ * to be really buggy.
46
+ */
47
+ #include <spawn.h>
48
+ #define USE_POSIX_SPAWN
49
+ #endif
50
+
39
51
/* This symbol is defined in ext/standard/config.m4.
40
52
* Essentially, it is set if you HAVE_FORK || PHP_WIN32
41
53
* Other platforms may modify that configure check and add suitable #ifdefs
@@ -982,6 +994,36 @@ static zend_result set_proc_descriptor_from_resource(zval *resource, descriptors
982
994
}
983
995
984
996
#ifndef PHP_WIN32
997
+ #if defined(USE_POSIX_SPAWN )
998
+ static zend_result close_parentends_of_pipes (posix_spawn_file_actions_t * actions , descriptorspec_item * descriptors , int ndesc )
999
+ {
1000
+ int r ;
1001
+ for (int i = 0 ; i < ndesc ; i ++ ) {
1002
+ if (descriptors [i ].type != DESCRIPTOR_TYPE_STD ) {
1003
+ r = posix_spawn_file_actions_addclose (actions , descriptors [i ].parentend );
1004
+ if (r != 0 ) {
1005
+ php_error_docref (NULL , E_WARNING , "Cannot close file descriptor %d: %s" , descriptors [i ].parentend , strerror (r ));
1006
+ return FAILURE ;
1007
+ }
1008
+ }
1009
+ if (descriptors [i ].childend != descriptors [i ].index ) {
1010
+ r = posix_spawn_file_actions_adddup2 (actions , descriptors [i ].childend , descriptors [i ].index );
1011
+ if (r != 0 ) {
1012
+ php_error_docref (NULL , E_WARNING , "Unable to copy file descriptor %d (for pipe) into "
1013
+ "file descriptor %d: %s" , descriptors [i ].childend , descriptors [i ].index , strerror (r ));
1014
+ return FAILURE ;
1015
+ }
1016
+ r = posix_spawn_file_actions_addclose (actions , descriptors [i ].childend );
1017
+ if (r != 0 ) {
1018
+ php_error_docref (NULL , E_WARNING , "Cannot close file descriptor %d: %s" , descriptors [i ].childend , strerror (r ));
1019
+ return FAILURE ;
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ return SUCCESS ;
1025
+ }
1026
+ #else
985
1027
static zend_result close_parentends_of_pipes (descriptorspec_item * descriptors , int ndesc )
986
1028
{
987
1029
/* We are running in child process
@@ -1005,6 +1047,7 @@ static zend_result close_parentends_of_pipes(descriptorspec_item *descriptors, i
1005
1047
return SUCCESS ;
1006
1048
}
1007
1049
#endif
1050
+ #endif
1008
1051
1009
1052
static void close_all_descriptors (descriptorspec_item * descriptors , int ndesc )
1010
1053
{
@@ -1216,6 +1259,37 @@ PHP_FUNCTION(proc_open)
1216
1259
childHandle = pi .hProcess ;
1217
1260
child = pi .dwProcessId ;
1218
1261
CloseHandle (pi .hThread );
1262
+ #elif defined(USE_POSIX_SPAWN )
1263
+ posix_spawn_file_actions_t factions ;
1264
+ int r ;
1265
+ posix_spawn_file_actions_init (& factions );
1266
+
1267
+ if (close_parentends_of_pipes (& factions , descriptors , ndesc ) == FAILURE ) {
1268
+ posix_spawn_file_actions_destroy (& factions );
1269
+ close_all_descriptors (descriptors , ndesc );
1270
+ goto exit_fail ;
1271
+ }
1272
+
1273
+ if (cwd ) {
1274
+ r = posix_spawn_file_actions_addchdir_np (& factions , cwd );
1275
+ if (r != 0 ) {
1276
+ php_error_docref (NULL , E_WARNING , "posix_spawn_file_actions_addchdir_np() failed: %s" , strerror (r ));
1277
+ }
1278
+ }
1279
+
1280
+ if (argv ) {
1281
+ r = posix_spawnp (& child , ZSTR_VAL (command_str ), & factions , NULL , argv , (env .envarray ? env .envarray : environ ));
1282
+ } else {
1283
+ r = posix_spawn (& child , "/bin/sh" , & factions , NULL ,
1284
+ (char * const []) {"sh" , "-c" , ZSTR_VAL (command_str ), NULL },
1285
+ env .envarray ? env .envarray : environ );
1286
+ }
1287
+ posix_spawn_file_actions_destroy (& factions );
1288
+ if (r != 0 ) {
1289
+ close_all_descriptors (descriptors , ndesc );
1290
+ php_error_docref (NULL , E_WARNING , "posix_spawn() failed: %s" , strerror (r ));
1291
+ goto exit_fail ;
1292
+ }
1219
1293
#elif HAVE_FORK
1220
1294
/* the Unix way */
1221
1295
child = fork ();
0 commit comments