From 099a10b88c3cf45e4ed9f9ea5fc8b7ee00ac5099 Mon Sep 17 00:00:00 2001 From: Stanislav Litvinenko Date: Sun, 20 Oct 2019 23:55:39 +0300 Subject: [PATCH 1/2] Improvements to function Added 'exec verify' to wait for a return code and verify it --- include/actions.hpp | 1 + src/actions.cpp | 2 ++ src/call.cpp | 76 +++++++++++++++++++++++++++++++-------------- src/scenario.cpp | 3 ++ 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/include/actions.hpp b/include/actions.hpp index d7fa8d8c1..3a543cc30 100644 --- a/include/actions.hpp +++ b/include/actions.hpp @@ -57,6 +57,7 @@ class CAction E_AT_LOG_WARNING, E_AT_LOG_ERROR, E_AT_EXECUTE_CMD, + E_AT_VERIFY_CMD, E_AT_EXEC_INTCMD, E_AT_VAR_ADD, E_AT_VAR_SUBTRACT, diff --git a/src/actions.cpp b/src/actions.cpp index a216f4c51..ce7b1661b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -111,6 +111,8 @@ void CAction::afficheInfo() } } else if (M_action == E_AT_EXECUTE_CMD) { printf("Type[%d] - command[%-32.32s]", M_action, M_message_str[0]); + } else if (M_action == E_AT_VERIFY_CMD) { + printf("Type[%d] - verify[%-32.32s]", M_action, M_message_str[0]); } else if (M_action == E_AT_EXEC_INTCMD) { printf("Type[%d] - intcmd[%-32.32s]", M_action, strIntCmd(M_IntCmd)); } else if (M_action == E_AT_LOG_TO_FILE) { diff --git a/src/call.cpp b/src/call.cpp index a44573db0..db053c9cf 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -3243,6 +3243,30 @@ double call::get_rhs(CAction *currentAction) } } +void execute_system_shell_and_exit(char *x) +{ +// Execute shell in different ways via compiler check. +// This is required because cygwin wrongly returns true for system(0) +// even when the shell is not available +// For some reason if system is invoked when sh is not available the program seg faults. +// This is avoided by ifdef'ing out the system() call in favor of exec of cmd.exe on Windows. +#ifndef __CYGWIN + int ret = system(x); // second child runs + if(ret == -1) { + WARNING("system call error for %s",x); + } + TRACE_MSG("Exec of '%s' returned %d", x, WEXITSTATUS(ret)); + exit(WEXITSTATUS(ret)); + + +#else + // sh not available, use exec(command) + int ret = execlp("cmd.exe", "cmd.exe", "/c", x, (char *) NULL); + ERROR_NO("Exec of 'cmd.exe /c %s' failed", x); +#endif + +} + call::T_ActionResult call::executeAction(const char* msg, message* curmsg) { CActions* actions; @@ -3671,8 +3695,11 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg) } else if (currentAction->getActionType() == CAction::E_AT_LOG_ERROR) { char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/); ERROR("%s", x); - } else if (currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) { + } else if ((currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) || + (currentAction->getActionType() == CAction::E_AT_VERIFY_CMD)) { char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/); + bool verify_result = (currentAction->getActionType() == CAction::E_AT_VERIFY_CMD); + // TRACE_MSG("Trying to execute [%s]", x); pid_t l_pid; switch(l_pid = fork()) { @@ -3683,41 +3710,42 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg) case 0: // first child process - execute the command - if((l_pid = fork()) < 0) { - ERROR_NO("Forking error child"); + if (verify_result) { + /* run command in this process and return exit code to waiting main sipp process */ + execute_system_shell_and_exit(x); } else { - if( l_pid == 0) { - int ret; - ret = system(x); // second child runs - if(ret == -1) { - WARNING("system call error for %s", x); + if((l_pid = fork()) < 0) { + ERROR_NO("Forking error child"); + } else { + if( l_pid == 0) { + int ret; + ret = system(x); // second child runs + if(ret == -1) { + WARNING("system call error for %s", x); + } } + exit(EXIT_OTHER); } - exit(EXIT_OTHER); } break; default: // parent process continue // reap first child immediately pid_t ret; - while ((ret=waitpid(l_pid, NULL, 0)) != l_pid) { + int status; + while ((ret=waitpid(l_pid, &status, 0)) != l_pid) { if (ret != -1) { - ERROR("waitpid returns %1ld for child %1ld", (long) ret, (long) l_pid); + ERROR("waitpid returns %1d for child %1d", ret,l_pid); } } - break; - } - } else if (currentAction->getActionType() == CAction::E_AT_EXEC_INTCMD) { - switch (currentAction->getIntCmd()) { - case CAction::E_INTCMD_STOP_ALL: - quitting = 1; - break; - case CAction::E_INTCMD_STOP_NOW: - sipp_exit(EXIT_TEST_RES_INTERNAL); - break; - case CAction::E_INTCMD_STOPCALL: - default: - return(call::E_AR_STOP_CALL); + if (verify_result) { + if (!WIFEXITED(status)) { + ERROR("'%s' did not exit normally (status = %d)", x, status); + } else if (WEXITSTATUS(status) != EXIT_SUCCESS) { + ERROR("'%s' returned result code %d", x, WEXITSTATUS(status)); + } + } + break; } #ifdef PCAPPLAY diff --git a/src/scenario.cpp b/src/scenario.cpp index 4236820aa..ada25728e 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -1618,6 +1618,9 @@ void scenario::parseAction(CActions *actions) if ((cptr = xp_get_value("command"))) { tmpAction->setActionType(CAction::E_AT_EXECUTE_CMD); tmpAction->setMessage(cptr); + } else if((cptr = xp_get_value((char *)"verify"))) { + tmpAction->setActionType(CAction::E_AT_VERIFY_CMD); + tmpAction->setMessage(cptr); } else if((cptr = xp_get_value("int_cmd"))) { CAction::T_IntCmdType type(CAction::E_INTCMD_STOPCALL); /* assume the default */ From aa52c003229472f9319e26a511359e4ac225f6e0 Mon Sep 17 00:00:00 2001 From: Stanislav Litvinenko Date: Mon, 21 Oct 2019 23:59:52 +0300 Subject: [PATCH 2/2] Fixed indentation --- src/call.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/call.cpp b/src/call.cpp index db053c9cf..0be13506c 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -3251,18 +3251,17 @@ void execute_system_shell_and_exit(char *x) // For some reason if system is invoked when sh is not available the program seg faults. // This is avoided by ifdef'ing out the system() call in favor of exec of cmd.exe on Windows. #ifndef __CYGWIN - int ret = system(x); // second child runs - if(ret == -1) { - WARNING("system call error for %s",x); - } - TRACE_MSG("Exec of '%s' returned %d", x, WEXITSTATUS(ret)); - exit(WEXITSTATUS(ret)); - + int ret = system(x); // second child runs + if(ret == -1) { + WARNING("system call error for %s",x); + } + TRACE_MSG("Exec of '%s' returned %d", x, WEXITSTATUS(ret)); + exit(WEXITSTATUS(ret)); #else - // sh not available, use exec(command) - int ret = execlp("cmd.exe", "cmd.exe", "/c", x, (char *) NULL); - ERROR_NO("Exec of 'cmd.exe /c %s' failed", x); + // sh not available, use exec(command) + int ret = execlp("cmd.exe", "cmd.exe", "/c", x, (char *) NULL); + ERROR_NO("Exec of 'cmd.exe /c %s' failed", x); #endif } @@ -3696,7 +3695,7 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg) char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/); ERROR("%s", x); } else if ((currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) || - (currentAction->getActionType() == CAction::E_AT_VERIFY_CMD)) { + (currentAction->getActionType() == CAction::E_AT_VERIFY_CMD)) { char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/); bool verify_result = (currentAction->getActionType() == CAction::E_AT_VERIFY_CMD);