diff --git a/libs/main/system/piprocess.cpp b/libs/main/system/piprocess.cpp index 6af89a70..19684090 100644 --- a/libs/main/system/piprocess.cpp +++ b/libs/main/system/piprocess.cpp @@ -23,6 +23,7 @@ # include "piincludes_p.h" # include "piliterals_bytes.h" # include "piprocess.h" +# include "pitranslator.h" # ifndef WINDOWS # include # include @@ -89,13 +90,12 @@ using PipeHandleType = int; # endif # ifdef WINDOWS -const char * convertWindowsCmd(PIStringList sl) { - for (int i = 0; i < sl.size_s(); ++i) { - sl[i].push_front('"'); - sl[i].push_back('"'); +PIString convertWindowsCmd(PIStringList sl) { + if (sl.isNotEmpty()) { + sl[0].replaceAll('/', '\\'); + sl[0].quote(); } - PIString s = sl.join(' '); - return s.data(); + return sl.join(' '); } # else char * const * convertToCharArrays(const PIStringList & sl) { @@ -142,9 +142,9 @@ PRIVATE_DEFINITION_START(PIProcess) const int pt = pipe_type; # ifdef WINDOWS SECURITY_ATTRIBUTES saAttr; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - satrueAttr.lpSecurityDescriptor = NULL; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&(pipes[pt][PipeRead]), &(pipes[pt][PipeWrite]), &saAttr, 0)) return false; return true; # else @@ -167,6 +167,11 @@ PRIVATE_DEFINITION_START(PIProcess) } } } +# ifdef WINDOWS + if (grab[StdIn]) SetHandleInformation(pipes[StdIn][PipeWrite], HANDLE_FLAG_INHERIT, 0); + if (grab[StdOut]) SetHandleInformation(pipes[StdOut][PipeRead], HANDLE_FLAG_INHERIT, 0); + if (grab[StdErr]) SetHandleInformation(pipes[StdErr][PipeRead], HANDLE_FLAG_INHERIT, 0); +# endif return true; } @@ -178,7 +183,7 @@ PRIVATE_DEFINITION_START(PIProcess) void closePipe(PipeHandleType & hpipe) { # ifdef WINDOWS - if (hpipe] != 0) { + if (hpipe != 0) { CloseHandle(hpipe); hpipe = 0; } @@ -205,12 +210,24 @@ PRIVATE_DEFINITION_START(PIProcess) size_t offset = 0; while (1) { # ifdef WINDOWS - BOOL ok = ReadFile(pipes[pipe_type][PipeRead], read_buffer.data(offset), read_buffer.size() - offset, &bytes_read, NULL); + DWORD available = 0; + BOOL ok = PeekNamedPipe(pipes[pipe_type][PipeRead], nullptr, 0, nullptr, &available, nullptr); + // piCout << "ReadFile" << available; + if (available == 0) { + read_buffer.resize(offset); + break; + } + ok = ReadFile(pipes[pipe_type][PipeRead], + read_buffer.data(offset), + piMini(available, read_buffer.size() - offset), + &bytes_read, + nullptr); + // piCout << "ReadFile" << ok; if (!ok) bytes_read = 0; # else bytes_read = ::read(pipes[pipe_type][PipeRead], read_buffer.data(offset), read_buffer.size() - offset); # endif - piCout << "readed" << bytes_read; + // piCout << "readed" << bytes_read; if (bytes_read > 0) { offset += bytes_read; read_buffer.resize(offset + read_buffer_size); @@ -219,7 +236,7 @@ PRIVATE_DEFINITION_START(PIProcess) break; } } - piCout << "readPipe" << read_buffer.toHex(); + // piCout << "readPipe" << PIString::fromConsole(read_buffer); return read_buffer; } @@ -232,7 +249,7 @@ PRIVATE_DEFINITION_START(PIProcess) # else sz = ::write(pipes[StdIn][PipeWrite], data.data(), data.size()); # endif - piCout << "writePipe" << sz; + // piCout << "writePipe" << sz; return sz == data.size_s(); } @@ -274,23 +291,26 @@ void PIProcess::startProc(bool detached) { if (!PRIVATE->createPipes()) return; # ifdef WINDOWS STARTUPINFOA si; - piZeroMemory(pi); + piZeroMemory(si); si.cb = sizeof(STARTUPINFOA); if (PRIVATE->grab[StdIn]) si.hStdInput = PRIVATE->pipes[StdIn][PipeRead]; if (PRIVATE->grab[StdOut]) si.hStdOutput = PRIVATE->pipes[StdOut][PipeWrite]; if (PRIVATE->grab[StdErr]) si.hStdError = PRIVATE->pipes[StdErr][PipeWrite]; si.dwFlags |= STARTF_USESTDHANDLES; + const auto cmd = convertWindowsCmd(args); + // piCout << cmd; if (CreateProcessA(0, // No module name (use command line) - convertWindowsCmd(args), // Command line + (LPSTR)cmd.data(), // Command line 0, // Process handle not inheritable 0, // Thread handle not inheritable - false, // Set handle inheritance to FALSE + true, // Set handle inheritance to FALSE detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags 0, // Use environment wd.isEmpty() ? 0 : wd.data(), // Use working directory &si, // Pointer to STARTUPINFO structure &(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure { + // piCout << "started"; exec_start = true; if (!detached) { WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE); @@ -397,7 +417,12 @@ bool PIProcess::writeInput(const PIByteArray & data) { void PIProcess::closeInput() { - if (PRIVATE->grab[StdIn]) PRIVATE->closePipe(StdIn, PipeWrite); + if (PRIVATE->grab[StdIn]) { +# ifdef WINDOWS + // PRIVATE->writePipe({0x1A}); +# endif + PRIVATE->closePipe(StdIn, PipeWrite); + } } diff --git a/tests/system/process_test.cpp b/tests/system/process_test.cpp index db678929..3b2878e7 100644 --- a/tests/system/process_test.cpp +++ b/tests/system/process_test.cpp @@ -9,7 +9,7 @@ protected: PIProcess launcher; const PIString command = #ifdef _WIN32 - "cmd.exe"; + "C:/Windows/System32/cmd.exe"; #else "/bin/sh"; #endif @@ -61,7 +61,7 @@ TEST_F(ProcessTest, Output) { TEST_F(ProcessTest, Input) { #ifdef _WIN32 - const PIStringList args = {"/c", "set /p input= && echo %input%"}; + const PIStringList args = {"/c", "more"}; #else const PIStringList args = {"-c", "read input; echo $input"}; #endif @@ -73,7 +73,10 @@ TEST_F(ProcessTest, Input) { EXPECT_TRUE(launcher.isExecStarted()); EXPECT_TRUE(!launcher.isExecFinished()); - const PIString test_input = "Test input string\n"; + PIString test_input = "Test input string\n"; +#ifdef WINDOWS + test_input += (char)0x1A; +#endif EXPECT_TRUE(launcher.writeInput(test_input.toAscii())); launcher.closeInput(); @@ -91,5 +94,5 @@ TEST_F(ProcessTest, NonexistentCommand) { launcher.exec(command); ASSERT_TRUE(launcher.isRunning()); ASSERT_TRUE(launcher.waitForFinish()); - EXPECT_FALSE(!launcher.isExecFinished()); + EXPECT_FALSE(launcher.isExecFinished()); }