]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[core, mod_commands] Execute command under shell when using spawn in switch_system().
authorChris Rienzo <chris@signalwire.com>
Tue, 9 Feb 2021 18:19:22 +0000 (13:19 -0500)
committerAndrey Volk <andywolk@gmail.com>
Fri, 16 Jul 2021 14:34:53 +0000 (17:34 +0300)
src/include/switch_core.h
src/mod/applications/mod_commands/mod_commands.c
src/switch_core.c
tests/unit/conf/freeswitch.xml
tests/unit/switch_core.c

index e2dfa57afc0b849c851fee10139cbcadd6443cdb..4f172a928e0225fbcaae2202e55f7c98d5ad3ba0 100644 (file)
@@ -2843,7 +2843,7 @@ SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_han
 SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
 
 SWITCH_DECLARE(int) switch_spawn(const char *cmd, switch_bool_t wait);
-SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, switch_stream_handle_t *stream);
+SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t shell, switch_bool_t wait, switch_stream_handle_t *stream);
 
 SWITCH_DECLARE(void) switch_core_session_debug_pool(switch_stream_handle_t *stream);
 
index 6c36d26d2a4def6559dfa43a88c8ae4a9efa61a0..ad5bd51ce973a0baf27bd01d060273ce556b3203 100644 (file)
@@ -6530,7 +6530,7 @@ SWITCH_STANDARD_API(spawn_stream_function)
                return SWITCH_STATUS_SUCCESS;
        }
 
-       if (switch_stream_spawn(cmd, SWITCH_TRUE, stream) < 0) {
+       if (switch_stream_spawn(cmd, SWITCH_FALSE, SWITCH_TRUE, stream) < 0) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Failed to execute command: %s\n", cmd);
        }
 
index 617b6237535847b84eff210ecc73eb998ac94a51..2589d276a4aceb05467026950f24325ac5dd935f 100644 (file)
@@ -3361,17 +3361,21 @@ static int switch_system_fork(const char *cmd, switch_bool_t wait)
 
 SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait)
 {
+       int retval = 0;
 #ifdef __linux__
        switch_bool_t spawn_instead_of_system = switch_true(switch_core_get_variable("spawn_instead_of_system"));
 #else
        switch_bool_t spawn_instead_of_system = SWITCH_FALSE;
 #endif
-       int (*sys_p)(const char *cmd, switch_bool_t wait);
-
-       sys_p = spawn_instead_of_system ? switch_spawn : switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork;
-
-       return sys_p(cmd, wait);
-
+       
+       if (spawn_instead_of_system) {
+               retval = switch_stream_spawn(cmd, SWITCH_TRUE, wait, NULL);
+       } else if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) {
+               retval = switch_system_thread(cmd, wait);
+       } else {
+               retval = switch_system_fork(cmd, wait);
+       }
+       return retval;
 }
 
 
@@ -3385,7 +3389,7 @@ SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_han
 extern char **environ;
 #endif
 
-SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, switch_stream_handle_t *stream)
+SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t shell, switch_bool_t wait, switch_stream_handle_t *stream)
 {
 #ifndef __linux__
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "posix_spawn is unsupported on current platform\n");
@@ -3406,18 +3410,27 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
                return 1;
        }
 
-       if (!(pdata = strdup(cmd))) {
-               return 1;
-       }
-
-       if (!switch_separate_string(pdata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
-               free(pdata);
-               return 1;
+       if (shell) {
+               argv[0] = switch_core_get_variable("spawn_system_shell");
+               argv[1] = "-c";
+               argv[2] = (char *)cmd;
+               argv[3] = NULL;
+               if (zstr(argv[0])) {
+                       argv[0] = "/bin/sh";
+               }
+       } else {
+               if (!(pdata = strdup(cmd))) {
+                       return 1;
+               }
+               if (!switch_separate_string(pdata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
+                       free(pdata);
+                       return 1;
+               }
        }
 
        if (!(attr = malloc(sizeof(posix_spawnattr_t)))) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute switch_spawn_stream because of a memory error: %s\n", cmd);
-               free(pdata);
+               switch_safe_free(pdata);
                return 1;
        }
 
@@ -3425,7 +3438,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
                if (pipe(cout_pipe)) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute switch_spawn_stream because of a pipe error: %s\n", cmd);
                        free(attr);
-                       free(pdata);
+                       switch_safe_free(pdata);
                        return 1;
                }
 
@@ -3434,7 +3447,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
                        close(cout_pipe[0]);
                        close(cout_pipe[1]);
                        free(attr);
-                       free(pdata);
+                       switch_safe_free(pdata);
                        return 1;
                }
        }
@@ -3505,7 +3518,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
        posix_spawnattr_destroy(attr);
        free(attr);
        posix_spawn_file_actions_destroy(&action);
-       free(pdata);
+       switch_safe_free(pdata);
 
        return status;
 #endif
@@ -3513,7 +3526,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
 
 SWITCH_DECLARE(int) switch_spawn(const char *cmd, switch_bool_t wait)
 {
-       return switch_stream_spawn(cmd, wait, NULL);
+       return switch_stream_spawn(cmd, SWITCH_FALSE, wait, NULL);
 }
 
 SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max)
@@ -3549,7 +3562,7 @@ SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t
 #endif
 
        if (spawn_instead_of_system){
-               return switch_stream_spawn(cmd, SWITCH_TRUE, stream);
+               return switch_stream_spawn(cmd, SWITCH_TRUE, SWITCH_TRUE, stream);
        } else {
                char buffer[128];
                size_t bytes;
index 578a4fe2b77aa07b83bff62f29ea8e1c36252a5a..3dcb33198bea4f14df998a227eb3ec78cfc3bac6 100644 (file)
@@ -1,6 +1,9 @@
 <?xml version="1.0"?>
 <document type="freeswitch/xml">
   <X-PRE-PROCESS cmd="exec-set" data="test=echo 1234"/>
+  <X-PRE-PROCESS cmd="set" data="spawn_instead_of_system=true"/>
+  <X-PRE-PROCESS cmd="exec-set" data="shell_exec_set_test=ls / | grep usr"/>
+  <X-PRE-PROCESS cmd="set" data="spawn_instead_of_system=false"/>
   <X-PRE-PROCESS cmd="set" data="default_password=$${test}"/>
   <section name="configuration" description="Various Configuration">
     <configuration name="modules.conf" description="Modules">
index 44cfe148bf04005914e20d2cbd8c4132e138d3fd..bba7272cac13847ac1530a7403b44ffcd9fe590a 100644 (file)
 
 FST_CORE_BEGIN("./conf")
 {
-       FST_SUITE_BEGIN(switch_ivr_originate)
+       FST_SUITE_BEGIN(switch_core)
        {
                FST_SETUP_BEGIN()
                {
+                       switch_core_set_variable("spawn_instead_of_system", "false");
                }
                FST_SETUP_END()
 
@@ -101,17 +102,17 @@ FST_CORE_BEGIN("./conf")
 #ifndef WIN32
                FST_TEST_BEGIN(test_fork)
                {
-            switch_stream_handle_t exec_result = { 0 };
-               SWITCH_STANDARD_STREAM(exec_result);
-               fst_requires(switch_stream_system_fork("ip ad sh", &exec_result) == 0);
-                   fst_requires(!zstr(exec_result.data));
-            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)exec_result.data);
+                       switch_stream_handle_t exec_result = { 0 };
+                       SWITCH_STANDARD_STREAM(exec_result);
+                       fst_requires(switch_stream_system_fork("ip ad sh", &exec_result) == 0);
+                       fst_requires(!zstr(exec_result.data));
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)exec_result.data);
 
-               fst_requires(switch_stream_system_fork("ip ad sh | grep link", &exec_result) == 0);
-                   fst_requires(!zstr(exec_result.data));
-            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)exec_result.data);
+                       fst_requires(switch_stream_system_fork("ip ad sh | grep link", &exec_result) == 0);
+                       fst_requires(!zstr(exec_result.data));
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)exec_result.data);
 
-            switch_safe_free(exec_result.data);
+                       switch_safe_free(exec_result.data);
                }
                FST_TEST_END()
 #endif
@@ -171,13 +172,13 @@ FST_CORE_BEGIN("./conf")
                        fst_check_int_equals(status, 0);
 
                        SWITCH_STANDARD_STREAM(stream);
-                       status = switch_stream_spawn("echo DEADBEEF", SWITCH_TRUE, &stream);
+                       status = switch_stream_spawn("echo DEADBEEF", SWITCH_FALSE, SWITCH_TRUE, &stream);
                        fst_check_int_equals(status, 0);
                        fst_check_string_equals(stream.data, "DEADBEEF\n");
                        switch_safe_free(stream.data);
 
                        SWITCH_STANDARD_STREAM(stream);
-                       status = switch_stream_spawn("echo DEADBEEF", SWITCH_FALSE, &stream);
+                       status = switch_stream_spawn("echo DEADBEEF", SWITCH_FALSE, SWITCH_FALSE, &stream);
                        fst_check_int_equals(status, 0);
                        fst_check_string_equals(stream.data, "DEADBEEF\n");
                        switch_safe_free(stream.data);
@@ -191,6 +192,34 @@ FST_CORE_BEGIN("./conf")
 
                        status = switch_spawn("true", SWITCH_TRUE);
                        fct_chk_eq_int(status, 0);
+#endif
+               }
+               FST_TEST_END()
+
+               FST_TEST_BEGIN(test_switch_spawn_instead_of_system)
+               {
+#ifdef __linux__
+                       int status;
+                       char file_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+                       const char *filename = NULL;
+                       const char *cmd = NULL;
+
+                       // tell FS core to use posix_spawn() instead of popen() and friends
+                       switch_core_set_variable("spawn_instead_of_system", "true");
+
+                       // echo text to a file using shell redirection- this will ensure the command was executed in a shell, as expected
+                       switch_uuid_str(file_uuid, sizeof(file_uuid));
+                       filename = switch_core_sprintf(fst_pool, "%s" SWITCH_PATH_SEPARATOR "%s", SWITCH_GLOBAL_dirs.temp_dir, file_uuid);
+                       cmd = switch_core_sprintf(fst_pool, "echo test_switch_spawn_instead_of_system with spaces > %s", filename);
+                       status = switch_system(cmd, SWITCH_TRUE);
+
+                       fst_check_int_equals(status, 0);
+                       fst_xcheck(status == 0, "Expect switch_system() command to return 0");
+                       fst_xcheck(switch_file_exists(filename, fst_pool) == SWITCH_STATUS_SUCCESS, "Expect switch_system() to use shell to create file via > redirection");
+                       unlink(filename);
+
+                       // verify exec-set works- see conf/freeswitch.xml for test setup of shell_exec_set_test global variable
+                       fst_check_string_equals(switch_core_get_variable("shell_exec_set_test"), "usr");
 #endif
                }
                FST_TEST_END()