@@ -1047,7 +1047,7 @@ DWORD ProcessMessages(void* p)
1047
1047
return 0 ;
1048
1048
}
1049
1049
1050
- int wmain (int ac , wchar_t * * av ) {
1050
+ int start_with_pty (int ac , wchar_t * * av ) {
1051
1051
STARTUPINFO si ;
1052
1052
PROCESS_INFORMATION pi ;
1053
1053
wchar_t cmd [MAX_PATH ];
@@ -1076,18 +1076,6 @@ int wmain(int ac, wchar_t **av) {
1076
1076
memset (& sa , 0 , sizeof (SECURITY_ATTRIBUTES ));
1077
1077
sa .bInheritHandle = TRUE;
1078
1078
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
-
1091
1079
/* WM_APPEXIT */
1092
1080
hostThreadId = GetCurrentThreadId ();
1093
1081
hostProcessId = GetCurrentProcessId ();
@@ -1170,3 +1158,177 @@ int wmain(int ac, wchar_t **av) {
1170
1158
1171
1159
return 0 ;
1172
1160
}
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