Ejemplo n.º 1
0
const char *
vp_kill(char *args)
{
    vp_stack_t stack;
    pid_t pid, pgid;
    int sig;
    int ret;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &pid));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sig));

    ret = kill(pid, sig);
    if (ret < 0)
        return vp_stack_return_error(&_result, "kill() error: %s",
                strerror(errno));

    if (sig != 0) {
        /* Kill by the process group. */
        pgid = getpgid(pid);
        if (pid == pgid) {
            kill(-pgid, sig);
        }
    }

    vp_stack_push_num(&_result, "%d", ret);
    return vp_stack_return(&_result);
}
Ejemplo n.º 2
0
const char *
vp_socket_read(char *args)
{
    vp_stack_t stack;
    int sock;
    int nr;
    int timeout;
    struct timeval tv;
    int n;
    char buf[VP_READ_BUFSIZE];
    fd_set fdset;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sock));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &nr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;

    FD_ZERO(&fdset);
    FD_SET((unsigned)sock, &fdset);
    vp_stack_push_str(&_result, ""); /* initialize */
    while (nr != 0) {
        n = select(0, &fdset, NULL, NULL, (timeout == -1) ? NULL : &tv);
        if (n == SOCKET_ERROR) {
            return vp_stack_return_error(&_result, "select() error: %d",
                    WSAGetLastError());
        } else if (n == 0) {
            /* timeout */
            break;
        }
        if (nr > 0)
            n = recv(sock, buf,
                    (VP_READ_BUFSIZE < nr) ? VP_READ_BUFSIZE : nr, 0);
        else
            n = recv(sock, buf, VP_READ_BUFSIZE, 0);
        if (n == -1) {
            return vp_stack_return_error(&_result, "recv() error: %s",
                    strerror(errno));
        } else if (n == 0) {
            /* eof */
            vp_stack_push_num(&_result, "%d", 1);
            return vp_stack_return(&_result);
        }
        /* decrease stack top for concatenate. */
        _result.top--;
        vp_stack_push_bin(&_result, buf, n);
        if (nr > 0)
            nr -= n;
        /* try read more bytes without waiting */
        timeout = 0;
    }
    vp_stack_push_num(&_result, "%d", 0);
    return vp_stack_return(&_result);
}
Ejemplo n.º 3
0
const char *
vp_file_write(char *args)
{
    vp_stack_t stack;
    int fd;
    char *buf;
    size_t size;
    int timeout;
    size_t nleft;
    int n;
    struct pollfd pfd = {0, POLLOUT, 0};

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    size = vp_decode_size(stack.top);
    buf = stack.top + VP_HEADER_SIZE;

    pfd.fd = fd;
    nleft = 0;
    while (nleft < size) {
        n = poll(&pfd, 1, timeout);
        if (n == -1) {
            return vp_stack_return_error(&_result, "poll() error: %s",
                    strerror(errno));
        } else if (n == 0) {
            /* timeout */
            break;
        }
        if (pfd.revents & POLLOUT) {
            n = write(fd, buf + nleft, size - nleft);
            if (n == -1) {
                return vp_stack_return_error(&_result, "write() error: %s",
                        strerror(errno));
            }
            nleft += n;
            /* try write more bytes without waiting */
            timeout = 0;
            continue;
        } else if (pfd.revents & (POLLERR | POLLHUP)) {
            /* eof or error */
            break;
        } else if (pfd.revents & POLLNVAL) {
            return vp_stack_return_error(&_result, "poll() POLLNVAL: %d",
                    pfd.revents);
        }
        /* DO NOT REACH HERE */
        return vp_stack_return_error(&_result, "poll() unknown status: %s",
                pfd.revents);
    }
    vp_stack_push_num(&_result, "%zu", nleft);
    return vp_stack_return(&_result);
}
Ejemplo n.º 4
0
const char *
vp_pty_open(char *args)
{
    vp_stack_t stack;
    int argc;
    char *argv[VP_ARGC_MAX];
    int fdm;
    pid_t pid;
    struct winsize ws = {0, 0, 0, 0};
    struct termios ti;
    int i;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_col)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_row)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));
    if (argc < 1 || VP_ARGC_MAX <= argc)
        return vp_stack_return_error(&_result, "argc range error. too many arguments. please use xargs.");
    for (i = 0; i < argc; ++i)
        VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &(argv[i])));
    argv[argc] = NULL;

#if 0
    /* TODO: set termios parameter */
    /* tcgetattr will fail when gvim is executed from gnome menu */
    if (tcgetattr(STDIN_FILENO, &ti) < 0)
        return vp_stack_return_error(&_result, "tcgetattr() error: %s",
                strerror(errno));
    pid = forkpty(&fdm, NULL, &ti, &ws);
#else
    pid = forkpty(&fdm, NULL, NULL, &ws);
#endif
    if (pid < 0) {
        return vp_stack_return_error(&_result, "forkpty() error: %s",
                strerror(errno));
    } else if (pid == 0) {
        /* child */
        if (execv(argv[0], argv) < 0) {
            /* error */
            write(fdm, strerror(errno), strlen(strerror(errno)));
            _exit(EXIT_FAILURE);
        }
    } else {
        /* parent */
        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fdm);
        /* XXX - ttyname(fdm) breaks in OS X */
        vp_stack_push_str(&_result, "unused");
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HERE */
    return NULL;
}
Ejemplo n.º 5
0
const char *
vp_pipe_read(char *args)
{
    vp_stack_t stack;
    int fd;
    int nr;
    int timeout;
    DWORD n;
    char buf[VP_READ_BUFSIZE];

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &nr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    vp_stack_push_str(&_result, ""); /* initialize */
    while (nr != 0) {
        n = 0;
        if (!PeekNamedPipe((HANDLE)_get_osfhandle(fd), buf,
                (nr < 0) ? VP_READ_BUFSIZE : (VP_READ_BUFSIZE < nr) ? VP_READ_BUFSIZE : nr,
                &n, NULL, NULL))
        {
            /* can be ERROR_HANDLE_EOF? */
            if (GetLastError() == 0 || GetLastError() == ERROR_BROKEN_PIPE) {
                /* error or eof */
                if (n != 0) {
                    /* decrease stack top for concatenate. */
                    _result.top--;
                    vp_stack_push_bin(&_result, buf, n);
                }
                vp_stack_push_num(&_result, "%d", 1);
                return vp_stack_return(&_result);
            }
            return vp_stack_return_error(&_result, "PeekNamedPipe() error: %08X %s",
                    GetLastError(), lasterror());
        }
        if (n == 0) {
            break;
        }
        if (read(fd, buf, n) == -1)
            return vp_stack_return_error(&_result, "read() error: %s",
                    strerror(errno));
        /* decrease stack top for concatenate. */
        _result.top--;
        vp_stack_push_bin(&_result, buf, n);
        if (nr > 0)
            nr -= n;
        /* try read more bytes without waiting */
        timeout = 0;
    }
    vp_stack_push_num(&_result, "%d", 0);
    return vp_stack_return(&_result);
}
Ejemplo n.º 6
0
const char *
vp_file_read(char *args)
{
    vp_stack_t stack;
    int fd;
    int nr;
    int timeout;
    DWORD ret;
    int n;
    char buf[VP_READ_BUFSIZE];

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &nr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    vp_stack_push_str(&_result, ""); /* initialize */
    while (nr != 0) {
        ret = WaitForSingleObject((HANDLE)_get_osfhandle(fd), timeout);
        if (ret == WAIT_FAILED) {
            return vp_stack_return_error(&_result, "WaitForSingleObject() error: %s",
                    lasterror());
        } else if (ret == WAIT_TIMEOUT) {
            /* timeout */
            break;
        }
        if (nr > 0)
            n = read(fd, buf, (VP_READ_BUFSIZE < nr) ? VP_READ_BUFSIZE : nr);
        else
            n = read(fd, buf, VP_READ_BUFSIZE);
        if (n == -1) {
            return vp_stack_return_error(&_result, "read() error: %s",
                    strerror(errno));
        } else if (n == 0) {
            /* eof */
            vp_stack_push_num(&_result, "%d", 1);
            return vp_stack_return(&_result);
        }
        /* decrease stack top for concatenate. */
        _result.top--;
        vp_stack_push_bin(&_result, buf, n);
        if (nr > 0)
            nr -= n;
        /* try read more bytes without waiting */
        timeout = 0;
    }
    vp_stack_push_num(&_result, "%d", 0);
    return vp_stack_return(&_result);
}
Ejemplo n.º 7
0
const char *
vp_file_open(char *args)
{
    vp_stack_t stack;
    char *path;
    char *flags;
    int mode;  /* used when flags have O_CREAT */
    int oflag = 0;
    int fd;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &path));
    VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &flags));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &mode));

    oflag = str_to_oflag(flags);
    if (oflag == -1)
        return vp_stack_return_error(&_result, "open flag error.");

    fd = open(path, oflag, mode);
    if (fd == -1)
        return vp_stack_return_error(&_result, "open() error: %s",
                strerror(errno));
    vp_stack_push_num(&_result, "%d", fd);
    return vp_stack_return(&_result);
}
Ejemplo n.º 8
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_kill(char *args)
{
    vp_stack_t stack;
    pid_t pid;
    int sig;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &pid));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sig));

    if (kill(pid, sig) == -1)
        return vp_stack_return_error(&_result, "kill() error: %s",
                strerror(errno));
    return NULL;
}
Ejemplo n.º 9
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_waitpid(char *args)
{
    vp_stack_t stack;
    pid_t pid;
    pid_t n;
    int status;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &pid));

    n = waitpid(pid, &status, WNOHANG | WUNTRACED);
    if (n == -1)
        return vp_stack_return_error(&_result, "waitpid() error: %s",
                strerror(errno));
    if (n == 0 || WIFCONTINUED(status)) {
        vp_stack_push_str(&_result, "run");
        vp_stack_push_num(&_result, "%d", 0);
    } else if (WIFEXITED(status)) {
        vp_stack_push_str(&_result, "exit");
        vp_stack_push_num(&_result, "%d", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
        vp_stack_push_str(&_result, "signal");
        vp_stack_push_num(&_result, "%d", WTERMSIG(status));
    } else if (WIFSTOPPED(status)) {
        vp_stack_push_str(&_result, "stop");
        vp_stack_push_num(&_result, "%d", WSTOPSIG(status));
    } else {
        return vp_stack_return_error(&_result,
                "waitpid() unknown status: status=%d", status);
    }
    return vp_stack_return(&_result);
}
Ejemplo n.º 10
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_pty_set_winsize(char *args)
{
    vp_stack_t stack;
    int fd;
    struct winsize ws = {0, 0, 0, 0};

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_col)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_row)));

    if (ioctl(fd, TIOCSWINSZ, &ws) < 0)
        return vp_stack_return_error(&_result, "ioctl() error: %s",
                strerror(errno));
    return NULL;
}
Ejemplo n.º 11
0
const char *
vp_kill(char *args)
{
    vp_stack_t stack;
    pid_t pid;
    int sig;
    int ret;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &pid));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sig));

    ret = kill(pid, sig);
    if (ret < 0)
        return vp_stack_return_error(&_result, "kill() error: %s",
                                     strerror(errno));
    vp_stack_push_num(&_result, "%d", ret);
    return vp_stack_return(&_result);
}
Ejemplo n.º 12
0
const char *
vp_socket_write(char *args)
{
    vp_stack_t stack;
    int sock;
    char *buf;
    size_t size;
    int timeout;
    struct timeval tv;
    size_t nleft;
    int n;
    fd_set fdset;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sock));
    VP_RETURN_IF_FAIL(vp_stack_pop_bin(&stack, &buf, &size));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;

    FD_ZERO(&fdset);
    FD_SET((unsigned)sock, &fdset);
    nleft = 0;
    while (nleft < size) {
        n = select(0, NULL, &fdset, NULL, (timeout == -1) ? NULL : &tv);
        if (n == SOCKET_ERROR) {
            return vp_stack_return_error(&_result, "select() error: %d",
                    WSAGetLastError());
        } else if (n == 0) {
            /* timeout */
            break;
        }
        n = send(sock, buf + nleft, (int)(size - nleft), 0);
        if (n == -1)
            return vp_stack_return_error(&_result, "send() error: %s",
                    strerror(errno));
        nleft += n;
        /* try write more bytes without waiting */
        timeout = 0;
    }
    vp_stack_push_num(&_result, "%u", nleft);
    return vp_stack_return(&_result);
}
Ejemplo n.º 13
0
const char *
vp_file_write(char *args)
{
    vp_stack_t stack;
    int fd;
    char *buf;
    size_t size;
    int timeout;
    size_t nleft;
    DWORD ret;
    int n;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_bin(&stack, &buf, &size));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    nleft = 0;
    while (nleft < size) {
        ret = WaitForSingleObject((HANDLE)_get_osfhandle(fd), timeout);
        if (ret == WAIT_FAILED) {
            return vp_stack_return_error(&_result, "WaitForSingleObject() error: %s",
                    lasterror());
        } else if (ret == WAIT_TIMEOUT) {
            /* timeout */
            break;
        }
        n = write(fd, buf + nleft, (unsigned int)(size - nleft));
        if (n == -1) {
            return vp_stack_return_error(&_result, "write() error: %s",
                    strerror(errno));
        }
        nleft += n;
        /* try write more bytes without waiting */
        timeout = 0;
    }
    vp_stack_push_num(&_result, "%u", nleft);
    return vp_stack_return(&_result);
}
Ejemplo n.º 14
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_file_close(char *args)
{
    vp_stack_t stack;
    int fd;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));

    if (close(fd) == -1)
        return vp_stack_return_error(&_result, "close() error: %s",
                strerror(errno));
    return NULL;
}
Ejemplo n.º 15
0
const char *
vp_pipe_close(char *args)
{
    vp_stack_t stack;
    int fd;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));

    if (!CloseHandle((HANDLE)_get_osfhandle(fd)))
        return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                lasterror());
    return NULL;
}
Ejemplo n.º 16
0
const char *
vp_dlclose(char *args)
{
    vp_stack_t stack;
    HINSTANCE handle;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%p", &handle));

    if (!FreeLibrary(handle))
        return lasterror();
    vp_stack_free(&_result);
    return NULL;
}
Ejemplo n.º 17
0
const char *
vp_kill(char *args)
{
    vp_stack_t stack;
    HANDLE handle;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%p", &handle));

    if (!TerminateProcess(handle, 2) || !CloseHandle(handle))
        return vp_stack_return_error(&_result, "kill() error: %s",
                lasterror());
    return NULL;
}
Ejemplo n.º 18
0
const char *
vp_close_handle(char *args)
{
    vp_stack_t stack;
    HANDLE handle;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%p", &handle));

    if (!CloseHandle(handle))
        return vp_stack_return_error(&_result,
                "CloseHandle() error: %s", lasterror());
    return NULL;
}
Ejemplo n.º 19
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_dlclose(char *args)
{
    vp_stack_t stack;
    void *handle;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%p", &handle));

    /* On FreeBSD6, to call dlclose() twice with same pointer causes SIGSEGV */
    if (dlclose(handle) == -1)
        return dlerror();
    vp_stack_free(&_result);
    return NULL;
}
Ejemplo n.º 20
0
const char *
vp_waitpid(char *args)
{
    vp_stack_t stack;
    HANDLE handle;
    DWORD exitcode;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%p", &handle));

    if (!GetExitCodeProcess(handle, &exitcode))
        return vp_stack_return_error(&_result,
                "GetExitCodeProcess() error: %s", lasterror());

    vp_stack_push_str(&_result, (exitcode == STILL_ACTIVE) ? "run" : "exit");
    vp_stack_push_num(&_result, "%u", exitcode);
    return vp_stack_return(&_result);
}
Ejemplo n.º 21
0
const char *
vp_socket_close(char *args)
{
    vp_stack_t stack;
    int sock;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sock));

    if (closesocket(sock) == SOCKET_ERROR) {
        return vp_stack_return_error(&_result, "closesocket() error: %d",
                WSAGetLastError());
    }
    if (--sockets_number == 0)
    {
        WSACleanup();
    }
    return NULL;
}
Ejemplo n.º 22
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_pipe_open(char *args)
{
    vp_stack_t stack;
    int npipe, hstdin, hstderr, hstdout;
    int argc;
    int fd[3][2];
    pid_t pid;
    int dummy;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error. wrong pipes.");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdin));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdout));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstderr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));

    if (hstdin) {
        fd[0][0] = hstdin;
        fd[0][1] = 0;
    } else {
        if (pipe(fd[0]) < 0) {
            return vp_stack_return_error(&_result, "pipe() error: %s",
                    strerror(errno));
        }
    }
    if (hstdout) {
        fd[1][1] = hstdout;
        fd[1][0] = 0;
    } else {
        if (pipe(fd[1]) < 0) {
            return vp_stack_return_error(&_result, "pipe() error: %s",
                    strerror(errno));
        }
    }
    if (npipe == 3) {
        if (hstderr) {
            fd[2][1] = hstderr;
            fd[2][0] = 0;
        } else {
            if (pipe(fd[2]) < 0) {
                return vp_stack_return_error(&_result, "pipe() error: %s",
                        strerror(errno));
            }
        }
    }

    pid = fork();
    if (pid < 0) {
        return vp_stack_return_error(&_result, "fork() error: %s",
                strerror(errno));
    } else if (pid == 0) {
        /* child */
        char **argv;
        int i;

        if (!hstdin) {
            close(fd[0][1]);
        }
        if (!hstdout) {
            close(fd[1][0]);
        }
        if (npipe == 3 && !hstderr) {
            close(fd[2][0]);
        }
        if (fd[0][0] != STDIN_FILENO) {
            if (dup2(fd[0][0], STDIN_FILENO) != STDIN_FILENO) {
                goto child_error;
            }
            close(fd[0][0]);
        }
        if (fd[1][1] != STDOUT_FILENO) {
            if (dup2(fd[1][1], STDOUT_FILENO) != STDOUT_FILENO) {
                goto child_error;
            }
            close(fd[1][1]);
        }
        if (npipe == 2) {
            if (dup2(STDOUT_FILENO, STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
        } else if (fd[2][1] != STDERR_FILENO) {
            if (dup2(fd[2][1], STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
            close(fd[2][1]);
        }

        argv = malloc(sizeof(char *) * (argc+1));
        if (argv == NULL) {
            goto child_error;
        }
        for (i = 0; i < argc; ++i) {
            if (vp_stack_pop_str(&stack, &(argv[i]))) {
                free(argv);
                goto child_error;
            }
        }
        argv[argc] = NULL;

        if (execvp(argv[0], argv) < 0) {
            free(argv);
            goto child_error;
        }
        free(argv);
    } else {
        /* parent */
        if (!hstdin) {
            close(fd[0][0]);
        }
        if (!hstdout) {
            close(fd[1][1]);
        }
        if (npipe == 3 && !hstderr) {
            close(fd[2][1]);
        }

        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fd[0][1]);
        vp_stack_push_num(&_result, "%d", fd[1][0]);
        if (npipe == 3)
            vp_stack_push_num(&_result, "%d", fd[2][0]);
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HEAR */
    return NULL;


    /* error */
child_error:
    dummy = write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
    _exit(EXIT_FAILURE);
}
Ejemplo n.º 23
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_file_read(char *args)
{
    vp_stack_t stack;
    int fd;
    int nr;
    int timeout;
    int n;
    char buf[VP_READ_BUFSIZE];
    struct pollfd pfd = {0, POLLIN, 0};

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &nr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    pfd.fd = fd;
    vp_stack_push_str(&_result, ""); /* initialize */
    while (nr != 0) {
        n = poll(&pfd, 1, timeout);
        if (n == -1) {
            /* eof or error */
            vp_stack_push_num(&_result, "%d", 1);
            return vp_stack_return(&_result);
        } else if (n == 0) {
            /* timeout */
            break;
        }
        if (pfd.revents & POLLIN) {
            if (nr > 0)
                n = read(fd, buf,
                        (VP_READ_BUFSIZE < nr) ? VP_READ_BUFSIZE : nr);
            else
                n = read(fd, buf, VP_READ_BUFSIZE);
            if (n == -1) {
                return vp_stack_return_error(&_result, "read() error: %s",
                        strerror(errno));
            } else if (n == 0) {
                /* eof */
                vp_stack_push_num(&_result, "%d", 1);
                return vp_stack_return(&_result);
            }
            /* decrease stack top for concatenate. */
            _result.top--;
            vp_stack_push_bin(&_result, buf, n);
            if (nr > 0)
                nr -= n;
            /* try read more bytes without waiting */
            timeout = 0;
            continue;
        } else if (pfd.revents & (POLLERR | POLLHUP)) {
            /* eof or error */
            vp_stack_push_num(&_result, "%d", 1);
            return vp_stack_return(&_result);
        } else if (pfd.revents & POLLNVAL) {
            return vp_stack_return_error(&_result, "poll() POLLNVAL: %d",
                    pfd.revents);
        }
        /* DO NOT REACH HERE */
        return vp_stack_return_error(&_result, "poll() unknown status: %d",
                pfd.revents);
    }
    vp_stack_push_num(&_result, "%d", 0);
    return vp_stack_return(&_result);
}
Ejemplo n.º 24
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_file_open(char *args)
{
    vp_stack_t stack;
    char *path;
    char *flags;
    int mode;  /* used when flags have O_CREAT */
    int f = 0;
    int fd;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &path));
    VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &flags));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &mode));

#ifdef O_RDONLY
    if (strstr(flags, "O_RDONLY"))      f |= O_RDONLY;
#endif
#ifdef O_WRONLY
    if (strstr(flags, "O_WRONLY"))      f |= O_WRONLY;
#endif
#ifdef O_RDRW
    if (strstr(flags, "O_RDRW"))        f |= O_RDWR;
#endif
#ifdef O_NONBLOCK
    if (strstr(flags, "O_NONBLOCK"))    f |= O_NONBLOCK;
#endif
#ifdef O_APPEND
    if (strstr(flags, "O_APPEND"))      f |= O_APPEND;
#endif
#ifdef O_CREAT
    if (strstr(flags, "O_CREAT"))       f |= O_CREAT;
#endif
#ifdef O_EXCL
    if (strstr(flags, "O_EXCL"))        f |= O_EXCL;
#endif
#ifdef O_TRUNC
    if (strstr(flags, "O_TRUNC"))       f |= O_TRUNC;
#endif
#ifdef O_SHLOCK
    if (strstr(flags, "O_SHLOCK"))      f |= O_SHLOCK;
#endif
#ifdef O_EXLOCK
    if (strstr(flags, "O_EXLOCK"))      f |= O_EXLOCK;
#endif
#ifdef O_DIRECT
    if (strstr(flags, "O_DIRECT"))      f |= O_DIRECT;
#endif
#ifdef O_FSYNC
    if (strstr(flags, "O_FSYNC"))       f |= O_FSYNC;
#endif
#ifdef O_NOFOLLOW
    if (strstr(flags, "O_NOFOLLOW"))    f |= O_NOFOLLOW;
#endif
#ifdef O_TEMPORARY
    if (strstr(flags, "O_TEMPORARY"))   f |= O_TEMPORARY;
#endif
#ifdef O_RANDOM
    if (strstr(flags, "O_RANDOM"))      f |= O_RANDOM;
#endif
#ifdef O_SEQUENTIAL
    if (strstr(flags, "O_SEQENTIAL"))   f |= O_SEQUENTIAL;
#endif
#ifdef O_BINARY
    if (strstr(flags, "O_BINARY"))      f |= O_BINARY;
#endif
#ifdef O_TEXT
    if (strstr(flags, "O_TEXT"))        f |= O_TEXT;
#endif
#ifdef O_INHERIT
    if (strstr(flags, "O_INHERIT"))     f |= O_INHERIT;
#endif
#ifdef _O_SHORT_LIVED
    if (strstr(flags, "O_SHORT_LIVED")) f |= _O_SHORT_LIVED;
#endif

    fd = open(path, f, mode);
    if (fd == -1)
        return vp_stack_return_error(&_result, "open() error: %s",
                strerror(errno));
    vp_stack_push_num(&_result, "%d", fd);
    return vp_stack_return(&_result);
}
Ejemplo n.º 25
0
const char *
vp_fd_read(char *args, int is_pty_pipe)
{
#ifdef __linux__
# define VP_POLLIN (POLLIN | POLLHUP)
#else
# define VP_POLLIN (POLLIN)
#endif
    vp_stack_t stack;
    int fd;
    int cnt;
    int timeout;
    int n;
    char *buf;
    char *eof;
    unsigned int size = 0;
    struct pollfd pfd = {0, POLLIN, 0};

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &cnt));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout));

    if (cnt < 0 || VP_READ_BUFSIZE < cnt) {
        cnt = VP_READ_BUFSIZE;
    }

    /* initialize buffer */
    _result.top = _result.buf;
    vp_stack_push_num(&_result, "%d", 0);   /* set eof to 0 */
    eof = _result.top - 1;
    buf = _result.top;
    *(buf++) = VP_EOV;
    buf += VP_HEADER_SIZE;

    pfd.fd = fd;
    while (cnt > 0) {
        n = poll(&pfd, 1, timeout);
        if (n == -1) {
            /* eof or error */
            *eof = '1';
            break;
        } else if (n == 0) {
            /* timeout */
            break;
        }
        if (pfd.revents & VP_POLLIN) {
            n = read(fd, buf, cnt);
            if (n == -1) {
                if (pfd.revents & POLLERR
                        || pfd.revents & POLLNVAL
                        || pfd.revents & POLLWRNORM
                        /* Cygwin(after ver.2.0) fails pty read and returns
                         * POLLIN. */
                        || (!is_pty_pipe && pfd.revents & POLLIN)
                        ) {
                    return vp_stack_return_error(&_result,
                            "read() error: revents = %d, error = %s",
                            pfd.revents, strerror(errno));
                }
                /* eof */
                *eof = '1';
                break;
            } else if (n == 0) {
                /* eof */
                *eof = '1';
                break;
            }
            /* decrease stack top for concatenate. */
            cnt -= n;
            buf += n;
            size += n;
            /* try read more bytes without waiting */
            timeout = 0;
            continue;
        } else if (pfd.revents & (POLLERR | POLLHUP)) {
            /* eof or error */
            *eof = '1';
            break;
        } else if (pfd.revents & POLLNVAL) {
            return vp_stack_return_error(&_result, "poll() POLLNVAL: %d",
                    pfd.revents);
        }
        /* DO NOT REACH HERE */
        return vp_stack_return_error(&_result, "poll() unknown status: %d",
                pfd.revents);
    }
    vp_encode_size(size, _result.top + 1);
    _result.top = buf;
    return vp_stack_return(&_result);
#undef VP_POLLIN
}
Ejemplo n.º 26
0
Archivo: proc.c Proyecto: thawk/vimproc
const char *
vp_pty_open(char *args)
{
    vp_stack_t stack;
    int argc;
    int fd[3][2];
    pid_t pid;
    struct winsize ws = {0, 0, 0, 0};
    int dummy;
    int hstdin, hstderr, hstdout;
    int fdm;
    int npipe;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error. wrong pipes.");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_col)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_row)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdin));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdout));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstderr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));

    /* Set pipe */
    if (hstdin) {
        fd[0][0] = hstdin;
        fd[0][1] = 0;
    }
    if (hstdout == 1) {
        if (pipe(fd[1]) < 0) {
            return vp_stack_return_error(&_result, "pipe() error: %s",
                    strerror(errno));
        }
    } else if (hstdout) {
        fd[1][1] = hstdout;
        fd[1][0] = 0;
    }
    if (npipe == 3) {
        if (hstderr == 1) {
            if (pipe(fd[2]) < 0) {
                return vp_stack_return_error(&_result, "pipe() error: %s",
                        strerror(errno));
            }
        } else if (hstderr == 1) {
            fd[2][1] = hstderr;
            fd[2][0] = 0;
        } else {
            if (openpty(&fd[2][0], &fd[2][1], NULL, NULL, &ws) < 0) {
                return vp_stack_return_error(&_result, "openpty() error: %s",
                        strerror(errno));
            }
        }
    }

    pid = forkpty(&fdm, NULL, NULL, &ws);
    if (hstdin == 0) {
        fd[0][1] = fdm;
    }
    if (hstdout == 0) {
        fd[1][0] = fdm;
    }
    if (hstdin == 0 && hstdout == 0) {
        fd[1][0] = dup(fdm);
    }

    if (pid < 0) {
        return vp_stack_return_error(&_result, "fork() error: %s",
                strerror(errno));
    } else if (pid == 0) {
        /* child */
        char **argv;
        int i;

        /* Close pipe */
        if (hstdout == 1) {
            close(fd[1][0]);
        }
        if (npipe == 3 && hstderr == 1) {
            close(fd[2][0]);
        }

        if (hstdin && fd[0][0] != STDIN_FILENO) {
            if (dup2(fd[0][0], STDIN_FILENO) != STDIN_FILENO) {
                goto child_error;
            }
            close(fd[0][0]);
        }

        if (hstdout && fd[1][1] != STDOUT_FILENO) {
            /* Set termios. */
            if (dup2(fd[1][1], STDOUT_FILENO) != STDOUT_FILENO) {
                goto child_error;
            }
            close(fd[1][1]);
        }

        if (npipe == 3 && fd[2][1] != STDERR_FILENO) {
            if (dup2(fd[2][1], STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
            close(fd[2][1]);
        }

        argv = malloc(sizeof(char *) * (argc+1));
        if (argv == NULL) {
            goto child_error;
        }
        for (i = 0; i < argc; ++i) {
            if (vp_stack_pop_str(&stack, &(argv[i]))) {
                free(argv);
                goto child_error;
            }
        }
        argv[argc] = NULL;

        if (execvp(argv[0], argv) < 0) {
            /* error */
            free(argv);

            goto child_error;
        }
        free(argv);
    } else {
        /* parent */
        if (hstdout == 1) {
            close(fd[1][1]);
        }
        if (npipe == 3 && (hstderr == 0 || hstderr == 1)) {
            close(fd[2][1]);
        }

        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fd[0][1]);
        vp_stack_push_num(&_result, "%d", fd[1][0]);
        if (npipe == 3) {
            vp_stack_push_num(&_result, "%d", fd[2][0]);
        }
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HERE */
    return NULL;

    /* error */
child_error:
    dummy = write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
    _exit(EXIT_FAILURE);
}
Ejemplo n.º 27
0
const char *
vp_pipe_open(char *args)
{
#define VP_GOTO_ERROR(_fmt) do { errfmt = (_fmt); goto error; } while(0)
    vp_stack_t stack;
    int npipe, hstdin, hstderr, hstdout;
    int argc;
    int fd[3][2] = {{0}};
    pid_t pid;
    int dummy;
    char *errfmt;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error. wrong pipes.");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdin));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdout));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstderr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));

    if (hstdin > 0) {
        fd[0][0] = hstdin;
        fd[0][1] = 0;
    } else {
        if (pipe(fd[0]) < 0) {
            VP_GOTO_ERROR("pipe() error: %s");
        }
    }
    if (hstdout > 0) {
        fd[1][1] = hstdout;
        fd[1][0] = 0;
    } else {
        if (pipe(fd[1]) < 0) {
            VP_GOTO_ERROR("pipe() error: %s");
        }
    }
    if (hstderr > 0) {
        fd[2][1] = hstderr;
        fd[2][0] = 0;
    } else if (npipe == 3 && hstderr == 0) {
        if (pipe(fd[2]) < 0) {
            VP_GOTO_ERROR("pipe() error: %s");
        }
    }

    pid = fork();
    if (pid < 0) {
        VP_GOTO_ERROR("fork() error: %s");
    } else if (pid == 0) {
        /* child */
        char **argv;
        int i;

        /* Set process group. */
        setpgid(0, 0);

        if (fd[0][1] > 0) {
            close(fd[0][1]);
        }
        if (fd[1][0] > 0) {
            close(fd[1][0]);
        }
        if (fd[2][0] > 0) {
            close(fd[2][0]);
        }
        if (fd[0][0] > 0) {
            if (dup2(fd[0][0], STDIN_FILENO) != STDIN_FILENO) {
                goto child_error;
            }
            close(fd[0][0]);
        }
        if (fd[1][1] > 0) {
            if (dup2(fd[1][1], STDOUT_FILENO) != STDOUT_FILENO) {
                goto child_error;
            }
            close(fd[1][1]);
        }
        if (fd[2][1] > 0) {
            if (dup2(fd[2][1], STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
            close(fd[2][1]);
        } else if (npipe == 2) {
            if (dup2(STDOUT_FILENO, STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
        }

        {
#ifndef TIOCNOTTY
            setsid();
#else
            /* Ignore tty. */
            char name[L_ctermid];
            if (ctermid(name)[0] != '\0') {
                int tfd;
                if ((tfd = open(name, O_RDONLY)) != -1) {
                    ioctl(tfd, TIOCNOTTY, NULL);
                    close(tfd);
                }
            }
#endif
        }

        argv = malloc(sizeof(char *) * (argc+1));
        if (argv == NULL) {
            goto child_error;
        }
        for (i = 0; i < argc; ++i) {
            if (vp_stack_pop_str(&stack, &(argv[i]))) {
                free(argv);
                goto child_error;
            }
        }
        argv[argc] = NULL;

        execv(argv[0], argv);
        /* error */
        goto child_error;
    } else {
        /* parent */
        if (fd[0][0] > 0) {
            close(fd[0][0]);
        }
        if (fd[1][1] > 0) {
            close(fd[1][1]);
        }
        if (fd[2][1] > 0) {
            close(fd[2][1]);
        }

        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fd[0][1]);
        vp_stack_push_num(&_result, "%d", fd[1][0]);
        if (npipe == 3) {
            vp_stack_push_num(&_result, "%d", fd[2][0]);
        }
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HERE */
    return NULL;

    /* error */
error:
    close_allfd(fd);
    return vp_stack_return_error(&_result, errfmt, strerror(errno));

child_error:
    dummy = write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
    _exit(EXIT_FAILURE);
#undef VP_GOTO_ERROR
}
Ejemplo n.º 28
0
const char *
vp_pipe_open(char *args)
{
    vp_stack_t stack;
    int npipe;
    int argc;
    char *argv[VP_ARGC_MAX];
    int fd[3][2];
    pid_t pid;
    int i;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error. wrong pipes.");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));
    if (argc < 1 || VP_ARGC_MAX <= argc)
        return vp_stack_return_error(&_result, "argc range error. too many arguments. please use xargs.");
    for (i = 0; i < argc; ++i)
        VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &(argv[i])));
    argv[argc] = NULL;

    if (pipe(fd[0]) < 0 || pipe(fd[1]) < 0 || (npipe == 3 && pipe(fd[2]) < 0))
        return vp_stack_return_error(&_result, "pipe() error: %s",
                strerror(errno));

    pid = fork();
    if (pid < 0) {
        return vp_stack_return_error(&_result, "fork() error: %s",
                strerror(errno));
    } else if (pid == 0) {
        /* child */
        close(fd[0][1]);
        close(fd[1][0]);
        if (npipe == 3)
            close(fd[2][0]);
        if (fd[0][0] != STDIN_FILENO) {
            if (dup2(fd[0][0], STDIN_FILENO) != STDIN_FILENO) {
                write(fd[1][1], strerror(errno), strlen(strerror(errno)));
                _exit(EXIT_FAILURE);
            }
            close(fd[0][0]);
        }
        if (fd[1][1] != STDOUT_FILENO) {
            if (dup2(fd[1][1], STDOUT_FILENO) != STDOUT_FILENO) {
                write(fd[1][1], strerror(errno), strlen(strerror(errno)));
                _exit(EXIT_FAILURE);
            }
            close(fd[1][1]);
        }
        if (npipe == 2) {
            if (dup2(STDOUT_FILENO, STDERR_FILENO) != STDERR_FILENO) {
                write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
                _exit(EXIT_FAILURE);
            }
        } else if (fd[2][1] != STDERR_FILENO) {
            if (dup2(fd[2][1], STDERR_FILENO) != STDERR_FILENO) {
                write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
                _exit(EXIT_FAILURE);
            }
            close(fd[2][1]);
        }
        if (execv(argv[0], argv) < 0) {
            /* error */
            write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
            _exit(EXIT_FAILURE);
        }
    } else {
        /* parent */
        close(fd[0][0]);
        close(fd[1][1]);
        if (npipe == 3)
            close(fd[2][1]);
        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fd[0][1]);
        vp_stack_push_num(&_result, "%d", fd[1][0]);
        if (npipe == 3)
            vp_stack_push_num(&_result, "%d", fd[2][0]);
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HEAR */
    return NULL;
}
Ejemplo n.º 29
0
const char *
vp_pty_open(char *args)
{
#define VP_GOTO_ERROR(_fmt) do { errfmt = (_fmt); goto error; } while(0)
    vp_stack_t stack;
    int argc;
    int fd[3][2] = {{0}};
    pid_t pid;
    struct winsize ws = {0, 0, 0, 0};
    int dummy;
    int hstdin, hstderr, hstdout;
    int fdm;
    int npipe;
    char *errfmt;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error. wrong pipes.");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_col)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%hu", &(ws.ws_row)));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdin));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdout));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstderr));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &argc));

    /* Set pipe */
    if (hstdin > 0) {
        fd[0][0] = hstdin;
        fd[0][1] = 0;
    }
    if (hstdout > 1) {
        fd[1][1] = hstdout;
        fd[1][0] = 0;
    } else if (hstdout == 1) {
        if (pipe(fd[1]) < 0) {
            VP_GOTO_ERROR("pipe() error: %s");
        }
    }
    if (hstderr > 1) {
        fd[2][1] = hstderr;
        fd[2][0] = 0;
    } else if (npipe == 3) {
        if (hstderr == 1){
            if (pipe(fd[2]) < 0) {
                VP_GOTO_ERROR("pipe() error: %s");
            }
        } else if (hstderr == 0) {
            if (openpty(&fd[2][0], &fd[2][1], NULL, NULL, &ws) < 0) {
                VP_GOTO_ERROR("openpty() error: %s");
            }
            VP_SET_NONBLOCK_IF_NEEDED(fd[2][0]);
        }
    }

    pid = forkpty(&fdm, NULL, NULL, &ws);
    if (pid < 0) {
        VP_GOTO_ERROR("fork() error: %s");
    } else if (pid == 0) {
        /* child */
        char **argv;
        int i;

        /* Close pipe */
        if (fd[1][0] > 0) {
            close(fd[1][0]);
        }
        if (fd[2][0] > 0) {
            close(fd[2][0]);
        }

        if (fd[0][0] > 0) {
            if (dup2(fd[0][0], STDIN_FILENO) != STDIN_FILENO) {
                goto child_error;
            }
            close(fd[0][0]);
        }

        if (fd[1][1] > 0) {
            if (dup2(fd[1][1], STDOUT_FILENO) != STDOUT_FILENO) {
                goto child_error;
            }
            close(fd[1][1]);
        }

        if (fd[2][1] > 0) {
            if (dup2(fd[2][1], STDERR_FILENO) != STDERR_FILENO) {
                goto child_error;
            }
            close(fd[2][1]);
        }

        argv = malloc(sizeof(char *) * (argc+1));
        if (argv == NULL) {
            goto child_error;
        }
        for (i = 0; i < argc; ++i) {
            if (vp_stack_pop_str(&stack, &(argv[i]))) {
                free(argv);
                goto child_error;
            }
        }
        argv[argc] = NULL;

        execv(argv[0], argv);
        /* error */
        goto child_error;
    } else {
        /* parent */
        if (fd[1][1] > 0) {
            close(fd[1][1]);
        }
        if (fd[2][1] > 0) {
            close(fd[2][1]);
        }

        if (hstdin == 0) {
            fd[0][1] = fdm;
        }
        if (hstdout == 0) {
            fd[1][0] = hstdin == 0 ? dup(fdm) : fdm;
            VP_SET_NONBLOCK_IF_NEEDED(fd[1][0]);
        }

        vp_stack_push_num(&_result, "%d", pid);
        vp_stack_push_num(&_result, "%d", fd[0][1]);
        vp_stack_push_num(&_result, "%d", fd[1][0]);
        if (npipe == 3) {
            vp_stack_push_num(&_result, "%d", fd[2][0]);
        }
        return vp_stack_return(&_result);
    }
    /* DO NOT REACH HERE */
    return NULL;

    /* error */
error:
    close_allfd(fd);
    return vp_stack_return_error(&_result, errfmt, strerror(errno));

child_error:
    dummy = write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno)));
    _exit(EXIT_FAILURE);
#undef VP_GOTO_ERROR
}
Ejemplo n.º 30
0
/*
 * http://support.microsoft.com/kb/190351/
 */
const char *
vp_pipe_open(char *args)
{
    vp_stack_t stack;
    int npipe, hstdin, hstderr, hstdout;
    char *cmdline;
    HANDLE hInputWrite = INVALID_HANDLE_VALUE, hInputRead;
    HANDLE hOutputWrite, hOutputRead = INVALID_HANDLE_VALUE;
    HANDLE hErrorWrite, hErrorRead = INVALID_HANDLE_VALUE;
    SECURITY_ATTRIBUTES sa;
    PROCESS_INFORMATION pi;
    STARTUPINFO si;

    VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &npipe));
    if (npipe != 2 && npipe != 3)
        return vp_stack_return_error(&_result, "npipe range error");
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdin));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstdout));
    VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &hstderr));
    VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &cmdline));

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    if (hstdin) {
        /* Get handle. */
        hInputRead = (HANDLE)_get_osfhandle(hstdin);
    } else {
        HANDLE hInputWriteTmp;

        /* Create pipe. */
        if (!CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0))
            return vp_stack_return_error(&_result, "CreatePipe() error: %s",
                    lasterror());

        if (!DuplicateHandle(GetCurrentProcess(),
                    hInputWriteTmp,
                    GetCurrentProcess(),
                    &hInputWrite,
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS))
            return vp_stack_return_error(&_result, "DuplicateHandle() error: %s",
                    lasterror());
        if (!CloseHandle(hInputWriteTmp))
            return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                    lasterror());
    }

    if (hstdout) {
        /* Get handle. */
        hOutputWrite = (HANDLE)_get_osfhandle(hstdout);
    } else {
        HANDLE hOutputReadTmp;

        /* Create pipe. */
        if (!CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0))
            return vp_stack_return_error(&_result, "CreatePipe() error: %s",
                    lasterror());

        if (!DuplicateHandle(GetCurrentProcess(),
                    hOutputReadTmp,
                    GetCurrentProcess(),
                    &hOutputRead,
                    0,
                    TRUE,
                    DUPLICATE_SAME_ACCESS))
            return vp_stack_return_error(&_result, "DuplicateHandle() error: %s",
                    lasterror());
        if (!CloseHandle(hOutputReadTmp))
            return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                    lasterror());
    }

    if (npipe == 2) {
        if (!DuplicateHandle(GetCurrentProcess(),
                             hOutputWrite,
                             GetCurrentProcess(),
                             &hErrorWrite,
                             0,
                             TRUE,
                             DUPLICATE_SAME_ACCESS))
            return vp_stack_return_error(&_result, "DuplicateHandle() error: %s",
                    lasterror());
    } else {
        if (hstderr) {
            /* Get handle. */
            hErrorWrite = (HANDLE)_get_osfhandle(hstderr);
        } else {
            HANDLE hErrorReadTmp;

            /* Create pipe. */
            if (!CreatePipe(&hErrorReadTmp, &hErrorWrite, &sa, 0))
                return vp_stack_return_error(&_result, "CreatePipe() error: %s",
                        lasterror());

            if (!DuplicateHandle(GetCurrentProcess(),
                        hErrorReadTmp,
                        GetCurrentProcess(),
                        &hErrorRead,
                        0,
                        TRUE,
                        DUPLICATE_SAME_ACCESS))
                return vp_stack_return_error(&_result, "DuplicateHandle() error: %s",
                        lasterror());
            if (!CloseHandle(hErrorReadTmp))
                return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                        lasterror());
        }
    }

    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    /*si.dwFlags = STARTF_USESTDHANDLES;*/
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = hInputRead;
    si.hStdOutput = hOutputWrite;
    si.hStdError = hErrorWrite;

    if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE,
                        CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
                        /*0, NULL, NULL, &si, &pi))*/
                        /*DETACHED_PROCESS, NULL, NULL, &si, &pi))*/
                        /*CREATE_NO_WINDOW, NULL, NULL, &si, &pi))*/
        return vp_stack_return_error(&_result, "CreateProcess() error: %s %s",
                lasterror());

    if (!CloseHandle(pi.hThread))
        return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                lasterror());

    if (!CloseHandle(hInputRead))
        return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                lasterror());
    if (!CloseHandle(hOutputWrite))
        return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                lasterror());
    if (!CloseHandle(hErrorWrite))
        return vp_stack_return_error(&_result, "CloseHandle() error: %s",
                lasterror());

    vp_stack_push_num(&_result, "%p", pi.hProcess);
    vp_stack_push_num(&_result, "%d", hstdin ?
            0 : _open_osfhandle((size_t)hInputWrite, 0));
    vp_stack_push_num(&_result, "%d", hstdout ?
            0 : _open_osfhandle((size_t)hOutputRead, _O_RDONLY));
    if (npipe == 3)
        vp_stack_push_num(&_result, "%d", hstderr ?
                0 : _open_osfhandle((size_t)hErrorRead, _O_RDONLY));
    return vp_stack_return(&_result);
}