Skip to content

Commit

Permalink
Merge pull request #151 from marcgurevitx/tidify-windows-exec
Browse files Browse the repository at this point in the history
Delete obsolete WINDOWS section of exec from ShellIntrinsics
  • Loading branch information
JoeStrout authored Jul 28, 2024
2 parents 4ac0ca5 + 53efb64 commit 1ce1036
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 135 deletions.
8 changes: 3 additions & 5 deletions MiniScript-cpp/src/ShellExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
130 changes: 0 additions & 130 deletions MiniScript-cpp/src/ShellIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1ce1036

Please sign in to comment.