in src/unix-adapter/main.cc [581:729]
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
g_mainWakeup = new WakeupFd();
Arguments args;
parseArguments(argc, argv, args);
setupWin32Environment();
winsize sz = { 0 };
sz.ws_col = 80;
sz.ws_row = 25;
ioctl(STDIN_FILENO, TIOCGWINSZ, &sz);
DWORD agentFlags = WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION;
if (args.testConerr) { agentFlags |= WINPTY_FLAG_CONERR; }
if (args.testPlainOutput) { agentFlags |= WINPTY_FLAG_PLAIN_OUTPUT; }
if (args.testColorEscapes) { agentFlags |= WINPTY_FLAG_COLOR_ESCAPES; }
winpty_config_t *agentCfg = winpty_config_new(agentFlags, NULL);
assert(agentCfg != NULL);
winpty_config_set_initial_size(agentCfg, sz.ws_col, sz.ws_row);
if (args.mouseInput) {
winpty_config_set_mouse_mode(agentCfg, WINPTY_MOUSE_MODE_FORCE);
}
winpty_error_ptr_t openErr = NULL;
winpty_t *wp = winpty_open(agentCfg, &openErr);
if (wp == NULL) {
fprintf(stderr, "Error creating winpty: %s\n",
wcsToMbs(winpty_error_msg(openErr)).c_str());
exit(1);
}
winpty_config_free(agentCfg);
winpty_error_free(openErr);
HANDLE conin = CreateFileW(winpty_conin_name(wp), GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
HANDLE conout = CreateFileW(winpty_conout_name(wp), GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL);
assert(conin != INVALID_HANDLE_VALUE);
assert(conout != INVALID_HANDLE_VALUE);
HANDLE conerr = NULL;
if (args.testConerr) {
conerr = CreateFileW(winpty_conerr_name(wp), GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL);
assert(conerr != INVALID_HANDLE_VALUE);
}
HANDLE childHandle = NULL;
{
// Start the child process under the console.
args.childArgv[0] = findProgram(argv[0], args.childArgv[0]);
std::string cmdLine = argvToCommandLine(args.childArgv);
wchar_t *cmdLineW = heapMbsToWcs(cmdLine.c_str());
winpty_spawn_config_t *spawnCfg = winpty_spawn_config_new(
WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN,
NULL, cmdLineW, NULL, NULL, NULL);
assert(spawnCfg != NULL);
winpty_error_ptr_t spawnErr = NULL;
DWORD lastError = 0;
BOOL spawnRet = winpty_spawn(wp, spawnCfg, &childHandle, NULL,
&lastError, &spawnErr);
winpty_spawn_config_free(spawnCfg);
if (!spawnRet) {
winpty_result_t spawnCode = winpty_error_code(spawnErr);
if (spawnCode == WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED) {
fprintf(stderr, "%s: error: cannot start '%s': %s\n",
argv[0],
cmdLine.c_str(),
formatErrorMessage(lastError).c_str());
} else {
fprintf(stderr, "%s: error: cannot start '%s': internal error: %s\n",
argv[0],
cmdLine.c_str(),
wcsToMbs(winpty_error_msg(spawnErr)).c_str());
}
exit(1);
}
winpty_error_free(spawnErr);
delete [] cmdLineW;
}
registerResizeSignalHandler();
SavedTermiosMode mode =
setRawTerminalMode(args.testAllowNonTtys, true, args.testConerr);
InputHandler inputHandler(conin, STDIN_FILENO, mainWakeup());
OutputHandler outputHandler(conout, STDOUT_FILENO, mainWakeup());
OutputHandler *errorHandler = NULL;
if (args.testConerr) {
errorHandler = new OutputHandler(conerr, STDERR_FILENO, mainWakeup());
}
while (true) {
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(mainWakeup().fd(), &readfds);
selectWrapper("main thread", mainWakeup().fd() + 1, &readfds);
mainWakeup().reset();
// Check for terminal resize.
{
winsize sz2;
ioctl(STDIN_FILENO, TIOCGWINSZ, &sz2);
if (memcmp(&sz, &sz2, sizeof(sz)) != 0) {
sz = sz2;
winpty_set_size(wp, sz.ws_col, sz.ws_row, NULL);
}
}
// Check for an I/O handler shutting down (possibly indicating that the
// child process has exited).
if (inputHandler.isComplete() || outputHandler.isComplete() ||
(errorHandler != NULL && errorHandler->isComplete())) {
break;
}
}
// Kill the agent connection. This will kill the agent, closing the CONIN
// and CONOUT pipes on the agent pipe, prompting our I/O handler to shut
// down.
winpty_free(wp);
inputHandler.shutdown();
outputHandler.shutdown();
CloseHandle(conin);
CloseHandle(conout);
if (errorHandler != NULL) {
errorHandler->shutdown();
delete errorHandler;
CloseHandle(conerr);
}
restoreTerminalMode(mode);
DWORD exitCode = 0;
if (!GetExitCodeProcess(childHandle, &exitCode)) {
exitCode = 1;
}
CloseHandle(childHandle);
return exitCode;
}