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