@@ -1205,134 +1205,6 @@ static IntrinsicResult intrinsic_keyEcho(Context *context, IntrinsicResult parti
12051205}
12061206
12071207
1208- #if WINDOWS
1209- // timeout : The time to wait in milliseconds before killing the child process.
1210- bool CreateChildProcess (const String& cmd, String& out, String& err, DWORD& returnCode, DWORD timeout) {
1211- SECURITY_ATTRIBUTES saAttr;
1212- saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
1213- saAttr.bInheritHandle = TRUE ;
1214- saAttr.lpSecurityDescriptor = nullptr ;
1215-
1216- HANDLE hChildStd_OUT_Rd = nullptr ;
1217- HANDLE hChildStd_OUT_Wr = nullptr ;
1218- HANDLE hChildStd_ERR_Rd = nullptr ;
1219- HANDLE hChildStd_ERR_Wr = nullptr ;
1220-
1221- // Create a pipe for the child process's STDOUT.
1222- if (!CreatePipe (&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0 ))
1223- return false ;
1224-
1225- // Ensure the read handle to the pipe for STDOUT is not inherited.
1226- SetHandleInformation (hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 );
1227-
1228- // Create a pipe for the child process's STDERR.
1229- if (!CreatePipe (&hChildStd_ERR_Rd, &hChildStd_ERR_Wr, &saAttr, 0 ))
1230- return false ;
1231-
1232- // Ensure the read handle to the pipe for STDERR is not inherited.
1233- SetHandleInformation (hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0 );
1234-
1235- STARTUPINFO siStartInfo;
1236- ZeroMemory (&siStartInfo, sizeof (STARTUPINFO));
1237- siStartInfo.cb = sizeof (STARTUPINFO);
1238- siStartInfo.hStdError = hChildStd_ERR_Wr;
1239- siStartInfo.hStdOutput = hChildStd_OUT_Wr;
1240- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
1241-
1242- PROCESS_INFORMATION piProcInfo;
1243- ZeroMemory (&piProcInfo, sizeof (PROCESS_INFORMATION));
1244-
1245- // Start the child process.
1246- if (!CreateProcessA (nullptr ,
1247- (LPSTR)cmd.c_str (), // command line
1248- nullptr , // process security attributes
1249- nullptr , // primary thread security attributes
1250- TRUE , // handles are inherited
1251- 0 , // creation flags
1252- nullptr , // use parent's environment
1253- nullptr , // use parent's current directory
1254- &siStartInfo, // STARTUPINFO pointer
1255- &piProcInfo)) // receives PROCESS_INFORMATION
1256- {
1257- return false ;
1258- }
1259-
1260- // Close handles to the stdin and stdout pipes no longer needed by the child process.
1261- // If they are not explicitly closed, there is no way to recognize that the child process has completed.
1262- CloseHandle (hChildStd_OUT_Wr);
1263- CloseHandle (hChildStd_ERR_Wr);
1264-
1265- // Read output from the child process's pipe for STDOUT
1266- // and print to the parent process's STDOUT.
1267- DWORD dwRead;
1268- CHAR chBuf[4096 ];
1269- bool bSuccess = FALSE ;
1270-
1271- for (;;) {
1272- bSuccess = ReadFile (hChildStd_OUT_Rd, chBuf, 4096 , &dwRead, nullptr );
1273- if (!bSuccess || dwRead == 0 ) break ;
1274-
1275- String outputStr (chBuf, dwRead);
1276- out += outputStr;
1277- }
1278-
1279- // Read from STDERR
1280- for (;;) {
1281- bSuccess = ReadFile (hChildStd_ERR_Rd, chBuf, 4096 , &dwRead, nullptr );
1282- if (!bSuccess || dwRead == 0 ) break ;
1283-
1284- String errorStr (chBuf, dwRead);
1285- err += errorStr;
1286- }
1287-
1288- // Wait until child process exits or timeout
1289- DWORD waitResult = WaitForSingleObject (piProcInfo.hProcess , timeout);
1290- if (waitResult == WAIT_TIMEOUT) {
1291- // If the process is still running after the timeout, terminate it
1292- TerminateProcess (piProcInfo.hProcess , 1 ); // Use 1 or another number to indicate forced termination
1293-
1294- err += " Timed out" ;
1295- returnCode = 124 << 8 ; // (124 is status code used by `timeout` command)
1296- }
1297-
1298- // Regardless of the outcome, try to get the exit code
1299- if (!GetExitCodeProcess (piProcInfo.hProcess , &returnCode)) {
1300- returnCode = (DWORD)-1 ; // Use -1 or another value to indicate that getting the exit code failed
1301- }
1302-
1303- // Close handles to the child process and its primary thread.
1304- CloseHandle (piProcInfo.hProcess );
1305- CloseHandle (piProcInfo.hThread );
1306-
1307- // Close the remaining pipe handles.
1308- CloseHandle (hChildStd_OUT_Rd);
1309- CloseHandle (hChildStd_ERR_Rd);
1310-
1311- return true ;
1312- }
1313-
1314- static IntrinsicResult intrinsic_exec (Context* context, IntrinsicResult partialResult) {
1315- String cmd = " cmd /k " + context->GetVar (" cmd" ).ToString ();
1316- String out;
1317- String err;
1318- DWORD returnCode;
1319-
1320- double timeoutSecs = context->GetVar (" timeout" ).DoubleValue ();
1321- double timeoutMs = (timeoutSecs == 0 ) ? INFINITE : (timeoutSecs * 1000 );
1322-
1323- if (!CreateChildProcess (cmd, out, err, returnCode, timeoutMs)) {
1324- Error (" Failed to create child process." );
1325- }
1326-
1327- // Build our result map.
1328- ValueDict result;
1329- result.SetValue (" output" , Value (out));
1330- result.SetValue (" errors" , Value (err));
1331- result.SetValue (" status" , Value (returnCode));
1332- return IntrinsicResult (result);
1333- }
1334- #else
1335-
13361208static IntrinsicResult intrinsic_exec (Context *context, IntrinsicResult partialResult) {
13371209 double now = context->vm ->RunTime ();
13381210 if (partialResult.Done ()) {
0 commit comments