diff --git a/src/os/portable/os-impl-no-shell.c b/src/os/portable/os-impl-no-shell.c new file mode 100644 index 000000000..e5add69b9 --- /dev/null +++ b/src/os/portable/os-impl-no-shell.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Glenn + * Research Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +#include "osapi.h" + +/** + * \file os-impl-no-shell.c + * + * Purpose: No shell implementation, returns OS_ERR_NOT_IMPLEMENTED for calls + */ + +/*---------------------------------------------------------------- + * + * Function: OS_ShellOutputToFile_Impl + * + * Purpose: Implemented per internal OSAL API + * See description in os-impl.h for argument/return detail + * + *-----------------------------------------------------------------*/ +int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char* Cmd) +{ + return OS_ERR_NOT_IMPLEMENTED; +} diff --git a/src/os/posix/CMakeLists.txt b/src/os/posix/CMakeLists.txt index b628aefe0..67b1d1320 100644 --- a/src/os/posix/CMakeLists.txt +++ b/src/os/posix/CMakeLists.txt @@ -15,5 +15,5 @@ add_library(osal_posix_impl OBJECT osnetwork.c osselect.c ostimer.c + ../portable/os-impl-no-shell.c ) - diff --git a/src/os/posix/osfileapi.c b/src/os/posix/osfileapi.c index 140a705a4..193672e10 100644 --- a/src/os/posix/osfileapi.c +++ b/src/os/posix/osfileapi.c @@ -26,9 +26,6 @@ #include #include #include -#include -#include - /**************************************************************************************** GLOBALS @@ -137,68 +134,3 @@ int32 OS_Posix_DirAPI_Impl_Init(void) memset(OS_impl_dir_table, 0, sizeof(OS_impl_dir_table)); return OS_SUCCESS; } /* end OS_Posix_DirAPI_Impl_Init */ - - - - -/*---------------------------------------------------------------- - * - * Function: OS_ShellOutputToFile_Impl - * - * Purpose: Implemented per internal OSAL API - * See prototype in os-impl.h for argument/return detail - * - *-----------------------------------------------------------------*/ -int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char* Cmd) -{ - pid_t cpid; - uint32 local_id; - int wstat; - const char *shell = getenv("SHELL"); - - if (shell == NULL) - { - shell = "/bin/sh"; - } - - cpid = fork(); - if (cpid < 0) - { - OS_DEBUG("%s(): Error during fork(): %s\n", __func__, strerror(errno)); - return OS_ERROR; - } - - if (cpid == 0) - { - /* child process */ - dup2(OS_impl_filehandle_table[file_id].fd, STDOUT_FILENO); - dup2(OS_impl_filehandle_table[file_id].fd, STDERR_FILENO); - - /* close all _other_ filehandles */ - for (local_id = 0; local_id < OS_MAX_NUM_OPEN_FILES; ++local_id) - { - if (OS_global_stream_table[local_id].active_id != 0) - { - close(OS_impl_filehandle_table[local_id].fd); - } - } - - execl(shell, "sh", "-c", Cmd, NULL); /* does not return if successful */ - exit(EXIT_FAILURE); - } - - if (waitpid(cpid, &wstat, 0) != cpid) - { - OS_DEBUG("%s(): Error during waitpid(): %s\n", __func__, strerror(errno)); - return OS_ERROR; - } - - if (!WIFEXITED(wstat) || WEXITSTATUS(wstat) != 0) - { - OS_DEBUG("%s(): Error from child process: %d\n", __func__, wstat); - return OS_ERROR; - } - - return OS_SUCCESS; -} /* end OS_ShellOutputToFile_Impl */ - diff --git a/src/os/posix/osshell.c b/src/os/posix/osshell.c new file mode 100644 index 000000000..22bf035aa --- /dev/null +++ b/src/os/posix/osshell.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Glenn + * Research Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/** + * \file osshell.c + * + * Purpose: Implements shell-related calls that can be optionally built + * for distributions that choose to support them. Alternatively + * build the portable no-shell implementation to exclude this + * functionality. + */ + +/**************************************************************************************** + INCLUDE FILES + ***************************************************************************************/ + +#include "os-posix.h" + +#include +#include + +/**************************************************************************************** + IMPLEMENTATION-SPECIFIC ROUTINES + These are specific to this particular operating system + ****************************************************************************************/ + +/*---------------------------------------------------------------- + * + * Function: OS_ShellOutputToFile_Impl + * + * Purpose: Implemented per internal OSAL API + * See prototype in os-impl.h for argument/return detail + * + *-----------------------------------------------------------------*/ +int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char* Cmd) +{ + pid_t cpid; + uint32 local_id; + int wstat; + const char *shell = getenv("SHELL"); + + if (shell == NULL) + { + shell = "/bin/sh"; + } + + cpid = fork(); + if (cpid < 0) + { + OS_DEBUG("%s(): Error during fork(): %s\n", __func__, strerror(errno)); + return OS_ERROR; + } + + if (cpid == 0) + { + /* child process */ + dup2(OS_impl_filehandle_table[file_id].fd, STDOUT_FILENO); + dup2(OS_impl_filehandle_table[file_id].fd, STDERR_FILENO); + + /* close all _other_ filehandles */ + for (local_id = 0; local_id < OS_MAX_NUM_OPEN_FILES; ++local_id) + { + if (OS_global_stream_table[local_id].active_id != 0) + { + close(OS_impl_filehandle_table[local_id].fd); + } + } + + execl(shell, "sh", "-c", Cmd, NULL); /* does not return if successful */ + exit(EXIT_FAILURE); + } + + if (waitpid(cpid, &wstat, 0) != cpid) + { + OS_DEBUG("%s(): Error during waitpid(): %s\n", __func__, strerror(errno)); + return OS_ERROR; + } + + if (!WIFEXITED(wstat) || WEXITSTATUS(wstat) != 0) + { + OS_DEBUG("%s(): Error from child process: %d\n", __func__, wstat); + return OS_ERROR; + } + + return OS_SUCCESS; +} /* end OS_ShellOutputToFile_Impl */ + diff --git a/src/os/rtems/CMakeLists.txt b/src/os/rtems/CMakeLists.txt index 32ef42a9c..c8bbc655f 100644 --- a/src/os/rtems/CMakeLists.txt +++ b/src/os/rtems/CMakeLists.txt @@ -14,4 +14,5 @@ add_library(osal_rtems_impl OBJECT osnetwork.c osselect.c ostimer.c + ../portable/os-impl-no-shell.c ) diff --git a/src/os/rtems/osfileapi.c b/src/os/rtems/osfileapi.c index f7733a31e..d7a49a9a3 100644 --- a/src/os/rtems/osfileapi.c +++ b/src/os/rtems/osfileapi.c @@ -137,47 +137,3 @@ int32 OS_Rtems_DirAPI_Impl_Init(void) /* FIXME - need to do something better here */ - - -/*---------------------------------------------------------------- - * - * Function: OS_ShellOutputToFile_Impl - * - * Purpose: Implemented per internal OSAL API - * See prototype in os-impl.h for argument/return detail - * - *-----------------------------------------------------------------*/ -int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char *Cmd) -{ - /* - ** this is a #define to avoid a 'variable length array' warning - ** 15 is for the size of the redirection string that is added - ** to the command - */ - char LocalCmd [OS_MAX_CMD_LEN + OS_REDIRECTSTRSIZE]; - int32 Result; - - strncpy(LocalCmd,Cmd,OS_MAX_CMD_LEN +OS_REDIRECTSTRSIZE); - - /* Make sure that we are able to access this file */ - fchmod(OS_impl_filehandle_table[file_id].fd, 0666); - - /* - ** add in the extra chars necessary to perform the redirection - ** 1 for stdout and 2 for stderr. they are redirected to the - ** file descriptor passed in - */ - snprintf(LocalCmd, sizeof(LocalCmd), "%s 1>&%d 2>&%d", - Cmd, - OS_impl_filehandle_table[file_id].fd, - OS_impl_filehandle_table[file_id].fd); - - Result = system(LocalCmd); - - if (Result != 0) - { - return OS_FS_ERROR; - } - return OS_SUCCESS; -} /* end OS_ShellOutputToFile_Impl */ - diff --git a/src/os/rtems/osshell.c b/src/os/rtems/osshell.c new file mode 100644 index 000000000..9303fe871 --- /dev/null +++ b/src/os/rtems/osshell.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Glenn + * Research Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/** + * \file osshell.c + * + * Purpose: Implements shell-related calls that can be optionally built + * for distributions that choose to support them. Alternatively + * build the portable no-shell implementation to exclude this + * functionality. + */ + +/**************************************************************************************** + INCLUDE FILES + ***************************************************************************************/ + +#include "os-rtems.h" + +#include +#include + +/**************************************************************************************** + IMPLEMENTATION-SPECIFIC ROUTINES + These are specific to this particular operating system + ****************************************************************************************/ + +/*---------------------------------------------------------------- + * + * Function: OS_ShellOutputToFile_Impl + * + * Purpose: Implemented per internal OSAL API + * See prototype in os-impl.h for argument/return detail + * + *-----------------------------------------------------------------*/ +int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char* Cmd) +{ + /* + ** this is a #define to avoid a 'variable length array' warning + ** 15 is for the size of the redirection string that is added + ** to the command + */ + char LocalCmd [OS_MAX_CMD_LEN + OS_REDIRECTSTRSIZE]; + int32 Result; + + strncpy(LocalCmd,Cmd,OS_MAX_CMD_LEN +OS_REDIRECTSTRSIZE); + + /* Make sure that we are able to access this file */ + fchmod(OS_impl_filehandle_table[file_id].fd, 0666); + + /* + ** add in the extra chars necessary to perform the redirection + ** 1 for stdout and 2 for stderr. they are redirected to the + ** file descriptor passed in + */ + snprintf(LocalCmd, sizeof(LocalCmd), "%s 1>&%d 2>&%d", + Cmd, + OS_impl_filehandle_table[file_id].fd, + OS_impl_filehandle_table[file_id].fd); + + Result = system(LocalCmd); + + if (Result != 0) + { + return OS_FS_ERROR; + } + return OS_SUCCESS; +} /* end OS_ShellOutputToFile_Impl */ + diff --git a/src/os/vxworks/CMakeLists.txt b/src/os/vxworks/CMakeLists.txt index 578be6c60..f3c07036e 100644 --- a/src/os/vxworks/CMakeLists.txt +++ b/src/os/vxworks/CMakeLists.txt @@ -14,4 +14,5 @@ add_library(osal_vxworks_impl OBJECT osnetwork.c osselect.c ostimer.c -) \ No newline at end of file + ../portable/os-impl-no-shell.c +) diff --git a/src/os/vxworks/osfileapi.c b/src/os/vxworks/osfileapi.c index 09b1b291a..afe881894 100644 --- a/src/os/vxworks/osfileapi.c +++ b/src/os/vxworks/osfileapi.c @@ -25,13 +25,9 @@ #include #include #include -#include #include #include -#include #include -#include -#include /* * Leverage the POSIX-style File I/O as this will also work on vxWorks. @@ -219,18 +215,6 @@ int32 OS_DirRemove_Impl(const char *local_path) } /* end OS_DirRemove_Impl */ -/**************************************************************************************** - DEFINES -****************************************************************************************/ - -#define OS_REDIRECTSTRSIZE 15 -#define OS_SHELL_TMP_FILE_EXT ".out" -#define OS_SHELL_TMP_FILE_EXT_LEN 4 -#define OS_SHELL_CMD_TASK_STACK_SIZE 16384 -#define OS_SHELL_CMD_TASK_PRIORITY 250 - - - /*---------------------------------------------------------------- * * Function: OS_VxWorks_StreamAPI_Impl_Init @@ -268,61 +252,3 @@ int32 OS_VxWorks_DirAPI_Impl_Init(void) return OS_SUCCESS; } /* end OS_VxWorks_DirAPI_Impl_Init */ - - -/*---------------------------------------------------------------- - * - * Function: OS_ShellOutputToFile_Impl - * - * Purpose: Implemented per internal OSAL API - * See prototype in os-impl.h for argument/return detail - * - *-----------------------------------------------------------------*/ -int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char *Cmd) -{ - int32 ReturnCode = OS_FS_ERROR; - int32 Result = ERROR; - int32 fdCmd; - uint32 cmdidx; - char * shellName; - - /* Create a file to write the command to (or write over the old one) */ - fdCmd = OS_creat(OS_SHELL_CMD_INPUT_FILE_NAME,OS_READ_WRITE); - - if (fdCmd < OS_FS_SUCCESS) - { - return OS_FS_ERROR; - } - - if (OS_ConvertToArrayIndex(fdCmd, &cmdidx) == OS_SUCCESS) - { - /* copy the command to the file, and then seek back to the beginning of the file */ - OS_write(fdCmd, Cmd, strlen(Cmd)); - OS_lseek(fdCmd,0,OS_SEEK_SET); - - /* Create a shell task the will run the command in the file, push output to OS_fd */ - Result = shellGenericInit("INTERPRETER=Cmd", 0, NULL, &shellName, false, false, - OS_impl_filehandle_table[cmdidx].fd, - OS_impl_filehandle_table[file_id].fd, - OS_impl_filehandle_table[file_id].fd); - } - - if (Result == OK) - { - /* Wait for the command to terminate */ - do - { - taskDelay(sysClkRateGet()); - } - while (taskNameToId(shellName) != ((TASK_ID)ERROR)); - - ReturnCode = OS_SUCCESS; - } - - /* Close the file descriptor */ - OS_close(fdCmd); - - return ReturnCode; - -} /* end OS_ShellOutputToFile_Impl */ - diff --git a/src/os/vxworks/osshell.c b/src/os/vxworks/osshell.c new file mode 100644 index 000000000..ec3ecd83a --- /dev/null +++ b/src/os/vxworks/osshell.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Glenn + * Research Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/** + * \file osshell.c + * + * Purpose: Implements shell-related calls that can be optionally built + * for distributions that choose to support them. Alternatively + * build the portable no-shell implementation to exclude this + * functionality. + */ + +/**************************************************************************************** + INCLUDE FILES + ***************************************************************************************/ + +#include "os-vxworks.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************************** + IMPLEMENTATION-SPECIFIC ROUTINES + These are specific to this particular operating system + ****************************************************************************************/ + +/*---------------------------------------------------------------- + * + * Function: OS_ShellOutputToFile_Impl + * + * Purpose: Implemented per internal OSAL API + * See prototype in os-impl.h for argument/return detail + * + *-----------------------------------------------------------------*/ +int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char *Cmd) +{ + int32 ReturnCode = OS_FS_ERROR; + int32 Result = ERROR; + int32 fdCmd; + uint32 cmdidx; + char * shellName; + + /* Create a file to write the command to (or write over the old one) */ + fdCmd = OS_creat(OS_SHELL_CMD_INPUT_FILE_NAME,OS_READ_WRITE); + + if (fdCmd < OS_FS_SUCCESS) + { + return OS_FS_ERROR; + } + + if (OS_ConvertToArrayIndex(fdCmd, &cmdidx) == OS_SUCCESS) + { + /* copy the command to the file, and then seek back to the beginning of the file */ + OS_write(fdCmd, Cmd, strlen(Cmd)); + OS_lseek(fdCmd,0,OS_SEEK_SET); + + /* Create a shell task the will run the command in the file, push output to OS_fd */ + Result = shellGenericInit("INTERPRETER=Cmd", 0, NULL, &shellName, false, false, + OS_impl_filehandle_table[cmdidx].fd, + OS_impl_filehandle_table[file_id].fd, + OS_impl_filehandle_table[file_id].fd); + } + + if (Result == OK) + { + /* Wait for the command to terminate */ + do + { + taskDelay(sysClkRateGet()); + } + while (taskNameToId(shellName) != ((TASK_ID)ERROR)); + + ReturnCode = OS_SUCCESS; + } + + /* Close the file descriptor */ + OS_close(fdCmd); + + return ReturnCode; + +} /* end OS_ShellOutputToFile_Impl */ diff --git a/src/unit-test-coverage/vxworks/CMakeLists.txt b/src/unit-test-coverage/vxworks/CMakeLists.txt index 7a1041de5..b43f34862 100644 --- a/src/unit-test-coverage/vxworks/CMakeLists.txt +++ b/src/unit-test-coverage/vxworks/CMakeLists.txt @@ -1,6 +1,6 @@ # CMake snippet for building the shared OSAL layer coverage tests -set(MODULE_LIST osapi osfileapi osfilesys osloader osnetwork osselect ostimer posixio posixfile posixgettime printf) +set(MODULE_LIST osapi osfileapi osfilesys osloader osnetwork osselect osshell ostimer posixio posixfile posixgettime printf) # This unit test is allowed to directly include any internal file in # the respective set under test. diff --git a/src/unit-test-coverage/vxworks/modules/src/ut-osshell.c b/src/unit-test-coverage/vxworks/modules/src/ut-osshell.c new file mode 100644 index 000000000..10169877c --- /dev/null +++ b/src/unit-test-coverage/vxworks/modules/src/ut-osshell.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/* pull in the OSAL configuration */ +#include "osconfig.h" +#include "ut-osfileapi.h" + +/* + * Now include all extra logic required to stub-out subsequent calls to + * library functions and replace with our own + */ +#include "osshell.c" + +OS_VxWorks_filehandle_entry_t OS_impl_filehandle_table[OS_MAX_NUM_OPEN_FILES]; diff --git a/src/unit-test-coverage/vxworks/src/coveragetest-osfileapi.c b/src/unit-test-coverage/vxworks/src/coveragetest-osfileapi.c index b7deec7b8..7f4016e8a 100644 --- a/src/unit-test-coverage/vxworks/src/coveragetest-osfileapi.c +++ b/src/unit-test-coverage/vxworks/src/coveragetest-osfileapi.c @@ -25,8 +25,6 @@ #include "os-vxworks-coveragetest.h" #include -#include -#include #include #include #include @@ -120,34 +118,6 @@ void Test_OS_DirRemove_Impl(void) OSAPI_TEST_FUNCTION_RC(OS_DirRemove_Impl("dir"), OS_ERROR); } -void Test_OS_ShellOutputToFile_Impl(void) -{ - /* - * Test Case For: - * int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char *Cmd) - */ - int32 expected = OS_SUCCESS; - int32 actual; - - /* - * The ShellOutputToFile will loop until the - * taskNameToId() function returns ERROR, so this - * must be set to avoid getting into an endless loop. - */ - UT_SetDeferredRetcode(UT_KEY(OCS_taskNameToId), 2, -1); - - actual = OS_ShellOutputToFile_Impl(0, "TestCmd"); - - UtAssert_True(actual == expected, "OS_ShellOutputToFile_Impl() (%ld) == OS_SUCCESS", (long)actual); - UtAssert_True(UT_GetStubCount(UT_KEY(OCS_shellGenericInit)) == 1, "shellGenericInit() called"); - - /* failure to open the output file */ - UT_SetForceFail(UT_KEY(OS_creat), OS_ERROR); - expected = OS_ERROR; - actual = OS_ShellOutputToFile_Impl(0, "TestCmd"); - UtAssert_True(actual == expected, "OS_ShellOutputToFile_Impl() (%ld) == OS_ERROR", (long)actual); -} - /* ------------------- End of test cases --------------------------------------*/ @@ -187,7 +157,6 @@ void UtTest_Setup(void) ADD_TEST(OS_DirRead_Impl); ADD_TEST(OS_DirRewind_Impl); ADD_TEST(OS_DirRemove_Impl); - ADD_TEST(OS_ShellOutputToFile_Impl); } diff --git a/src/unit-test-coverage/vxworks/src/coveragetest-osshell.c b/src/unit-test-coverage/vxworks/src/coveragetest-osshell.c new file mode 100644 index 000000000..accea5dc8 --- /dev/null +++ b/src/unit-test-coverage/vxworks/src/coveragetest-osshell.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/* + * Filename: osapi_testcase_common.c + * + * Purpose: This file contains unit test cases for items in the "osfileapi-common" file + * + * Notes: + * + */ + + +/* + * Includes + */ + +#include "os-vxworks-coveragetest.h" + +#include +#include +#include +#include +#include +#include + +#include "ut-osfileapi.h" + +void Test_OS_ShellOutputToFile_Impl(void) +{ + /* + * Test Case For: + * int32 OS_ShellOutputToFile_Impl(uint32 file_id, const char *Cmd) + */ + int32 expected = OS_SUCCESS; + int32 actual; + + /* + * The ShellOutputToFile will loop until the + * taskNameToId() function returns ERROR, so this + * must be set to avoid getting into an endless loop. + */ + UT_SetDeferredRetcode(UT_KEY(OCS_taskNameToId), 2, -1); + + actual = OS_ShellOutputToFile_Impl(0, "TestCmd"); + + UtAssert_True(actual == expected, "OS_ShellOutputToFile_Impl() (%ld) == OS_SUCCESS", (long)actual); + UtAssert_True(UT_GetStubCount(UT_KEY(OCS_shellGenericInit)) == 1, "shellGenericInit() called"); + + /* failure to open the output file */ + UT_SetForceFail(UT_KEY(OS_creat), OS_ERROR); + expected = OS_ERROR; + actual = OS_ShellOutputToFile_Impl(0, "TestCmd"); + UtAssert_True(actual == expected, "OS_ShellOutputToFile_Impl() (%ld) == OS_ERROR", (long)actual); +} + + +/* ------------------- End of test cases --------------------------------------*/ + +/* Osapi_Task_Setup + * + * Purpose: + * Called by the unit test tool to set up the app prior to each test + */ +void Osapi_Task_Setup(void) +{ + UT_ResetState(0); +} + +/* + * Osapi_TearDown + * + * Purpose: + * Called by the unit test tool to tear down the app after each test + */ +void Osapi_TearDown(void) +{ + +} + +/* UtTest_Setup + * + * Purpose: + * Registers the test cases to execute with the unit test tool + */ +void UtTest_Setup(void) +{ + ADD_TEST(OS_ShellOutputToFile_Impl); +} + +