diff --git a/MiniScript-cpp/src/ShellExec.cpp b/MiniScript-cpp/src/ShellExec.cpp index 7869f73..4fcb609 100644 --- a/MiniScript-cpp/src/ShellExec.cpp +++ b/MiniScript-cpp/src/ShellExec.cpp @@ -41,14 +41,12 @@ String readFromFd(HANDLE fd, bool trimTrailingNewline=true) { buffer[bytesRead] = '\0'; if (trimTrailingNewline and bytesRead < bufferSize-1 and bytesRead > 0 and buffer[bytesRead-1] == '\n') { // Efficiently trim \n or \r\n from the end of the buffer - buffer[bytesRead-1] = '\0'; - if (bytesRead > 1 and buffer[bytesRead-2] == '\r') { - buffer[bytesRead-2] = '\0'; - } + bytesRead--; + if (bytesRead > 0 and buffer[bytesRead-1] == '\r') bytesRead--; trimmed = true; } - String s(buffer, bytesRead+1); + String s(buffer, bytesRead); output += s; } diff --git a/MiniScript-cpp/src/ShellIntrinsics.cpp b/MiniScript-cpp/src/ShellIntrinsics.cpp index 178c2b4..3bab145 100644 --- a/MiniScript-cpp/src/ShellIntrinsics.cpp +++ b/MiniScript-cpp/src/ShellIntrinsics.cpp @@ -1124,135 +1124,6 @@ static IntrinsicResult intrinsic_rawDataSetUtf8(Context *context, IntrinsicResul return IntrinsicResult(nBytes); } -#if WINDOWS -// timeout : The time to wait in milliseconds before killing the child process. -bool CreateChildProcess(const String& cmd, String& out, String& err, DWORD& returnCode, DWORD timeout) { - SECURITY_ATTRIBUTES saAttr; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = nullptr; - - HANDLE hChildStd_OUT_Rd = nullptr; - HANDLE hChildStd_OUT_Wr = nullptr; - HANDLE hChildStd_ERR_Rd = nullptr; - HANDLE hChildStd_ERR_Wr = nullptr; - - // Create a pipe for the child process's STDOUT. - if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0)) - return false; - - // Ensure the read handle to the pipe for STDOUT is not inherited. - SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0); - - // Create a pipe for the child process's STDERR. - if (!CreatePipe(&hChildStd_ERR_Rd, &hChildStd_ERR_Wr, &saAttr, 0)) - return false; - - // Ensure the read handle to the pipe for STDERR is not inherited. - SetHandleInformation(hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0); - - STARTUPINFO siStartInfo; - ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); - siStartInfo.hStdError = hChildStd_ERR_Wr; - siStartInfo.hStdOutput = hChildStd_OUT_Wr; - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - - PROCESS_INFORMATION piProcInfo; - ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); - - // Start the child process. - if (!CreateProcessA(nullptr, - (LPSTR)cmd.c_str(), // command line - nullptr, // process security attributes - nullptr, // primary thread security attributes - TRUE, // handles are inherited - 0, // creation flags - nullptr, // use parent's environment - nullptr, // use parent's current directory - &siStartInfo, // STARTUPINFO pointer - &piProcInfo)) // receives PROCESS_INFORMATION - { - return false; - } - - // Close handles to the stdin and stdout pipes no longer needed by the child process. - // If they are not explicitly closed, there is no way to recognize that the child process has completed. - CloseHandle(hChildStd_OUT_Wr); - CloseHandle(hChildStd_ERR_Wr); - - // Read output from the child process's pipe for STDOUT - // and print to the parent process's STDOUT. - DWORD dwRead; - CHAR chBuf[4096]; - bool bSuccess = FALSE; - - for (;;) { - bSuccess = ReadFile(hChildStd_OUT_Rd, chBuf, 4096, &dwRead, nullptr); - if (!bSuccess || dwRead == 0) break; - - String outputStr(chBuf, dwRead); - out += outputStr; - } - - // Read from STDERR - for (;;) { - bSuccess = ReadFile(hChildStd_ERR_Rd, chBuf, 4096, &dwRead, nullptr); - if (!bSuccess || dwRead == 0) break; - - String errorStr(chBuf, dwRead); - err += errorStr; - } - - // Wait until child process exits or timeout - DWORD waitResult = WaitForSingleObject(piProcInfo.hProcess, timeout); - if (waitResult == WAIT_TIMEOUT) { - // If the process is still running after the timeout, terminate it - TerminateProcess(piProcInfo.hProcess, 1); // Use 1 or another number to indicate forced termination - - err += "Timed out"; - returnCode = 124 << 8; // (124 is status code used by `timeout` command) - } - - // Regardless of the outcome, try to get the exit code - if (!GetExitCodeProcess(piProcInfo.hProcess, &returnCode)) { - returnCode = (DWORD)-1; // Use -1 or another value to indicate that getting the exit code failed - } - - // Close handles to the child process and its primary thread. - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); - - // Close the remaining pipe handles. - CloseHandle(hChildStd_OUT_Rd); - CloseHandle(hChildStd_ERR_Rd); - - return true; -} - -static IntrinsicResult intrinsic_exec(Context* context, IntrinsicResult partialResult) { - String cmd = "cmd /k " + context->GetVar("cmd").ToString(); - String out; - String err; - DWORD returnCode; - - double timeoutSecs = context->GetVar("timeout").DoubleValue(); - double timeoutMs = (timeoutSecs == 0) ? INFINITE : (timeoutSecs * 1000); - - if (!CreateChildProcess(cmd, out, err, returnCode, timeoutMs)) { - Error("Failed to create child process."); - } - - // Build our result map. - ValueDict result; - result.SetValue("output", Value(out)); - result.SetValue("errors", Value(err)); - result.SetValue("status", Value(returnCode)); - return IntrinsicResult(result); -} -#else - - static IntrinsicResult intrinsic_exec(Context *context, IntrinsicResult partialResult) { double now = context->vm->RunTime(); if (partialResult.Done()) { @@ -1284,7 +1155,6 @@ static IntrinsicResult intrinsic_exec(Context *context, IntrinsicResult partialR return IntrinsicResult(data, false); } } -#endif static bool disallowAssignment(ValueDict& dict, Value key, Value value) { return true;