Skip to content

Commit

Permalink
Merge pull request #174 from marcgurevitx/remove-old-win-exec-again
Browse files Browse the repository at this point in the history
Removing redundant Windows' intrinsic_exec part
  • Loading branch information
JoeStrout authored Jul 28, 2024
2 parents 81f923c + e722d06 commit 11d594e
Showing 1 changed file with 0 additions and 128 deletions.
128 changes: 0 additions & 128 deletions MiniScript-cpp/src/ShellIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,134 +1205,6 @@ static IntrinsicResult intrinsic_keyEcho(Context *context, IntrinsicResult parti
}


#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()) {
Expand Down

0 comments on commit 11d594e

Please sign in to comment.