# HG changeset patch # User Sebastien Jodogne # Date 1406108195 -7200 # Node ID 64f1842aae2e9c00248cff54dbfeb89ec86ada17 # Parent bd2cb95003da7762aebfcaf28e9e806c8289a1fd Toolbox::ExecuteSystemCommand diff -r bd2cb95003da -r 64f1842aae2e Core/Enumerations.h --- a/Core/Enumerations.h Tue Jul 22 16:49:34 2014 +0200 +++ b/Core/Enumerations.h Wed Jul 23 11:36:35 2014 +0200 @@ -57,6 +57,7 @@ ErrorCode_InexistentItem, ErrorCode_BadRequest, ErrorCode_NetworkProtocol, + ErrorCode_SystemCommand, // Specific error codes ErrorCode_UriSyntax, diff -r bd2cb95003da -r 64f1842aae2e Core/OrthancException.cpp --- a/Core/OrthancException.cpp Tue Jul 22 16:49:34 2014 +0200 +++ b/Core/OrthancException.cpp Wed Jul 23 11:36:35 2014 +0200 @@ -124,6 +124,9 @@ case ErrorCode_SharedLibrary: return "Error while using a shared library (plugin)"; + case ErrorCode_SystemCommand: + return "Error while calling a system command"; + case ErrorCode_Custom: default: return "???"; diff -r bd2cb95003da -r 64f1842aae2e Core/Toolbox.cpp --- a/Core/Toolbox.cpp Tue Jul 22 16:49:34 2014 +0200 +++ b/Core/Toolbox.cpp Wed Jul 23 11:36:35 2014 +0200 @@ -44,9 +44,14 @@ #include #include #include +#include #if defined(_WIN32) #include +#include // For "_spawnvp()" +#else +#include // For "execvp()" +#include // For "waitpid()" #endif #if defined(__APPLE__) && defined(__MACH__) @@ -951,5 +956,58 @@ } #endif + + + void Toolbox::ExecuteSystemCommand(const std::string& command, + const std::vector& arguments) + { + // Convert the arguments as a C array + std::vector args(arguments.size() + 2); + + args.front() = const_cast(command.c_str()); + + for (size_t i = 0; i < arguments.size(); i++) + { + args[i + 1] = const_cast(arguments[i].c_str()); + } + + args.back() = NULL; + + int status; + +#if defined(_WIN32) + // http://msdn.microsoft.com/en-us/library/275khfab.aspx + status = static_cast(_spawnvp(_P_OVERLAY, command.c_str(), &args[0])); + +#else + int pid = fork(); + + if (pid == -1) + { + // Error in fork() + LOG(ERROR) << "Cannot fork a child process"; + throw OrthancException(ErrorCode_SystemCommand); + } + else if (pid == 0) + { + // Execute the system command in the child process + execvp(command.c_str(), &args[0]); + + // We should never get here + _exit(1); + } + else + { + // Wait for the system command to exit + waitpid(pid, &status, 0); + } +#endif + + if (status != 0) + { + LOG(ERROR) << "System command failed with status code " << status; + throw OrthancException(ErrorCode_SystemCommand); + } + } } diff -r bd2cb95003da -r 64f1842aae2e Core/Toolbox.h --- a/Core/Toolbox.h Tue Jul 22 16:49:34 2014 +0200 +++ b/Core/Toolbox.h Wed Jul 23 11:36:35 2014 +0200 @@ -144,5 +144,8 @@ const std::string& rootElement = "root", const std::string& arrayElement = "item"); #endif + + void ExecuteSystemCommand(const std::string& command, + const std::vector& arguments); } } diff -r bd2cb95003da -r 64f1842aae2e UnitTestsSources/UnitTestsMain.cpp --- a/UnitTestsSources/UnitTestsMain.cpp Tue Jul 22 16:49:34 2014 +0200 +++ b/UnitTestsSources/UnitTestsMain.cpp Wed Jul 23 11:36:35 2014 +0200 @@ -689,7 +689,18 @@ std::cout << s; } +#endif + +#if !defined(_WIN32) +TEST(Toolbox, ExecuteSystemCommand) +{ + std::vector args(2); + args[0] = "Hello"; + args[1] = "World"; + + Toolbox::ExecuteSystemCommand("echo", args); +} #endif