@@ -1047,7 +1047,7 @@ DWORD ProcessMessages(void* p)
10471047 return 0 ;
10481048}
10491049
1050- int wmain (int ac , wchar_t * * av ) {
1050+ int start_with_pty (int ac , wchar_t * * av ) {
10511051 STARTUPINFO si ;
10521052 PROCESS_INFORMATION pi ;
10531053 wchar_t cmd [MAX_PATH ];
@@ -1076,18 +1076,6 @@ int wmain(int ac, wchar_t **av) {
10761076 memset (& sa , 0 , sizeof (SECURITY_ATTRIBUTES ));
10771077 sa .bInheritHandle = TRUE;
10781078
1079- /* create job to hold all child processes */
1080- {
1081- /* TODO - this does not work as expected*/
1082- HANDLE job = CreateJobObject (NULL , NULL );
1083- JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info ;
1084- memset (& job_info , 0 , sizeof (JOBOBJECT_EXTENDED_LIMIT_INFORMATION ));
1085- job_info .BasicLimitInformation .LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE ;
1086- if (!SetInformationJobObject (job , JobObjectExtendedLimitInformation , & job_info , sizeof (job_info )))
1087- return -1 ;
1088- CloseHandle (job );
1089- }
1090-
10911079 /* WM_APPEXIT */
10921080 hostThreadId = GetCurrentThreadId ();
10931081 hostProcessId = GetCurrentProcessId ();
@@ -1170,3 +1158,177 @@ int wmain(int ac, wchar_t **av) {
11701158
11711159 return 0 ;
11721160}
1161+
1162+ HANDLE child_pipe_read ;
1163+ HANDLE child_pipe_write ;
1164+ DWORD WINAPI MonitorChild_nopty (
1165+ _In_ LPVOID lpParameter
1166+ ) {
1167+ WaitForSingleObject (child , INFINITE );
1168+ CloseHandle (pipe_in );
1169+ //printf("XXXX CHILD PROCESS DEAD XXXXX");
1170+ return 0 ;
1171+ }
1172+
1173+ int start_withno_pty (int ac , wchar_t * * av ) {
1174+ STARTUPINFO si ;
1175+ PROCESS_INFORMATION pi ;
1176+ wchar_t cmd [MAX_PATH ];
1177+ SECURITY_ATTRIBUTES sa ;
1178+ BOOL ret ;
1179+
1180+ pipe_in = GetStdHandle (STD_INPUT_HANDLE );
1181+ pipe_out = GetStdHandle (STD_OUTPUT_HANDLE );
1182+ pipe_err = GetStdHandle (STD_ERROR_HANDLE );
1183+
1184+ /* copy pipe handles passed through std io*/
1185+ if ((pipe_in == INVALID_HANDLE_VALUE )
1186+ || (pipe_out == INVALID_HANDLE_VALUE )
1187+ || (pipe_err == INVALID_HANDLE_VALUE ))
1188+ return -1 ;
1189+
1190+ memset (& sa , 0 , sizeof (SECURITY_ATTRIBUTES ));
1191+ sa .bInheritHandle = TRUE;
1192+ if (!CreatePipe (& child_pipe_read , & child_pipe_write , & sa , 128 ))
1193+ return -1 ;
1194+
1195+ memset (& si , 0 , sizeof (STARTUPINFO ));
1196+ memset (& pi , 0 , sizeof (PROCESS_INFORMATION ));
1197+
1198+ si .cb = sizeof (STARTUPINFO );
1199+ si .dwFlags = STARTF_USESTDHANDLES ;
1200+ si .hStdInput = child_pipe_read ;
1201+ si .hStdOutput = pipe_out ;
1202+ si .hStdError = pipe_err ;
1203+
1204+ /* disable inheritance on child_pipe_write and pipe_in*/
1205+ GOTO_CLEANUP_ON_FALSE (SetHandleInformation (pipe_in , HANDLE_FLAG_INHERIT , 0 ));
1206+ GOTO_CLEANUP_ON_FALSE (SetHandleInformation (child_pipe_write , HANDLE_FLAG_INHERIT , 0 ));
1207+
1208+ /*TODO - pick this up from system32*/
1209+ cmd [0 ] = L'\0' ;
1210+ GOTO_CLEANUP_ON_ERR (wcscat_s (cmd , MAX_PATH , L"cmd.exe" ));
1211+ ac -= 2 ;
1212+ av += 2 ;
1213+ if (ac )
1214+ GOTO_CLEANUP_ON_ERR (wcscat_s (cmd , MAX_PATH , L" /c" ));
1215+ while (ac ) {
1216+ GOTO_CLEANUP_ON_ERR (wcscat_s (cmd , MAX_PATH , L" " ));
1217+ GOTO_CLEANUP_ON_ERR (wcscat_s (cmd , MAX_PATH , * av ));
1218+ ac -- ;
1219+ av ++ ;
1220+ }
1221+
1222+ GOTO_CLEANUP_ON_FALSE (CreateProcess (NULL , cmd , NULL , NULL , TRUE, 0 , NULL , NULL , & si , & pi ));
1223+
1224+ /* close unwanted handles*/
1225+ CloseHandle (child_pipe_read );
1226+ child_pipe_read = INVALID_HANDLE_VALUE ;
1227+
1228+ child = pi .hProcess ;
1229+ /* monitor child exist */
1230+ monitor_thread = CreateThread (NULL , 0 , MonitorChild_nopty , NULL , 0 , NULL );
1231+ if (monitor_thread == INVALID_HANDLE_VALUE )
1232+ goto cleanup ;
1233+
1234+ /* disable Ctrl+C hander in this process*/
1235+ SetConsoleCtrlHandler (NULL , TRUE);
1236+
1237+ /* process data from pipe_in and route appropriately */
1238+ while (1 ) {
1239+ char buf [128 ];
1240+ DWORD rd = 0 , wr = 0 , i = 0 ;
1241+ GOTO_CLEANUP_ON_FALSE (ReadFile (pipe_in , buf , 128 , & rd , NULL ));
1242+
1243+ while (i < rd ) {
1244+
1245+ /* skip arrow keys */
1246+ if ((rd - i >= 3 ) && (buf [i ] == '\033' ) && (buf [i + 1 ] == '[' )
1247+ && (buf [i + 2 ] >= 'A' ) && (buf [i + 2 ] <= 'D' )) {
1248+ i += 3 ;
1249+ continue ;
1250+ }
1251+
1252+ /* skip tab */
1253+ if (buf [i ] == '\t' ) {
1254+ i ++ ;
1255+ continue ;
1256+ }
1257+
1258+ // Ctrl +C
1259+ if (buf [i ] == '\003' ) {
1260+ GOTO_CLEANUP_ON_FALSE (GenerateConsoleCtrlEvent (CTRL_C_EVENT , 0 ));
1261+ in_cmd_len = 0 ;
1262+ i ++ ;
1263+ continue ;
1264+ }
1265+
1266+ // for backspace, we need to send space and another backspace for visual erase
1267+ if (buf [i ] == '\b' ) {
1268+ if (in_cmd_len > 0 ) {
1269+ GOTO_CLEANUP_ON_FALSE (WriteFile (pipe_out , "\b \b" , 3 , & wr , NULL ));
1270+ in_cmd_len -- ;
1271+ }
1272+ i ++ ;
1273+ continue ;
1274+ }
1275+
1276+ //for CR and LF
1277+ if ((buf [i ] == '\r' ) || (buf [i ] == '\n' )) {
1278+
1279+ /* TODO - do a much accurate mapping */
1280+ GOTO_CLEANUP_ON_FALSE (WriteFile (pipe_out , buf + i , 1 , & wr , NULL ));
1281+ if ((buf [i ] == '\r' ) && ((i == rd - 1 ) || (buf [i + 1 ] != '\n' ))) {
1282+ buf [i ] = '\n' ;
1283+ GOTO_CLEANUP_ON_FALSE (WriteFile (pipe_out , buf + i , 1 , & wr , NULL ));
1284+ }
1285+ in_cmd [in_cmd_len ] = buf [i ];
1286+ in_cmd_len ++ ;
1287+ GOTO_CLEANUP_ON_FALSE (WriteFile (child_pipe_write , in_cmd , in_cmd_len , & wr , NULL ));
1288+ in_cmd_len = 0 ;
1289+ i ++ ;
1290+ continue ;
1291+ }
1292+
1293+
1294+ GOTO_CLEANUP_ON_FALSE (WriteFile (pipe_out , buf + i , 1 , & wr , NULL ));
1295+ in_cmd [in_cmd_len ] = buf [i ];
1296+ in_cmd_len ++ ;
1297+ if (in_cmd_len == MAX_CMD_LEN - 1 ) {
1298+ GOTO_CLEANUP_ON_FALSE (WriteFile (child_pipe_write , in_cmd , in_cmd_len , & wr , NULL ));
1299+ in_cmd_len = 0 ;
1300+ }
1301+
1302+ i ++ ;
1303+ }
1304+ }
1305+
1306+ cleanup :
1307+
1308+ if (child != INVALID_HANDLE_VALUE )
1309+ TerminateProcess (child , 0 );
1310+ if (monitor_thread != INVALID_HANDLE_VALUE )
1311+ WaitForSingleObject (monitor_thread , INFINITE );
1312+ return 0 ;
1313+ }
1314+
1315+ int wmain (int ac , wchar_t * * av ) {
1316+
1317+
1318+ /* create job to hold all child processes */
1319+ {
1320+ /* TODO - this does not work as expected*/
1321+ HANDLE job = CreateJobObject (NULL , NULL );
1322+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info ;
1323+ memset (& job_info , 0 , sizeof (JOBOBJECT_EXTENDED_LIMIT_INFORMATION ));
1324+ job_info .BasicLimitInformation .LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE ;
1325+ if (!SetInformationJobObject (job , JobObjectExtendedLimitInformation , & job_info , sizeof (job_info )))
1326+ return -1 ;
1327+ CloseHandle (job );
1328+ }
1329+
1330+ if ((ac == 1 ) || wcscmp (av [1 ], L"-nopty" ))
1331+ return start_with_pty (ac , av );
1332+ else
1333+ return start_withno_pty (ac , av );
1334+ }
0 commit comments