[core, mod_commands] Execute command under shell when using spawn in switch_system().
This commit is contained in:
parent
9aee9b8e24
commit
311e932df5
|
@ -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_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_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);
|
SWITCH_DECLARE(void) switch_core_session_debug_pool(switch_stream_handle_t *stream);
|
||||||
|
|
||||||
|
|
|
@ -6530,7 +6530,7 @@ SWITCH_STANDARD_API(spawn_stream_function)
|
||||||
return SWITCH_STATUS_SUCCESS;
|
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);
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Failed to execute command: %s\n", cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait)
|
||||||
{
|
{
|
||||||
|
int retval = 0;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
switch_bool_t spawn_instead_of_system = switch_true(switch_core_get_variable("spawn_instead_of_system"));
|
switch_bool_t spawn_instead_of_system = switch_true(switch_core_get_variable("spawn_instead_of_system"));
|
||||||
#else
|
#else
|
||||||
switch_bool_t spawn_instead_of_system = SWITCH_FALSE;
|
switch_bool_t spawn_instead_of_system = SWITCH_FALSE;
|
||||||
#endif
|
#endif
|
||||||
int (*sys_p)(const char *cmd, switch_bool_t wait);
|
|
||||||
|
if (spawn_instead_of_system) {
|
||||||
sys_p = spawn_instead_of_system ? switch_spawn : switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork;
|
retval = switch_stream_spawn(cmd, SWITCH_TRUE, wait, NULL);
|
||||||
|
} else if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) {
|
||||||
return sys_p(cmd, wait);
|
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;
|
extern char **environ;
|
||||||
#endif
|
#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__
|
#ifndef __linux__
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "posix_spawn is unsupported on current platform\n");
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pdata = strdup(cmd))) {
|
if (shell) {
|
||||||
return 1;
|
argv[0] = switch_core_get_variable("spawn_system_shell");
|
||||||
}
|
argv[1] = "-c";
|
||||||
|
argv[2] = (char *)cmd;
|
||||||
if (!switch_separate_string(pdata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
|
argv[3] = NULL;
|
||||||
free(pdata);
|
if (zstr(argv[0])) {
|
||||||
return 1;
|
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)))) {
|
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);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3425,7 +3438,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
|
||||||
if (pipe(cout_pipe)) {
|
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);
|
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(attr);
|
||||||
free(pdata);
|
switch_safe_free(pdata);
|
||||||
return 1;
|
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[0]);
|
||||||
close(cout_pipe[1]);
|
close(cout_pipe[1]);
|
||||||
free(attr);
|
free(attr);
|
||||||
free(pdata);
|
switch_safe_free(pdata);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3505,7 +3518,7 @@ SWITCH_DECLARE(int) switch_stream_spawn(const char *cmd, switch_bool_t wait, swi
|
||||||
posix_spawnattr_destroy(attr);
|
posix_spawnattr_destroy(attr);
|
||||||
free(attr);
|
free(attr);
|
||||||
posix_spawn_file_actions_destroy(&action);
|
posix_spawn_file_actions_destroy(&action);
|
||||||
free(pdata);
|
switch_safe_free(pdata);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
#endif
|
#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)
|
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)
|
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
|
#endif
|
||||||
|
|
||||||
if (spawn_instead_of_system){
|
if (spawn_instead_of_system){
|
||||||
return switch_stream_spawn(cmd, SWITCH_TRUE, stream);
|
return switch_stream_spawn(cmd, SWITCH_TRUE, SWITCH_TRUE, stream);
|
||||||
} else {
|
} else {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<document type="freeswitch/xml">
|
<document type="freeswitch/xml">
|
||||||
<X-PRE-PROCESS cmd="exec-set" data="test=echo 1234"/>
|
<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}"/>
|
<X-PRE-PROCESS cmd="set" data="default_password=$${test}"/>
|
||||||
<section name="configuration" description="Various Configuration">
|
<section name="configuration" description="Various Configuration">
|
||||||
<configuration name="modules.conf" description="Modules">
|
<configuration name="modules.conf" description="Modules">
|
||||||
|
|
|
@ -40,10 +40,11 @@
|
||||||
|
|
||||||
FST_CORE_BEGIN("./conf")
|
FST_CORE_BEGIN("./conf")
|
||||||
{
|
{
|
||||||
FST_SUITE_BEGIN(switch_ivr_originate)
|
FST_SUITE_BEGIN(switch_core)
|
||||||
{
|
{
|
||||||
FST_SETUP_BEGIN()
|
FST_SETUP_BEGIN()
|
||||||
{
|
{
|
||||||
|
switch_core_set_variable("spawn_instead_of_system", "false");
|
||||||
}
|
}
|
||||||
FST_SETUP_END()
|
FST_SETUP_END()
|
||||||
|
|
||||||
|
@ -101,17 +102,17 @@ FST_CORE_BEGIN("./conf")
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
FST_TEST_BEGIN(test_fork)
|
FST_TEST_BEGIN(test_fork)
|
||||||
{
|
{
|
||||||
switch_stream_handle_t exec_result = { 0 };
|
switch_stream_handle_t exec_result = { 0 };
|
||||||
SWITCH_STANDARD_STREAM(exec_result);
|
SWITCH_STANDARD_STREAM(exec_result);
|
||||||
fst_requires(switch_stream_system_fork("ip ad sh", &exec_result) == 0);
|
fst_requires(switch_stream_system_fork("ip ad sh", &exec_result) == 0);
|
||||||
fst_requires(!zstr(exec_result.data));
|
fst_requires(!zstr(exec_result.data));
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)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(switch_stream_system_fork("ip ad sh | grep link", &exec_result) == 0);
|
||||||
fst_requires(!zstr(exec_result.data));
|
fst_requires(!zstr(exec_result.data));
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", (char *)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()
|
FST_TEST_END()
|
||||||
#endif
|
#endif
|
||||||
|
@ -171,13 +172,13 @@ FST_CORE_BEGIN("./conf")
|
||||||
fst_check_int_equals(status, 0);
|
fst_check_int_equals(status, 0);
|
||||||
|
|
||||||
SWITCH_STANDARD_STREAM(stream);
|
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_int_equals(status, 0);
|
||||||
fst_check_string_equals(stream.data, "DEADBEEF\n");
|
fst_check_string_equals(stream.data, "DEADBEEF\n");
|
||||||
switch_safe_free(stream.data);
|
switch_safe_free(stream.data);
|
||||||
|
|
||||||
SWITCH_STANDARD_STREAM(stream);
|
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_int_equals(status, 0);
|
||||||
fst_check_string_equals(stream.data, "DEADBEEF\n");
|
fst_check_string_equals(stream.data, "DEADBEEF\n");
|
||||||
switch_safe_free(stream.data);
|
switch_safe_free(stream.data);
|
||||||
|
@ -191,6 +192,34 @@ FST_CORE_BEGIN("./conf")
|
||||||
|
|
||||||
status = switch_spawn("true", SWITCH_TRUE);
|
status = switch_spawn("true", SWITCH_TRUE);
|
||||||
fct_chk_eq_int(status, 0);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
FST_TEST_END()
|
FST_TEST_END()
|
||||||
|
|
Loading…
Reference in New Issue