changeset 1050:64f1842aae2e

Toolbox::ExecuteSystemCommand
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 23 Jul 2014 11:36:35 +0200
parents bd2cb95003da
children 92f4bf2c5d73
files Core/Enumerations.h Core/OrthancException.cpp Core/Toolbox.cpp Core/Toolbox.h UnitTestsSources/UnitTestsMain.cpp
diffstat 5 files changed, 76 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- 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 "???";
--- 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 <algorithm>
 #include <ctype.h>
 #include <boost/regex.hpp> 
+#include <glog/logging.h>
 
 #if defined(_WIN32)
 #include <windows.h>
+#include <process.h>   // For "_spawnvp()"
+#else
+#include <unistd.h>    // For "execvp()"
+#include <sys/wait.h>  // For "waitpid()"
 #endif
 
 #if defined(__APPLE__) && defined(__MACH__)
@@ -951,5 +956,58 @@
   }
 
 #endif
+
+
+  void Toolbox::ExecuteSystemCommand(const std::string& command,
+                                     const std::vector<std::string>& arguments)
+  {
+    // Convert the arguments as a C array
+    std::vector<char*>  args(arguments.size() + 2);
+
+    args.front() = const_cast<char*>(command.c_str());
+
+    for (size_t i = 0; i < arguments.size(); i++)
+    {
+      args[i + 1] = const_cast<char*>(arguments[i].c_str());
+    }
+
+    args.back() = NULL;
+
+    int status;
+
+#if defined(_WIN32)
+    // http://msdn.microsoft.com/en-us/library/275khfab.aspx
+    status = static_cast<int>(_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);
+    }
+  }
 }
 
--- 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<std::string>& arguments);
   }
 }
--- 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<std::string> args(2);
+  args[0] = "Hello";
+  args[1] = "World";
+
+  Toolbox::ExecuteSystemCommand("echo", args);
+}
 #endif