TVision

 view release on metacpan or  search on metacpan

tvision.git/source/platform/unixclip.cpp  view on Meta::CPAN

                free(text.data());
                return true;
            }
            break;
        }
    return false;
}

static bool executable_exists(const char *name)
{
    const char *path = "";
    if (name[0] != '/' && !(path = getenv("PATH")))
        path = "/usr/local/bin:/bin:/usr/bin";
    const char *end = path + strlen(path);
    size_t nameLen = strlen(name);
    const char *p = path;
    do
    {
        char buf[PATH_MAX];
        const char *q = strchr(p, ':');
        if (!q)
            q = end;
        if (q - p + nameLen + 2 <= PATH_MAX)
        {
            memcpy(&buf[0], p, q - p);
            buf[q - p] = '/';
            memcpy(&buf[q - p + 1], name, nameLen);
            buf[q - p + nameLen + 1] = '\0';

            struct stat st;
            if (stat(buf, &st) == 0 && !(~st.st_mode & (S_IFREG | S_IXOTH)))
                return true;
        }
        p = q;
    }
    while (p < end && *p++);
    return false;
}

enum class run_subprocess_mode
{
    read,
    write,
};

struct run_subprocess_t
{
    pid_t pid {-1};
    int fd {-1};
};

static run_subprocess_t run_subprocess(const char * const argv[], const char * const env[], run_subprocess_mode mode)
{
    int fds[2];
    if (pipe(fds) == -1)
        return {};
    pid_t pid = fork();
    if (pid == 0)
    {
        for (auto *p = env; p && *p; p += 2)
            setenv(p[0], p[1], true);

        int nul     = open("/dev/null", O_RDWR);
        int new_in  = mode == run_subprocess_mode::read ? nul    : fds[0];
        int new_out = mode == run_subprocess_mode::read ? fds[1] : nul;

        if ( nul != -1
             && dup2(new_in, STDIN_FILENO) != -1
             && dup2(new_out, STDOUT_FILENO) != -1
             && dup2(nul, STDERR_FILENO) != -1
             && close(fds[0]) != -1
             && close(fds[1]) != -1
             && close(nul) != -1 )
        {
            execvp(argv[0], (char * const *) argv);
        }
        _Exit(1);
    }
    else if (pid > 0)
    {
        int pipe_end = mode == run_subprocess_mode::read ? 0 : 1;
        close(fds[1 - pipe_end]);
        return {pid, fds[pipe_end]};
    }
    for (int fd : fds)
        close(fd);
    return {};
}

static bool close_subprocess(run_subprocess_t &process)
{
    close(process.fd);
    int status;
    int res = waitpid(process.pid, &status, 0);
    return res > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
}

struct read_pipe_t
{
    char *data {nullptr};
    size_t size {0};
    bool incomplete {false};
};

static read_pipe_t read_pipe(int fd, int timeoutMs)
{
    int flags = fcntl(fd, F_GETFL);
    if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
        return {};
    enum { minReadSize = 4096 };
    char *buf = (char *) malloc(minReadSize);
    if (!buf)
        return {};
    size_t bytesRead = 0;
    size_t capacity = minReadSize;
    int res = -1;
    while (true)
    {
        ssize_t r;
        while ((r = read(fd, buf + bytesRead, capacity - bytesRead)) > 0)
        {



( run in 0.819 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )