summaryrefslogtreecommitdiff
path: root/ace/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/Process.cpp')
-rw-r--r--ace/Process.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/ace/Process.cpp b/ace/Process.cpp
new file mode 100644
index 00000000000..c2aa3ba9a84
--- /dev/null
+++ b/ace/Process.cpp
@@ -0,0 +1,197 @@
+#define ACE_BUILD_DLL
+// $Id$
+
+#include "ace/Process.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Process.i"
+#endif /* __ACE_INLINE__ */
+
+int
+ACE_Process::wait (void)
+{
+#if defined (ACE_WIN32)
+ return ::WaitForSingleObject (process_info_.hProcess, INFINITE);
+#else /* ACE_WIN32 */
+ return ACE_OS::waitpid (this->child_id_, 0, 0);
+#endif /* ACE_WIN32 */
+}
+
+ACE_Process::ACE_Process (void)
+#if defined (ACE_WIN32)
+ : set_handles_called_ (0)
+#else /* ACE_WIN32 */
+ : stdin_ (ACE_INVALID_HANDLE),
+ stdout_ (ACE_INVALID_HANDLE),
+ stderr_ (ACE_INVALID_HANDLE)
+#endif /* ACE_WIN32 */
+{
+#if defined (ACE_WIN32)
+ ACE_OS::memset ((void *) &startup_info_, 0, sizeof startup_info_);
+ ACE_OS::memset ((void *) &process_info_, 0, sizeof process_info_);
+ startup_info_.cb = sizeof startup_info_;
+#endif /* ACE_WIN32 */
+}
+
+ACE_Process::~ACE_Process (void)
+{
+#if defined (ACE_WIN32)
+ // Just in case start wasn't called.
+ if (set_handles_called_)
+ {
+ ::CloseHandle (startup_info_.hStdInput);
+ ::CloseHandle (startup_info_.hStdOutput);
+ ::CloseHandle (startup_info_.hStdOutput);
+ set_handles_called_ = 0;
+ }
+
+ // Free resources allocated in kernel.
+ ACE_OS::close (process_info_.hThread);
+ ACE_OS::close (process_info_.hProcess);
+
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_Process::set_handles (ACE_HANDLE std_in,
+ ACE_HANDLE std_out,
+ ACE_HANDLE std_err)
+{
+#if defined (ACE_WIN32)
+ set_handles_called_ = 1;
+
+ // Tell the new process to use our std handles.
+ startup_info_.dwFlags = STARTF_USESTDHANDLES;
+
+ if (std_in == ACE_INVALID_HANDLE)
+ std_in = ACE_STDIN;
+ if (std_out == ACE_INVALID_HANDLE)
+ std_out = ACE_STDOUT;
+ if (std_err == ACE_INVALID_HANDLE)
+ std_err = ACE_STDERR;
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_in,
+ ::GetCurrentProcess(),
+ &startup_info_.hStdInput,
+ NULL,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_out,
+ ::GetCurrentProcess(),
+ &startup_info_.hStdOutput,
+ NULL,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_err,
+ ::GetCurrentProcess(),
+ &startup_info_.hStdError,
+ NULL,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ return -1;
+#else /* ACE_WIN32 */
+ stdin_ = std_in;
+ stdout_ = std_out;
+ stderr_ = std_err;
+#endif /* ACE_WIN32 */
+
+ return 0; // Success.
+}
+
+int
+ACE_Process::start (char *argv[])
+{
+#if defined (ACE_WIN32)
+ ACE_ARGV argv_buf (argv);
+
+ char *buf = argv_buf.buf ();
+
+ if (buf == 0)
+ return -1;
+
+ BOOL fork_result =
+ ::CreateProcess (NULL,
+ buf,
+ NULL, // No process attributes.
+ NULL, // No thread attributes.
+ TRUE, // Allow handle inheritance.
+ NULL, // CREATE_NEW_CONSOLE, // Create a new console window.
+ NULL, // No environment.
+ NULL, // No current directory.
+ &startup_info_,
+ &process_info_);
+
+ if (set_handles_called_)
+ {
+ ::CloseHandle (startup_info_.hStdInput);
+ ::CloseHandle (startup_info_.hStdOutput);
+ ::CloseHandle (startup_info_.hStdOutput);
+ set_handles_called_ = 0;
+ }
+
+ if (fork_result) // If success.
+ return 0;
+ else
+ // CreateProcess failed.
+ return -1;
+#else /* ACE_WIN32 */
+ // Fork the new process.
+ this->child_id_ = ACE_OS::fork ();
+
+ switch (this->child_id_)
+ {
+ case -1:
+ // Error.
+ return -1;
+ case 0:
+ if (stdin_ != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (stdin_, ACE_STDIN) == -1)
+ return -1;
+ else if (stdout_ != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (stdout_, ACE_STDOUT) == -1)
+ return -1;
+ else if (stderr_ != ACE_INVALID_HANDLE
+ && ACE_OS::dup2 (stderr_, ACE_STDERR) == -1)
+ return -1;
+
+ // Child process executes the command.
+ if (ACE_OS::execv (argv[0], argv) == -1)
+ // If the execv fails, this child needs to exit.
+ ACE_OS::exit (errno);
+ default:
+ // Server process. The fork succeeded.
+ return 0;
+ }
+#endif /* ACE_WIN32 */
+}
+
+ACE_Process::ACE_Process (char *argv[],
+ ACE_HANDLE std_in,
+ ACE_HANDLE std_out,
+ ACE_HANDLE std_err)
+#if defined (ACE_WIN32)
+ : set_handles_called_ (0)
+#else /* ACE_WIN32 */
+ : stdin_ (ACE_INVALID_HANDLE),
+ stdout_ (ACE_INVALID_HANDLE),
+ stderr_ (ACE_INVALID_HANDLE)
+#endif /* ACE_WIN32 */
+{
+#if defined (ACE_WIN32)
+ ACE_OS::memset ((void *) &startup_info_, 0, sizeof startup_info_);
+ ACE_OS::memset ((void *) &process_info_, 0, sizeof process_info_);
+ startup_info_.cb = sizeof startup_info_;
+#endif /* ACE_WIN32 */
+
+ if (this->set_handles (std_in, std_out, std_err) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "set_handles"));
+ else if (this->start (argv) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "start"));
+}