int main()

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;
}