int main()

in native/cyglaunch/main.c [144:225]


int main(int argc, char* argv[], char* envp[]) {
    int arg = 1;
    char *logFileName = argv[arg++];
    if (strcmp(logFileName, "null") != 0) {
        logFile = fopen(convert_path(logFileName), "w+");
    }

    bool consoleMode = (bool)atoi(argv[arg++]);

    struct pty_t pty;
    struct pty_t err_pty;

    flog("opening pty");
    if (create_pty(&pty) < 0) return -1;
    flog("opening err_pty");
    if (create_pty(&err_pty) < 0) return -1;

    struct thread_data_t thread_data_in = {pty.fdm, CreateFile(argv[arg++], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL), NULL, NULL, NULL};
    if (thread_data_in.pipe == INVALID_HANDLE_VALUE) flog("Opening in-pipe failed with %d", GetLastError());

    struct thread_data_t thread_data_out = {pty.fdm, CreateFile(argv[arg++], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), NULL, &out_cond, &out_mutex};
    if (thread_data_out.pipe == INVALID_HANDLE_VALUE) flog("Opening out-pipe failed with %d", GetLastError());

    char *errPipeName = argv[arg++];
    struct thread_data_t thread_data_err;
    if (consoleMode) {
        thread_data_err = (struct thread_data_t) {err_pty.fdm, CreateFile(errPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), NULL, &err_cond, &err_mutex};
        if (thread_data_err.pipe == INVALID_HANDLE_VALUE) flog("Opening err-pipe failed with %d", GetLastError());
    }

    char *command = argv[arg++];

    flog("converting path: %s", command);
    char *path = convert_path(command);
    flog("converted: %s", path);

    char * cargv[argc - arg + 2];
    memcpy(cargv + 1, argv + arg, sizeof(char*) * (argc - arg));
    cargv[0] = path;
    cargv[argc - arg + 1] = NULL;

    pid_t child_pid = exec_pty(path, cargv, envp, ".", pty.slave_name, pty.fdm, err_pty.slave_name, err_pty.fdm, consoleMode);
    free(path);

    flog("launched pid: %d", child_pid);

    pthread_create(&thread_data_in.tid, NULL, &readPipe, &thread_data_in);
    pthread_create(&thread_data_out.tid, NULL, &writePipe, &thread_data_out);
    if (consoleMode) {
        pthread_create(&thread_data_err.tid, NULL, &writePipe, &thread_data_err);
    }

    int status;
    bool waitpid_ok = true;
    if (waitpid(child_pid, &status, 0) < 0) {
        flog("wait for child process failed, error: %d", errno);
        waitpid_ok = false;
    } else {
        flog("child process terminated with status %d", status);
    }

    shutting_down = true;

    // Not shutting down the stdin thread because there is no way to abort synchronous ReadFile.
    // Since the process is already dead, it doesn't matter anyway.

    readOutputAndClose(thread_data_out);
    if (consoleMode) readOutputAndClose(thread_data_err);

    if (logFile != NULL) fclose(logFile);

    if (!waitpid_ok) {
        return 1;
    }
    if (WIFEXITED(status)) {
        return WEXITSTATUS(status);
    }
    if (WIFSIGNALED(status)) {
        return 128 + WTERMSIG(status);
    }
    return status;
}