Skip to content

Commit 08cda06

Browse files
committed
added support to run shellhost with -notty
1 parent bc83d7d commit 08cda06

File tree

1 file changed

+175
-13
lines changed

1 file changed

+175
-13
lines changed

contrib/win32/win32compat/shell-host.c

Lines changed: 175 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)