]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/portability/subprocesses.cpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / subprocesses.cpp
index a8139c238468b8ff6665234fd56ce25d6eedcfeb..782b994f5647f624156d7fff8b9677981c2f53f9 100644 (file)
@@ -2,7 +2,7 @@
 \r
 //   Author:    Andy Rushton\r
 //   Copyright: (c) Southampton University 1999-2004\r
-//              (c) Andy Rushton           2004-2009\r
+//              (c) Andy Rushton           2004 onwards\r
 //   License:   BSD License, see ../docs/license.html\r
 \r
 ////////////////////////////////////////////////////////////////////////////////\r
 #include <stdlib.h>\r
 \r
 #ifdef MSWINDOWS\r
+#ifdef __BORLANDC__\r
+// missing declaration in Borland headers\r
+LPTCH WINAPI GetEnvironmentStringsA(void);\r
+#endif\r
 #else\r
+extern char** environ;\r
 #include <signal.h>\r
 #include <errno.h>\r
 #include <sys/wait.h>\r
@@ -129,7 +134,7 @@ namespace stlplus
         // set of characters requiring escapes\r
 #ifdef MSWINDOWS\r
 #else\r
-      case '\\': case '\'': case '\"': case '`': case '(': case ')': \r
+      case '\\': case '\'': case '\"': case '`': case '(': case ')':\r
       case '&': case '|': case '<': case '>': case '*': case '?': case '!':\r
         result += '\\';\r
         result += arg[i];\r
@@ -419,8 +424,6 @@ namespace stlplus
 #else\r
   // Unix utilities\r
 \r
-  extern char** environ;\r
-\r
   static unsigned envp_size(char* const* envp)\r
   {\r
     unsigned size = 0;\r
@@ -603,6 +606,20 @@ namespace stlplus
     return result;\r
   }\r
 \r
+  bool env_vector::present (const std::string& name) const\r
+  {\r
+    unsigned i = 0;\r
+    while(m_env[i])\r
+    {\r
+      std::string current_name;\r
+      std::string current_value;\r
+      envp_extract(current_name, current_value, m_env, i);\r
+      if (envp_equal(name,current_name))\r
+        return true;\r
+    }\r
+    return false;\r
+  }\r
+\r
   std::string env_vector::operator [] (const std::string& name) const\r
   {\r
     return get(name);\r
@@ -739,6 +756,11 @@ namespace stlplus
 \r
 #endif\r
 \r
+  void subprocess::set_error(int e)\r
+  {\r
+    m_err = e;\r
+  }\r
+\r
   void subprocess::add_variable(const std::string& name, const std::string& value)\r
   {\r
     m_env.add(name, value);\r
@@ -749,6 +771,11 @@ namespace stlplus
     return m_env.remove(name);\r
   }\r
 \r
+  const env_vector& subprocess::get_variables(void) const\r
+  {\r
+       return m_env;\r
+  }\r
+\r
 #ifdef MSWINDOWS\r
 \r
   bool subprocess::spawn(const std::string& path, const arg_vector& argv,\r
@@ -805,7 +832,7 @@ namespace stlplus
     if (connect_stderr) CloseHandle(parent_stderr);\r
     if (!created)\r
     {\r
-      m_err = GetLastError();\r
+      set_error(GetLastError());\r
       close_stdin();\r
       close_stdout();\r
       close_stderr();\r
@@ -833,7 +860,7 @@ namespace stlplus
       DWORD exit_status = 0;\r
       if (!GetExitCodeProcess(m_pid.hProcess, &exit_status))\r
       {\r
-        m_err = GetLastError();\r
+        set_error(GetLastError());\r
         result = false;\r
       }\r
       else if (exit_status != 0)\r
@@ -857,15 +884,18 @@ namespace stlplus
 \r
     int stdin_pipe [2] = {-1, -1};\r
     if (connect_stdin)\r
-      pipe(stdin_pipe);\r
+      if (::pipe(stdin_pipe) != 0)\r
+        set_error(errno);\r
 \r
     int stdout_pipe [2] = {-1, -1};\r
     if (connect_stdout)\r
-      pipe(stdout_pipe);\r
+      if (::pipe(stdout_pipe) != 0)\r
+        set_error(errno);\r
 \r
     int stderr_pipe [2] = {-1, -1};\r
     if (connect_stderr)\r
-      pipe(stderr_pipe);\r
+      if (::pipe(stderr_pipe) != 0)\r
+        set_error(errno);\r
 \r
     // now create the subprocess\r
     // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec\r
@@ -873,7 +903,7 @@ namespace stlplus
     switch(m_pid)\r
     {\r
     case -1:   // failed to fork\r
-      m_err = errno;\r
+      set_error(errno);\r
       if (connect_stdin)\r
       {\r
         ::close(stdin_pipe[0]);\r
@@ -898,17 +928,17 @@ namespace stlplus
       if (connect_stdin)\r
       {\r
         ::close(stdin_pipe[1]);\r
-        dup2(stdin_pipe[0],STDIN_FILENO);\r
+        ::dup2(stdin_pipe[0],STDIN_FILENO);\r
       }\r
       if (connect_stdout)\r
       {\r
         ::close(stdout_pipe[0]);\r
-        dup2(stdout_pipe[1],STDOUT_FILENO);\r
+        ::dup2(stdout_pipe[1],STDOUT_FILENO);\r
       }\r
       if (connect_stderr)\r
       {\r
         ::close(stderr_pipe[0]);\r
-        dup2(stderr_pipe[1],STDERR_FILENO);\r
+        ::dup2(stderr_pipe[1],STDERR_FILENO);\r
       }\r
       execve(path.c_str(), argv.argv(), m_env.envp());\r
       // will only ever get here if the exec() failed completely - *must* now exit the child process\r
@@ -999,7 +1029,7 @@ namespace stlplus
     close_stderr();\r
     if (!TerminateJobObject(m_job, (UINT)-1))\r
     {\r
-      m_err = GetLastError();\r
+      set_error(GetLastError());\r
       return false;\r
     }\r
     return true;\r
@@ -1015,7 +1045,7 @@ namespace stlplus
     close_stderr();\r
     if (::kill(m_pid, SIGINT) == -1)\r
     {\r
-      m_err = errno;\r
+      set_error(errno);\r
       return false;\r
     }\r
     return true;\r
@@ -1032,7 +1062,7 @@ namespace stlplus
     DWORD bytes = 0;\r
     if (!WriteFile(m_child_in, buffer.c_str(), (DWORD)buffer.size(), &bytes, 0))\r
     {\r
-      m_err = GetLastError();\r
+      set_error(GetLastError());\r
       close_stdin();\r
       return -1;\r
     }\r
@@ -1051,7 +1081,7 @@ namespace stlplus
     int bytes = write(m_child_in, buffer.c_str(), buffer.size());\r
     if (bytes == -1)\r
     {\r
-      m_err = errno;\r
+      set_error(errno);\r
       close_stdin();\r
       return -1;\r
     }\r
@@ -1074,7 +1104,7 @@ namespace stlplus
     if (!ReadFile(m_child_out, tmp, buffer_size, &bytes, 0))\r
     {\r
       if (GetLastError() != ERROR_BROKEN_PIPE)\r
-        m_err = GetLastError();\r
+        set_error(GetLastError());\r
       close_stdout();\r
       delete[] tmp;\r
       return -1;\r
@@ -1101,7 +1131,7 @@ namespace stlplus
     int bytes = read(m_child_out, tmp, buffer_size);\r
     if (bytes == -1)\r
     {\r
-      m_err = errno;\r
+      set_error(errno);\r
       close_stdout();\r
       delete[] tmp;\r
       return -1;\r
@@ -1131,7 +1161,7 @@ namespace stlplus
     if (!ReadFile(m_child_err, tmp, buffer_size, &bytes, 0))\r
     {\r
       if (GetLastError() != ERROR_BROKEN_PIPE)\r
-        m_err = GetLastError();\r
+        set_error(GetLastError());\r
       close_stderr();\r
       delete[] tmp;\r
       return -1;\r
@@ -1158,7 +1188,7 @@ namespace stlplus
     int bytes = read(m_child_err, tmp, buffer_size);\r
     if (bytes == -1)\r
     {\r
-      m_err = errno;\r
+      set_error(errno);\r
       close_stderr();\r
       delete[] tmp;\r
       return -1;\r
@@ -1263,7 +1293,7 @@ namespace stlplus
 \r
   std::string subprocess::error_text(void) const\r
   {\r
-    if (m_err == 0) return std::string();\r
+    if (!error()) return std::string();\r
     char* message;\r
     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,\r
                   0,\r
@@ -1285,7 +1315,7 @@ namespace stlplus
 \r
   std::string subprocess::error_text(void) const\r
   {\r
-    if (m_err == 0) return std::string();\r
+    if (!error()) return std::string();\r
     char* text = strerror(m_err);\r
     if (text) return std::string(text);\r
     return "error number " + dformat("%d",m_err);\r
@@ -1332,6 +1362,7 @@ namespace stlplus
     std::vector<std::string> result;\r
     // convert the raw text into a vector of strings, each corresponding to a line\r
     // in the process, strip out platform-specific line-endings\r
+    result.push_back(std::string());\r
     for (unsigned i = 0; i < m_text.size(); i++)\r
     {\r
       // handle any kind of line-ending - Dos, Unix or MacOS\r
@@ -1462,6 +1493,11 @@ namespace stlplus
     return m_env.remove(name);\r
   }\r
 \r
+  const env_vector& async_subprocess::get_variables(void) const\r
+  {\r
+       return m_env;\r
+  }\r
+\r
 #ifdef MSWINDOWS\r
 \r
   bool async_subprocess::spawn(const std::string& path, const arg_vector& argv,\r
@@ -1543,15 +1579,18 @@ namespace stlplus
 \r
     int stdin_pipe [2] = {-1, -1};\r
     if (connect_stdin)\r
-      pipe(stdin_pipe);\r
+      if (::pipe(stdin_pipe) != 0)\r
+        set_error(errno);\r
 \r
     int stdout_pipe [2] = {-1, -1};\r
     if (connect_stdout)\r
-      pipe(stdout_pipe);\r
+      if (::pipe(stdout_pipe) != 0)\r
+        set_error(errno);\r
 \r
     int stderr_pipe [2] = {-1, -1};\r
     if (connect_stderr)\r
-      pipe(stderr_pipe);\r
+      if (::pipe(stderr_pipe) != 0)\r
+        set_error(errno);\r
 \r
     // now create the subprocess\r
     // In Unix, this is done by forking (creating two copies of the parent), then overwriting the child copy using exec\r
@@ -1584,22 +1623,22 @@ namespace stlplus
       if (connect_stdin)\r
       {\r
         ::close(stdin_pipe[1]);\r
-        dup2(stdin_pipe[0],STDIN_FILENO);\r
+        ::dup2(stdin_pipe[0],STDIN_FILENO);\r
       }\r
       if (connect_stdout)\r
       {\r
         ::close(stdout_pipe[0]);\r
-        dup2(stdout_pipe[1],STDOUT_FILENO);\r
+        ::dup2(stdout_pipe[1],STDOUT_FILENO);\r
       }\r
       if (connect_stderr)\r
       {\r
         ::close(stderr_pipe[0]);\r
-        dup2(stderr_pipe[1],STDERR_FILENO);\r
+        ::dup2(stderr_pipe[1],STDERR_FILENO);\r
       }\r
-      execve(path.c_str(), argv.argv(), m_env.envp());\r
+      ::execve(path.c_str(), argv.argv(), m_env.envp());\r
       // will only ever get here if the exec() failed completely - *must* now exit the child process\r
       // by using errno, the parent has some chance of diagnosing the cause of the problem\r
-      exit(errno);\r
+      ::exit(errno);\r
     }\r
     break;\r
     default:  // in parent\r
@@ -2037,7 +2076,7 @@ namespace stlplus
 \r
   std::string async_subprocess::error_text(void) const\r
   {\r
-    if (m_err == 0) return std::string();\r
+    if (!error()) return std::string();\r
     char* message;\r
     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,\r
                   0,\r
@@ -2059,7 +2098,7 @@ namespace stlplus
 \r
   std::string async_subprocess::error_text(void) const\r
   {\r
-    if (m_err == 0) return std::string();\r
+    if (!error()) return std::string();\r
     char* text = strerror(m_err);\r
     if (text) return std::string(text);\r
     return "error number " + dformat("%d",m_err);\r
This page took 0.031702 seconds and 4 git commands to generate.