static std::string findProgram()

in src/unix-adapter/main.cc [261:319]


static std::string findProgram(
    const char *winptyProgName,
    const std::string &prog)
{
    std::string candidate;
    if (prog.find('/') == std::string::npos &&
            prog.find('\\') == std::string::npos) {
        // XXX: It would be nice to use a lambda here (once/if old MSYS support
        // is dropped).
        // Search the PATH.
        const char *const pathVar = getenv("PATH");
        const std::string pathList(pathVar ? pathVar : "");
        size_t elpos = 0;
        while (true) {
            const size_t elend = pathList.find(':', elpos);
            candidate = pathList.substr(elpos, elend - elpos);
            if (!candidate.empty() && *(candidate.end() - 1) != '/') {
                candidate += '/';
            }
            candidate += prog;
            candidate = resolvePath(candidate);
            if (!candidate.empty()) {
                int perm = X_OK;
                if (endsWith(candidate, ".bat") || endsWith(candidate, ".cmd")) {
#ifdef __MSYS__
                    // In MSYS/MSYS2, batch files don't have the execute bit
                    // set, so just check that they're readable.
                    perm = R_OK;
#endif
                } else if (endsWith(candidate, ".com") || endsWith(candidate, ".exe")) {
                    // Do nothing.
                } else {
                    // Make the exe extension explicit so that we don't try to
                    // run shell scripts with CreateProcess/winpty_spawn.
                    candidate += ".exe";
                }
                if (!access(candidate.c_str(), perm)) {
                    break;
                }
            }
            if (elend == std::string::npos) {
                fprintf(stderr, "%s: error: cannot start '%s': Not found in PATH\n",
                    winptyProgName, prog.c_str());
                exit(1);
            } else {
                elpos = elend + 1;
            }
        }
    } else {
        candidate = resolvePath(prog);
        if (candidate.empty()) {
            std::string errstr(strerror(errno));
            fprintf(stderr, "%s: error: cannot start '%s': %s\n",
                winptyProgName, prog.c_str(), errstr.c_str());
            exit(1);
        }
    }
    return convertPosixPathToWin(candidate);
}