diff liboctave/oct-syscalls.cc @ 6321:363a2f8c9e97

[project @ 2007-02-16 20:26:23 by dbateman]
author dbateman
date Fri, 16 Feb 2007 20:27:46 +0000
parents 8d285942fc3c
children 7e958a1532c6
line wrap: on
line diff
--- a/liboctave/oct-syscalls.cc
+++ b/liboctave/oct-syscalls.cc
@@ -47,6 +47,7 @@
 #include <signal.h>
 
 #include "lo-utils.h"
+#include "lo-sysdep.h"
 #include "oct-syscalls.h"
 #include "str-vec.h"
 
@@ -356,6 +357,100 @@
   return status;
 }
 
+pid_t
+octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
+    bool sync_mode, int *fildes)
+{
+  std::string msg;
+  bool interactive = false;
+  return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
+}
+
+pid_t
+octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
+    bool sync_mode, int *fildes, std::string& msg)
+{
+  bool interactive = false;
+  return popen2 (cmd, args, sync_mode, fildes, msg, interactive);
+}
+
+pid_t
+octave_syscalls::popen2 (const std::string& cmd, const string_vector& args,
+    bool sync_mode, int *fildes, std::string& msg, bool &interactive)
+{
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+  return ::octave_popen2 (cmd, args, sync_mode, fildes, msg);
+#else
+  pid_t pid;
+  int child_stdin[2], child_stdout[2];
+
+  if (pipe (child_stdin, msg) == 0)
+    {
+      if (pipe (child_stdout, msg) == 0)
+        {
+          pid = fork (msg);
+          if (pid < 0)
+            msg = "popen2: process creation failed -- " + msg;
+          else if (pid == 0)
+            {
+	      std::string child_msg;
+
+	      interactive = false;
+
+              // Child process
+              ::close (child_stdin[1]);
+              ::close (child_stdout[0]);
+
+              if (dup2 (child_stdin[0], STDIN_FILENO) >= 0)
+                {
+                  ::close (child_stdin[0]);
+                  if (dup2 (child_stdout[1], STDOUT_FILENO) >= 0)
+                    {
+                      ::close (child_stdout[1]);
+                      if (execvp (cmd, args, child_msg) < 0)
+                        child_msg = "popen2 (child): unable to start process -- " + child_msg;
+                    }
+                  else
+                    child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
+                }
+              else
+                child_msg = "popen2 (child): file handle duplication failed -- " + child_msg;
+	      
+	      (*current_liboctave_error_handler)(child_msg.c_str());
+	      
+	      exit(0);
+            }
+          else
+            {
+              // Parent process
+              ::close (child_stdin[0]);
+              ::close (child_stdout[1]);
+#if defined (F_SETFL) && defined (O_NONBLOCK)
+              if (! sync_mode && fcntl (child_stdout[0], F_SETFL, O_NONBLOCK, msg) < 0)
+                msg = "popen2: error setting file mode -- " + msg;
+              else
+#endif
+                {
+                  fildes[0] = child_stdin [1];
+                  fildes[1] = child_stdout [0];
+                  return pid;
+                }
+            }
+          ::close (child_stdout[0]);
+          ::close (child_stdout[1]);
+        }
+      else
+        msg = "popen2: pipe creation failed -- " + msg;
+      ::close (child_stdin[0]);
+      ::close (child_stdin[1]);
+    }
+  else
+    msg = "popen2: pipe creation failed -- " + msg;
+
+  return -1;
+#endif
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***