Added ExecCmd::which + fix member variable names
--HG-- branch : WINDOWSPORT
This commit is contained in:
parent
e0dbadddc2
commit
40671020e4
@ -202,7 +202,11 @@ RclConfig *recollinit(RclInitFlags flags,
|
|||||||
// Init smallut and pathut static values
|
// Init smallut and pathut static values
|
||||||
pathut_init_mt();
|
pathut_init_mt();
|
||||||
smallut_init_mt();
|
smallut_init_mt();
|
||||||
|
// Init execmd.h static PATH and PATHELT splitting
|
||||||
|
{string bogus;
|
||||||
|
ExecCmd::which("nosuchcmd", bogus);
|
||||||
|
}
|
||||||
|
|
||||||
// Init Unac translation exceptions
|
// Init Unac translation exceptions
|
||||||
string unacex;
|
string unacex;
|
||||||
if (config->getConfParam("unac_except_trans", unacex) && !unacex.empty())
|
if (config->getConfParam("unac_except_trans", unacex) && !unacex.empty())
|
||||||
|
|||||||
@ -373,20 +373,29 @@ bool TempDir::wipe()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_catslash(string &s) {
|
void path_catslash(string &s)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
path_slashize(s);
|
||||||
|
#endif
|
||||||
if (s.empty() || s[s.length() - 1] != '/')
|
if (s.empty() || s[s.length() - 1] != '/')
|
||||||
s += '/';
|
s += '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
string path_cat(const string &s1, const string &s2) {
|
string path_cat(const string &s1, const string &s2)
|
||||||
|
{
|
||||||
string res = s1;
|
string res = s1;
|
||||||
path_catslash(res);
|
path_catslash(res);
|
||||||
res += s2;
|
res += s2;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
string path_getfather(const string &s) {
|
string path_getfather(const string &s)
|
||||||
|
{
|
||||||
string father = s;
|
string father = s;
|
||||||
|
#ifdef WIN32
|
||||||
|
path_slashize(father);
|
||||||
|
#endif
|
||||||
|
|
||||||
// ??
|
// ??
|
||||||
if (father.empty())
|
if (father.empty())
|
||||||
@ -409,8 +418,12 @@ string path_getfather(const string &s) {
|
|||||||
return father;
|
return father;
|
||||||
}
|
}
|
||||||
|
|
||||||
string path_getsimple(const string &s) {
|
string path_getsimple(const string &s)
|
||||||
|
{
|
||||||
string simple = s;
|
string simple = s;
|
||||||
|
#ifdef WIN32
|
||||||
|
path_slashize(simple);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (simple.empty())
|
if (simple.empty())
|
||||||
return simple;
|
return simple;
|
||||||
@ -508,6 +521,10 @@ string path_tildexpand(const string &s)
|
|||||||
if (s.empty() || s[0] != '~')
|
if (s.empty() || s[0] != '~')
|
||||||
return s;
|
return s;
|
||||||
string o = s;
|
string o = s;
|
||||||
|
#ifdef WIN32
|
||||||
|
path_slashize(o);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s.length() == 1) {
|
if (s.length() == 1) {
|
||||||
o.replace(0, 1, path_home());
|
o.replace(0, 1, path_home());
|
||||||
} else if (s[1] == '/') {
|
} else if (s[1] == '/') {
|
||||||
@ -532,7 +549,8 @@ bool path_isroot(const string& path)
|
|||||||
if (path.size() == 1 && path[0] == '/')
|
if (path.size() == 1 && path[0] == '/')
|
||||||
return true;
|
return true;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (path.size() == 3 && isalpha(path[0]) && path[1] == ':' && path[2] == '/')
|
if (path.size() == 3 && isalpha(path[0]) && path[1] == ':' &&
|
||||||
|
(path[2] == '/' || path[2] == '\\'))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@ -555,12 +573,15 @@ string path_absolute(const string &is)
|
|||||||
if (is.length() == 0)
|
if (is.length() == 0)
|
||||||
return is;
|
return is;
|
||||||
string s = is;
|
string s = is;
|
||||||
if (s[0] != '/') {
|
if (!path_isabsolute(s)) {
|
||||||
char buf[MAXPATHLEN];
|
char buf[MAXPATHLEN];
|
||||||
if (!getcwd(buf, MAXPATHLEN)) {
|
if (!getcwd(buf, MAXPATHLEN)) {
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
s = path_cat(string(buf), s);
|
s = path_cat(string(buf), s);
|
||||||
|
#ifdef _WIN32
|
||||||
|
path_slashize(s);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
#include "execmd.h"
|
#include "execmd.h"
|
||||||
|
|
||||||
@ -6,6 +7,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
#include "safesysstat.h"
|
||||||
|
#include "safeunistd.h"
|
||||||
|
#include "smallut.h"
|
||||||
|
#include "pathut.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -18,49 +23,50 @@ static void printError(const string& text)
|
|||||||
class ExecCmd::Internal {
|
class ExecCmd::Internal {
|
||||||
public:
|
public:
|
||||||
Internal()
|
Internal()
|
||||||
: advise(0), provide(0), timeoutMs(1000),
|
: m_advise(0), m_provide(0), m_timeoutMs(1000),
|
||||||
hOutputRead(NULL), hInputWrite(NULL) {
|
m_hOutputRead(NULL), m_hInputWrite(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> m_env;
|
vector<string> m_env;
|
||||||
ExecCmdAdvise *advise;
|
ExecCmdAdvise *m_advise;
|
||||||
ExecCmdProvide *provide;
|
ExecCmdProvide *m_provide;
|
||||||
bool killRequest;
|
|
||||||
int timeoutMs;
|
bool m_killRequest;
|
||||||
string stderrFile;
|
int m_timeoutMs;
|
||||||
|
string m_stderrFile;
|
||||||
// Subprocess id
|
// Subprocess id
|
||||||
HANDLE hOutputRead;
|
HANDLE m_hOutputRead;
|
||||||
HANDLE hInputWrite;
|
HANDLE m_hInputWrite;
|
||||||
OVERLAPPED oOutputRead; // Do these need resource control?
|
OVERLAPPED m_oOutputRead; // Do these need resource control?
|
||||||
OVERLAPPED oInputWrite;
|
OVERLAPPED m_oInputWrite;
|
||||||
PROCESS_INFORMATION piProcInfo;
|
PROCESS_INFORMATION m_piProcInfo;
|
||||||
|
|
||||||
// Reset internal state indicators. Any resources should have been
|
// Reset internal state indicators. Any resources should have been
|
||||||
// previously freed
|
// previously freed
|
||||||
void reset() {
|
void reset() {
|
||||||
killRequest = false;
|
m_killRequest = false;
|
||||||
hOutputRead = NULL;
|
m_hOutputRead = NULL;
|
||||||
hInputWrite = NULL;
|
m_hInputWrite = NULL;
|
||||||
memset(&oOutputRead, 0, sizeof(oOutputRead));
|
memset(&m_oOutputRead, 0, sizeof(m_oOutputRead));
|
||||||
memset(&oInputWrite, 0, sizeof(oInputWrite));
|
memset(&m_oInputWrite, 0, sizeof(m_oInputWrite));
|
||||||
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
|
ZeroMemory(&m_piProcInfo, sizeof(PROCESS_INFORMATION));
|
||||||
}
|
}
|
||||||
void releaseResources() {
|
void releaseResources() {
|
||||||
if (piProcInfo.hProcess)
|
if (m_piProcInfo.hProcess)
|
||||||
CloseHandle(piProcInfo.hProcess);
|
CloseHandle(m_piProcInfo.hProcess);
|
||||||
if (piProcInfo.hThread)
|
if (m_piProcInfo.hThread)
|
||||||
CloseHandle(piProcInfo.hThread);
|
CloseHandle(m_piProcInfo.hThread);
|
||||||
if (hOutputRead)
|
if (m_hOutputRead)
|
||||||
CloseHandle(hOutputRead);
|
CloseHandle(m_hOutputRead);
|
||||||
if (hInputWrite)
|
if (m_hInputWrite)
|
||||||
CloseHandle(hInputWrite);
|
CloseHandle(m_hInputWrite);
|
||||||
if (oOutputRead.hEvent)
|
if (m_oOutputRead.hEvent)
|
||||||
CloseHandle(oOutputRead.hEvent);
|
CloseHandle(m_oOutputRead.hEvent);
|
||||||
if (oInputWrite.hEvent)
|
if (m_oInputWrite.hEvent)
|
||||||
CloseHandle(oInputWrite.hEvent);
|
CloseHandle(m_oInputWrite.hEvent);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
bool PreparePipes(bool has_input, HANDLE *hChildInput,
|
bool preparePipes(bool has_input, HANDLE *hChildInput,
|
||||||
bool has_output, HANDLE *hChildOutput,
|
bool has_output, HANDLE *hChildOutput,
|
||||||
HANDLE *hChildError);
|
HANDLE *hChildError);
|
||||||
};
|
};
|
||||||
@ -78,36 +84,111 @@ ExecCmd::~ExecCmd()
|
|||||||
m->releaseResources();
|
m->releaseResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In mt programs the static vector computations below needs a call
|
||||||
|
// from main before going mt. This is done by rclinit and saves having
|
||||||
|
// to take a lock on every call
|
||||||
|
static bool is_exe(const string& path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (access(path.c_str(), X_OK) == 0 && stat(path.c_str(), &st) == 0 &&
|
||||||
|
S_ISREG(st.st_mode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static bool is_exe_base(const string& path)
|
||||||
|
{
|
||||||
|
static vector<string> exts;
|
||||||
|
if (exts.empty()) {
|
||||||
|
const char *ep = getenv("PATHEXT");
|
||||||
|
if (!ep || !*ep) {
|
||||||
|
ep = ".com;.exe;.bat;.cmd";
|
||||||
|
}
|
||||||
|
string eps(ep);
|
||||||
|
trimstring(eps, ";");
|
||||||
|
stringToTokens(eps, exts, ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_exe(path))
|
||||||
|
return true;
|
||||||
|
for (auto it = exts.begin(); it != exts.end(); it++) {
|
||||||
|
if (is_exe(path + *it))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_path_vec(const char *ep, vector<string>& vec)
|
||||||
|
{
|
||||||
|
if (ep && *ep) {
|
||||||
|
string eps(ep);
|
||||||
|
trimstring(eps, ";");
|
||||||
|
stringToTokens(eps, vec, ";");
|
||||||
|
}
|
||||||
|
vec.insert(vec.begin(), ".\\");
|
||||||
|
}
|
||||||
|
|
||||||
bool ExecCmd::which(const string& cmd, string& exe, const char* path)
|
bool ExecCmd::which(const string& cmd, string& exe, const char* path)
|
||||||
{
|
{
|
||||||
|
static vector<string> s_pathelts;
|
||||||
|
vector<string> pathelts;
|
||||||
|
vector<string> *pep;
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
make_path_vec(path, pathelts);
|
||||||
|
pep = &pathelts;
|
||||||
|
} else {
|
||||||
|
if (s_pathelts.empty()) {
|
||||||
|
const char *ep = getenv("PATH");
|
||||||
|
make_path_vec(ep, s_pathelts);
|
||||||
|
}
|
||||||
|
pep = &s_pathelts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.find_first_of("/\\") != string::npos) {
|
||||||
|
if (is_exe_base(cmd)) {
|
||||||
|
exe = cmd;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
exe.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = pep->begin(); it != pep->end(); it++) {
|
||||||
|
exe = path_cat(*it, cmd);
|
||||||
|
if (is_exe_base(exe)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exe.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecCmd::setAdvise(ExecCmdAdvise *adv)
|
void ExecCmd::setAdvise(ExecCmdAdvise *adv)
|
||||||
{
|
{
|
||||||
m->advise = adv;
|
m->m_advise = adv;
|
||||||
}
|
}
|
||||||
void ExecCmd::setProvide(ExecCmdProvide *p)
|
void ExecCmd::setProvide(ExecCmdProvide *p)
|
||||||
{
|
{
|
||||||
m->provide = p;
|
m->m_provide = p;
|
||||||
}
|
}
|
||||||
void ExecCmd::setTimeout(int mS)
|
void ExecCmd::setTimeout(int mS)
|
||||||
{
|
{
|
||||||
if (mS > 30) {
|
if (mS > 30) {
|
||||||
m->timeoutMs = mS;
|
m->m_timeoutMs = mS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ExecCmd::setStderr(const std::string& stderrFile)
|
void ExecCmd::setStderr(const std::string& stderrFile)
|
||||||
{
|
{
|
||||||
m->stderrFile = stderrFile;
|
m->m_stderrFile = stderrFile;
|
||||||
}
|
}
|
||||||
pid_t ExecCmd::getChildPid()
|
pid_t ExecCmd::getChildPid()
|
||||||
{
|
{
|
||||||
return m->piProcInfo.dwProcessId;
|
return m->m_piProcInfo.dwProcessId;
|
||||||
}
|
}
|
||||||
void ExecCmd::setKill()
|
void ExecCmd::setKill()
|
||||||
{
|
{
|
||||||
m->killRequest = true;
|
m->m_killRequest = true;
|
||||||
}
|
}
|
||||||
void ExecCmd::zapChild()
|
void ExecCmd::zapChild()
|
||||||
{
|
{
|
||||||
@ -125,7 +206,7 @@ void ExecCmd::putenv(const string &name, const string& value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
bool ExecCmd::Internal::preparePipes(bool has_input,HANDLE *hChildInput,
|
||||||
bool has_output, HANDLE *hChildOutput,
|
bool has_output, HANDLE *hChildOutput,
|
||||||
HANDLE *hChildError)
|
HANDLE *hChildError)
|
||||||
{
|
{
|
||||||
@ -134,22 +215,22 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
HANDLE hOutputWrite = NULL;
|
HANDLE hOutputWrite = NULL;
|
||||||
HANDLE hErrorWrite = NULL;
|
HANDLE hErrorWrite = NULL;
|
||||||
HANDLE hInputRead = NULL;
|
HANDLE hInputRead = NULL;
|
||||||
hOutputRead = NULL;
|
m_hOutputRead = NULL;
|
||||||
hInputWrite = NULL;
|
m_hInputWrite = NULL;
|
||||||
memset(&oOutputRead, 0, sizeof(oOutputRead));
|
memset(&m_oOutputRead, 0, sizeof(m_oOutputRead));
|
||||||
memset(&oInputWrite, 0, sizeof(oInputWrite));
|
memset(&m_oInputWrite, 0, sizeof(m_oInputWrite));
|
||||||
|
|
||||||
// manual reset event
|
// manual reset event
|
||||||
oOutputRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
m_oOutputRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (oOutputRead.hEvent == INVALID_HANDLE_VALUE) {
|
if (m_oOutputRead.hEvent == INVALID_HANDLE_VALUE) {
|
||||||
LOGERR(("ExecCmd::PreparePipes: CreateEvent failed\n"));
|
LOGERR(("ExecCmd::preparePipes: CreateEvent failed\n"));
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
// manual reset event
|
// manual reset event
|
||||||
oInputWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
m_oInputWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (oInputWrite.hEvent == INVALID_HANDLE_VALUE) {
|
if (m_oInputWrite.hEvent == INVALID_HANDLE_VALUE) {
|
||||||
LOGERR(("ExecCmd::PreparePipes: CreateEvent failed\n"));
|
LOGERR(("ExecCmd::preparePipes: CreateEvent failed\n"));
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +274,6 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
printError("preparePipes: CreateFile(outputWrite)");
|
printError("preparePipes: CreateFile(outputWrite)");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All is well? not quite. Our main server-side handle was
|
// All is well? not quite. Our main server-side handle was
|
||||||
// created shareable.
|
// created shareable.
|
||||||
// That means the client will receive it, and we have a
|
// That means the client will receive it, and we have a
|
||||||
@ -205,7 +285,7 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
// the child inherits the properties and, as a result,
|
// the child inherits the properties and, as a result,
|
||||||
// non-closeable handles to the pipes are created.
|
// non-closeable handles to the pipes are created.
|
||||||
if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp,
|
if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp,
|
||||||
GetCurrentProcess(), &hOutputRead,
|
GetCurrentProcess(), &m_hOutputRead,
|
||||||
0, FALSE, // Make it uninheritable.
|
0, FALSE, // Make it uninheritable.
|
||||||
DUPLICATE_SAME_ACCESS)) {
|
DUPLICATE_SAME_ACCESS)) {
|
||||||
printError("preparePipes: DuplicateHandle(readtmp->outputread)");
|
printError("preparePipes: DuplicateHandle(readtmp->outputread)");
|
||||||
@ -238,7 +318,7 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
|
|
||||||
// Stderr: output to file or inherit. We don't support the file thing
|
// Stderr: output to file or inherit. We don't support the file thing
|
||||||
// for the moment
|
// for the moment
|
||||||
if (false && !stderrFile.empty()) {
|
if (false && !m_stderrFile.empty()) {
|
||||||
// Open the file set up the child handle: TBD
|
// Open the file set up the child handle: TBD
|
||||||
} else {
|
} else {
|
||||||
// Let the child inherit our standard input
|
// Let the child inherit our standard input
|
||||||
@ -259,12 +339,12 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
if (has_input) {
|
if (has_input) {
|
||||||
// now same procedure for input pipe
|
// now same procedure for input pipe
|
||||||
|
|
||||||
HANDLE hInputWriteTmp = CreateNamedPipe(
|
HANDLE m_hInputWriteTmp = CreateNamedPipe(
|
||||||
TEXT("\\\\.\\pipe\\instreamPipe"),
|
TEXT("\\\\.\\pipe\\instreamPipe"),
|
||||||
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||||
1, 4096, 4096, 0, &sa);
|
1, 4096, 4096, 0, &sa);
|
||||||
if (hInputWriteTmp == INVALID_HANDLE_VALUE) {
|
if (m_hInputWriteTmp == INVALID_HANDLE_VALUE) {
|
||||||
printError("preparePipes: CreateNamedPipe(inputWTmp)");
|
printError("preparePipes: CreateNamedPipe(inputWTmp)");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@ -280,18 +360,18 @@ bool ExecCmd::Internal::PreparePipes(bool has_input,HANDLE *hChildInput,
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DuplicateHandle(GetCurrentProcess(), hInputWriteTmp,
|
if (!DuplicateHandle(GetCurrentProcess(), m_hInputWriteTmp,
|
||||||
GetCurrentProcess(), &hInputWrite,
|
GetCurrentProcess(), &m_hInputWrite,
|
||||||
0, FALSE, // Make it uninheritable.
|
0, FALSE, // Make it uninheritable.
|
||||||
DUPLICATE_SAME_ACCESS)) {
|
DUPLICATE_SAME_ACCESS)) {
|
||||||
printError("preparePipes: DuplicateHandle(inputWTmp->inputW)");
|
printError("preparePipes: DuplicateHandle(inputWTmp->inputW)");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
if (!CloseHandle(hInputWriteTmp)) {
|
if (!CloseHandle(m_hInputWriteTmp)) {
|
||||||
printError("preparePipes: CloseHandle(inputWTmp)");
|
printError("preparePipes: CloseHandle(inputWTmp)");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
hInputWriteTmp = NULL;
|
m_hInputWriteTmp = NULL;
|
||||||
} else {
|
} else {
|
||||||
// Let the child inherit our standard input
|
// Let the child inherit our standard input
|
||||||
HANDLE hstd = GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE hstd = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
@ -412,7 +492,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
|
|||||||
HANDLE hInputRead;
|
HANDLE hInputRead;
|
||||||
HANDLE hOutputWrite;
|
HANDLE hOutputWrite;
|
||||||
HANDLE hErrorWrite;
|
HANDLE hErrorWrite;
|
||||||
if (!m->PreparePipes(has_input, &hInputRead, has_output,
|
if (!m->preparePipes(has_input, &hInputRead, has_output,
|
||||||
&hOutputWrite, &hErrorWrite)) {
|
&hOutputWrite, &hErrorWrite)) {
|
||||||
LOGERR(("ExecCmd::startExec: preparePipes failed\n"));
|
LOGERR(("ExecCmd::startExec: preparePipes failed\n"));
|
||||||
m->releaseResources();
|
m->releaseResources();
|
||||||
@ -423,7 +503,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
|
|||||||
BOOL bSuccess = FALSE;
|
BOOL bSuccess = FALSE;
|
||||||
|
|
||||||
// Set up members of the PROCESS_INFORMATION structure.
|
// Set up members of the PROCESS_INFORMATION structure.
|
||||||
ZeroMemory(&m->piProcInfo, sizeof(PROCESS_INFORMATION));
|
ZeroMemory(&m->m_piProcInfo, sizeof(PROCESS_INFORMATION));
|
||||||
|
|
||||||
// Set up members of the STARTUPINFO structure.
|
// Set up members of the STARTUPINFO structure.
|
||||||
// This structure specifies the STDIN and STDOUT handles for redirection.
|
// This structure specifies the STDIN and STDOUT handles for redirection.
|
||||||
@ -448,7 +528,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
|
|||||||
NULL, // use parent's environment
|
NULL, // use parent's environment
|
||||||
NULL, // use parent's current directory
|
NULL, // use parent's current directory
|
||||||
&siStartInfo, // STARTUPINFO pointer
|
&siStartInfo, // STARTUPINFO pointer
|
||||||
&m->piProcInfo); // receives PROCESS_INFORMATION
|
&m->m_piProcInfo); // receives PROCESS_INFORMATION
|
||||||
if (!bSuccess) {
|
if (!bSuccess) {
|
||||||
printError("ExecCmd::doexec: CreateProcess");
|
printError("ExecCmd::doexec: CreateProcess");
|
||||||
} else {
|
} else {
|
||||||
@ -500,8 +580,8 @@ int ExecCmd::send(const string& data)
|
|||||||
DWORD dwWritten;
|
DWORD dwWritten;
|
||||||
BOOL bSuccess = false;
|
BOOL bSuccess = false;
|
||||||
|
|
||||||
bSuccess = WriteFile(m->hInputWrite, data.c_str(), (DWORD)data.size(),
|
bSuccess = WriteFile(m->m_hInputWrite, data.c_str(), (DWORD)data.size(),
|
||||||
NULL, &m->oInputWrite);
|
NULL, &m->m_oInputWrite);
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
|
|
||||||
// TODO: some more decision, either the operation completes immediately
|
// TODO: some more decision, either the operation completes immediately
|
||||||
@ -512,20 +592,20 @@ int ExecCmd::send(const string& data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitResult waitRes = Wait(m->oInputWrite.hEvent, m->timeoutMs);
|
WaitResult waitRes = Wait(m->m_oInputWrite.hEvent, m->m_timeoutMs);
|
||||||
if (waitRes == Ok) {
|
if (waitRes == Ok) {
|
||||||
if (!GetOverlappedResult(m->hInputWrite,
|
if (!GetOverlappedResult(m->m_hInputWrite,
|
||||||
&m->oInputWrite, &dwWritten, TRUE)) {
|
&m->m_oInputWrite, &dwWritten, TRUE)) {
|
||||||
printError("GetOverlappedResult");
|
printError("GetOverlappedResult");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if (waitRes == Quit) {
|
} else if (waitRes == Quit) {
|
||||||
if (!CancelIo(m->hInputWrite)) {
|
if (!CancelIo(m->m_hInputWrite)) {
|
||||||
printError("CancelIo");
|
printError("CancelIo");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else if (waitRes == Timeout) {
|
} else if (waitRes == Timeout) {
|
||||||
if (!CancelIo(m->hInputWrite)) {
|
if (!CancelIo(m->m_hInputWrite)) {
|
||||||
printError("CancelIo");
|
printError("CancelIo");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -549,8 +629,8 @@ int ExecCmd::receive(string& data, int cnt)
|
|||||||
const int BUFSIZE = 8192;
|
const int BUFSIZE = 8192;
|
||||||
CHAR chBuf[BUFSIZE];
|
CHAR chBuf[BUFSIZE];
|
||||||
int toread = cnt > 0 ? MIN(cnt - totread, BUFSIZE) : BUFSIZE;
|
int toread = cnt > 0 ? MIN(cnt - totread, BUFSIZE) : BUFSIZE;
|
||||||
BOOL bSuccess = ReadFile(m->hOutputRead, chBuf, toread,
|
BOOL bSuccess = ReadFile(m->m_hOutputRead, chBuf, toread,
|
||||||
NULL, &m->oOutputRead);
|
NULL, &m->m_oOutputRead);
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
LOGDEB1(("receive: ReadFile: success %d err %d\n",
|
LOGDEB1(("receive: ReadFile: success %d err %d\n",
|
||||||
int(bSuccess), int(err)));
|
int(bSuccess), int(err)));
|
||||||
@ -559,35 +639,35 @@ int ExecCmd::receive(string& data, int cnt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitResult waitRes = Wait(m->oOutputRead.hEvent, 1000);
|
WaitResult waitRes = Wait(m->m_oOutputRead.hEvent, 1000);
|
||||||
if (waitRes == Ok) {
|
if (waitRes == Ok) {
|
||||||
DWORD dwRead;
|
DWORD dwRead;
|
||||||
if (!GetOverlappedResult(m->hOutputRead, &m->oOutputRead,
|
if (!GetOverlappedResult(m->m_hOutputRead, &m->m_oOutputRead,
|
||||||
&dwRead, TRUE)) {
|
&dwRead, TRUE)) {
|
||||||
printError("GetOverlappedResult");
|
printError("GetOverlappedResult");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
totread += dwRead;
|
totread += dwRead;
|
||||||
data.append(chBuf, dwRead);
|
data.append(chBuf, dwRead);
|
||||||
if (m->advise)
|
if (m->m_advise)
|
||||||
m->advise->newData(dwRead);
|
m->m_advise->newData(dwRead);
|
||||||
LOGDEB(("ExecCmd::receive: got %d bytes\n", int(dwRead)));
|
LOGDEB(("ExecCmd::receive: got %d bytes\n", int(dwRead)));
|
||||||
} else if (waitRes == Quit) {
|
} else if (waitRes == Quit) {
|
||||||
if (!CancelIo(m->hOutputRead)) {
|
if (!CancelIo(m->m_hOutputRead)) {
|
||||||
printError("CancelIo");
|
printError("CancelIo");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (waitRes == Timeout) {
|
} else if (waitRes == Timeout) {
|
||||||
// We only want to cancel if m_advise says so here. Is the io still
|
// We only want to cancel if m_advise says so here. Is the io still
|
||||||
// valid at this point ? Should we catch a possible exception to CancelIo?
|
// valid at this point ? Should we catch a possible exception to CancelIo?
|
||||||
if (m->advise)
|
if (m->m_advise)
|
||||||
m->advise->newData(0);
|
m->m_advise->newData(0);
|
||||||
if (m->killRequest) {
|
if (m->m_killRequest) {
|
||||||
LOGINFO(("ExecCmd::doexec: cancel request\n"));
|
LOGINFO(("ExecCmd::doexec: cancel request\n"));
|
||||||
if (!CancelIo(m->hOutputRead)) {
|
if (!CancelIo(m->m_hOutputRead)) {
|
||||||
printError("CancelIo");
|
printError("CancelIo");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -603,11 +683,11 @@ int ExecCmd::getline(std::string& data)
|
|||||||
int ExecCmd::wait()
|
int ExecCmd::wait()
|
||||||
{
|
{
|
||||||
// Wait until child process exits.
|
// Wait until child process exits.
|
||||||
WaitForSingleObject(m->piProcInfo.hProcess, INFINITE);
|
WaitForSingleObject(m->m_piProcInfo.hProcess, INFINITE);
|
||||||
|
|
||||||
// Get exit code
|
// Get exit code
|
||||||
DWORD exit_code = 0;
|
DWORD exit_code = 0;
|
||||||
GetExitCodeProcess(m->piProcInfo.hProcess, &exit_code);
|
GetExitCodeProcess(m->m_piProcInfo.hProcess, &exit_code);
|
||||||
|
|
||||||
// Release all resources
|
// Release all resources
|
||||||
m->releaseResources();
|
m->releaseResources();
|
||||||
|
|||||||
@ -27,9 +27,14 @@ using namespace std;
|
|||||||
bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
|
bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
|
||||||
vector<string>& files)
|
vector<string>& files)
|
||||||
{
|
{
|
||||||
ExecCmd cmd;
|
if (files.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
vector<string> myparams;
|
ExecCmd cmd;
|
||||||
|
vector<string> myparams;
|
||||||
|
// Hack for windows: the command is always "Python somescript"
|
||||||
|
myparams.push_back(files[0]);
|
||||||
|
files.erase(files.begin());
|
||||||
|
|
||||||
if (cmd.startExec(cmdstr, myparams, 1, 1) < 0) {
|
if (cmd.startExec(cmdstr, myparams, 1, 1) < 0) {
|
||||||
cerr << "startExec " << cmdstr << " failed. Missing command?\n";
|
cerr << "startExec " << cmdstr << " failed. Missing command?\n";
|
||||||
@ -228,7 +233,7 @@ int main(int argc, char *argv[])
|
|||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
cout << "MESSAGE " << i << " FROM TREXECMD\n";
|
cout << "MESSAGE " << i << " FROM TREXECMD\n";
|
||||||
cout.flush();
|
cout.flush();
|
||||||
sleep(1);
|
//sleep(1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
default: Usage(); break;
|
default: Usage(); break;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user