aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-06-18 11:37:25 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-06-18 11:37:25 +0200
commit89ea9c8401d9e1b79977c6556b81b2eb4159ef59 (patch)
tree15e5e4114c08fc39d75ba9da088177c159cac06e
parent33ef0312f43646ab3dd9ff95430d70d24bc1d701 (diff)
Move process from build2 to libbutl
-rw-r--r--build/b.cxx1
-rw-r--r--build/buildfile4
-rw-r--r--build/cxx/module.cxx2
-rw-r--r--build/cxx/rule.cxx2
-rw-r--r--build/process67
-rw-r--r--build/process.cxx326
6 files changed, 4 insertions, 398 deletions
diff --git a/build/b.cxx b/build/b.cxx
index d65a6c2..24f4266 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -27,7 +27,6 @@
#include <build/file>
#include <build/module>
#include <build/algorithm>
-#include <build/process>
#include <build/diagnostics>
#include <build/context>
#include <build/utility>
diff --git a/build/buildfile b/build/buildfile
index 7d3a32a..8b4cb84 100644
--- a/build/buildfile
+++ b/build/buildfile
@@ -5,8 +5,8 @@ bin = bin/{target rule module}
cxx = cxx/{target rule module}
exe{b}: cxx{b algorithm name operation spec scope variable target \
- prerequisite rule file module context search diagnostics token lexer \
- parser process timestamp path path-io utility filesystem dump options \
+ prerequisite rule file module context search diagnostics token \
+ lexer parser timestamp path path-io utility filesystem dump options \
$config $bin $cxx} $libs
#@@ TODO
diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx
index 6efc1ed..4193104 100644
--- a/build/cxx/module.cxx
+++ b/build/cxx/module.cxx
@@ -4,11 +4,11 @@
#include <build/cxx/module>
+#include <butl/process>
#include <butl/fdstream>
#include <build/path>
#include <build/scope>
-#include <build/process>
#include <build/diagnostics>
#include <build/bin/module>
diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx
index 4fce59a..f05370d 100644
--- a/build/cxx/rule.cxx
+++ b/build/cxx/rule.cxx
@@ -10,12 +10,12 @@
#include <cstdlib> // exit
#include <utility> // move()
+#include <butl/process>
#include <butl/fdstream>
#include <build/scope>
#include <build/variable>
#include <build/algorithm>
-#include <build/process>
#include <build/timestamp>
#include <build/diagnostics>
#include <build/context>
diff --git a/build/process b/build/process
deleted file mode 100644
index 0e1a8c9..0000000
--- a/build/process
+++ /dev/null
@@ -1,67 +0,0 @@
-// file : build/process -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD_PROCESS
-#define BUILD_PROCESS
-
-#ifndef _WIN32
-# include <sys/types.h> // pid_t
-#endif
-
-#include <cassert>
-#include <system_error>
-
-namespace build
-{
-
- struct process_error: std::system_error
- {
- process_error (int e, bool child)
- : system_error (e, std::system_category ()), child_ (child) {}
-
- bool
- child () const {return child_;}
-
- private:
- bool child_;
- };
-
- struct process
- {
- // Start another process using the specified command line. Connect the
- // newly created process' stdin to out_fd. Also if connect_* are true,
- // connect the created process' stdout and stderr to in_*fd. Throw
- // process_error if anything goes wrong.
- //
- // Note that some of the exceptions (e.g., if exec() failed) can be
- // thrown in the child version of us.
- //
- process (char const* args[],
- bool connect_stdin = false,
- bool connect_stderr = false,
- bool connect_stdout = false);
-
- // Wait for the process to terminate. Return true if the process
- // terminated normally and with the zero exit status. Throw
- // process_error if anything goes wrong.
- //
- bool
- wait ();
-
- ~process () {assert (id == 0);}
-
-#ifndef _WIN32
- typedef pid_t id_type;
-#else
- typedef void* id_type; // Win32 HANDLE.
-#endif
-
- id_type id;
- int out_fd; // Write to this fd to send to the new process' stdin.
- int in_efd; // Read from this fd to receive from the new process' stderr.
- int in_ofd; // Read from this fd to receive from the new process' stdout.
- };
-}
-
-#endif // BUILD_PROCESS
diff --git a/build/process.cxx b/build/process.cxx
deleted file mode 100644
index 53e66c3..0000000
--- a/build/process.cxx
+++ /dev/null
@@ -1,326 +0,0 @@
-// file : build/process.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build/process>
-
-#ifndef _WIN32
-# include <unistd.h> // execvp, fork, dup2, pipe, {STDIN,STDERR}_FILENO
-# include <sys/wait.h> // waitpid
-#else
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h> // CreatePipe, CreateProcess
-# include <io.h> // _open_osfhandle
-# include <fcntl.h> // _O_TEXT
-#endif
-
-using namespace std;
-
-namespace build
-{
-#ifndef _WIN32
-
- process::
- process (char const* args[], bool in, bool err, bool out)
- {
- int out_fd[2];
- int in_efd[2];
- int in_ofd[2];
-
- if ((in && pipe (out_fd) == -1) ||
- (err && pipe (in_efd) == -1) ||
- (out && pipe (in_ofd) == -1))
- throw process_error (errno, false);
-
- id = fork ();
-
- if (id == -1)
- throw process_error (errno, false);
-
- if (id == 0)
- {
- // Child. If requested, close the write end of the pipe and duplicate
- // the read end to stdin. Then close the original read end descriptor.
- //
- if (in)
- {
- if (close (out_fd[1]) == -1 ||
- dup2 (out_fd[0], STDIN_FILENO) == -1 ||
- close (out_fd[0]) == -1)
- throw process_error (errno, true);
- }
-
- // Do the same for the stderr if requested.
- //
- if (err)
- {
- if (close (in_efd[0]) == -1 ||
- dup2 (in_efd[1], STDERR_FILENO) == -1 ||
- close (in_efd[1]) == -1)
- throw process_error (errno, true);
- }
-
- // Do the same for the stdout if requested.
- //
- if (out)
- {
- if (close (in_ofd[0]) == -1 ||
- dup2 (in_ofd[1], STDOUT_FILENO) == -1 ||
- close (in_ofd[1]) == -1)
- throw process_error (errno, true);
- }
-
- if (execvp (args[0], const_cast<char**> (&args[0])) == -1)
- throw process_error (errno, true);
- }
- else
- {
- // Parent. Close the other ends of the pipes.
- //
- if ((in && close (out_fd[0]) == -1) ||
- (err && close (in_efd[1]) == -1) ||
- (out && close (in_ofd[1]) == -1))
- throw process_error (errno, false);
- }
-
- this->out_fd = in ? out_fd[1] : 0;
- this->in_efd = err ? in_efd[0] : 0;
- this->in_ofd = out ? in_ofd[0] : 0;
- }
-
- bool process::
- wait ()
- {
- int status;
- int r (waitpid (id, &status, 0));
- id = 0; // We have tried.
-
- if (r == -1)
- throw process_error (errno, false);
-
- return WIFEXITED (status) && WEXITSTATUS (status) == 0;
- }
-
-#else // _WIN32
-
- static void
- print_error (char const* name)
- {
- LPTSTR msg;
- DWORD e (GetLastError());
-
- if (!FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- 0,
- e,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &msg,
- 0,
- 0))
- {
- cerr << name << ": error: unknown error code " << e << endl;
- return;
- }
-
- cerr << name << ": error: " << msg << endl;
- LocalFree (msg);
- }
-
- static process_info
- start_process (char const* args[], char const* name, bool err, bool out)
- {
- HANDLE out_h[2];
- HANDLE in_eh[2];
- HANDLE in_oh[2];
- SECURITY_ATTRIBUTES sa;
-
- sa.nLength = sizeof (SECURITY_ATTRIBUTES);
- sa.bInheritHandle = true;
- sa.lpSecurityDescriptor = 0;
-
- if (!CreatePipe (&out_h[0], &out_h[1], &sa, 0) ||
- !SetHandleInformation (out_h[1], HANDLE_FLAG_INHERIT, 0))
- {
- print_error (name);
- throw process_failure ();
- }
-
- if (err)
- {
- if (!CreatePipe (&in_eh[0], &in_eh[1], &sa, 0) ||
- !SetHandleInformation (in_eh[0], HANDLE_FLAG_INHERIT, 0))
- {
- print_error (name);
- throw process_failure ();
- }
- }
-
- if (out)
- {
- if (!CreatePipe (&in_oh[0], &in_oh[1], &sa, 0) ||
- !SetHandleInformation (in_oh[0], HANDLE_FLAG_INHERIT, 0))
- {
- print_error (name);
- throw process_failure ();
- }
- }
-
- // Create the process.
- //
- path file (args[0]);
-
- // Do PATH search.
- //
- if (file.directory ().empty ())
- file = path_search (file);
-
- if (file.empty ())
- {
- cerr << args[0] << ": error: file not found" << endl;
- throw process_failure ();
- }
-
- // Serialize the arguments to string.
- //
- string cmd_line;
-
- for (char const** p (args); *p != 0; ++p)
- {
- if (p != args)
- cmd_line += ' ';
-
- // On Windows we need to protect values with spaces using quotes.
- // Since there could be actual quotes in the value, we need to
- // escape them.
- //
- string a (*p);
- bool quote (a.find (' ') != string::npos);
-
- if (quote)
- cmd_line += '"';
-
- for (size_t i (0); i < a.size (); ++i)
- {
- if (a[i] == '"')
- cmd_line += "\\\"";
- else
- cmd_line += a[i];
- }
-
- if (quote)
- cmd_line += '"';
- }
-
- // Prepare other info.
- //
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
-
- memset (&si, 0, sizeof (STARTUPINFO));
- memset (&pi, 0, sizeof (PROCESS_INFORMATION));
-
- si.cb = sizeof(STARTUPINFO);
-
- if (err)
- si.hStdError = in_eh[1];
- else
- si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
-
- if (out)
- si.hStdOutput = in_oh[1];
- else
- si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
-
- si.hStdInput = out_h[0];
- si.dwFlags |= STARTF_USESTDHANDLES;
-
- if (!CreateProcess (
- file.string ().c_str (),
- const_cast<char*> (cmd_line.c_str ()),
- 0, // Process security attributes.
- 0, // Primary thread security attributes.
- true, // Inherit handles.
- 0, // Creation flags.
- 0, // Use our environment.
- 0, // Use our current directory.
- &si,
- &pi))
- {
- print_error (name);
- throw process_failure ();
- }
-
- CloseHandle (pi.hThread);
- CloseHandle (out_h[0]);
-
- if (err)
- CloseHandle (in_eh[1]);
-
- if (out)
- CloseHandle (in_oh[1]);
-
- process_info r;
- r.id = pi.hProcess;
- r.out_fd = _open_osfhandle ((intptr_t) (out_h[1]), 0);
-
- if (r.out_fd == -1)
- {
- cerr << name << ": error: unable to obtain C file handle" << endl;
- throw process_failure ();
- }
-
- if (err)
- {
- // Pass _O_TEXT to get newline translation.
- //
- r.in_efd = _open_osfhandle ((intptr_t) (in_eh[0]), _O_TEXT);
-
- if (r.in_efd == -1)
- {
- cerr << name << ": error: unable to obtain C file handle" << endl;
- throw process_failure ();
- }
- }
- else
- r.in_efd = 0;
-
- if (out)
- {
- // Pass _O_TEXT to get newline translation.
- //
- r.in_ofd = _open_osfhandle ((intptr_t) (in_oh[0]), _O_TEXT);
-
- if (r.in_ofd == -1)
- {
- cerr << name << ": error: unable to obtain C file handle" << endl;
- throw process_failure ();
- }
- }
- else
- r.in_ofd = 0;
-
- return r;
- }
-
- static bool
- wait_process (process_info pi, char const* name)
- {
- DWORD status;
-
- if (WaitForSingleObject (pi.id, INFINITE) != WAIT_OBJECT_0 ||
- !GetExitCodeProcess (pi.id, &status))
- {
- print_error (name);
- throw process_failure ();
- }
-
- CloseHandle (pi.id);
- return status == 0;
- }
-
-#endif // _WIN32
-}