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); }
const char * vp_readdir(char *args) { vp_stack_t stack; char *dirname; char buf[1024]; DIR *dir; struct dirent *dp; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &dirname)); if ((dir=opendir(dirname)) == NULL) { return vp_stack_return_error(&_result, "opendir() error: %s", strerror(errno)); } for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) { snprintf(buf, sizeof(buf), "%s/%s", dirname, dp->d_name); vp_stack_push_str(&_result, buf); } closedir(dir); return vp_stack_return(&_result); }
/* http://www.syuhitu.org/other/dir.html */ const char * vp_readdir(char *args) { vp_stack_t stack; char *dirname; char buf[1024]; WIN32_FIND_DATA fd; HANDLE h; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &dirname)); snprintf(buf, sizeof(buf), "%s\\*", dirname); /* Get handle. */ h = FindFirstFileEx(buf, FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, 0 ); if (h == INVALID_HANDLE_VALUE) { return vp_stack_return_error(&_result, "FindFirstFileEx() error: %s", GetLastError()); } do { snprintf(buf, sizeof(buf), "%s/%s", dirname, fd.cFileName); vp_stack_push_str(&_result, buf); } while (FindNextFile(h, &fd)); FindClose(h); return vp_stack_return(&_result); }
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); }
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; }
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); }
static const char * vp_stack_push_num(vp_stack_t *stack, const char *fmt, ...) { va_list ap; char buf[VP_NUM_BUFSIZE]; va_start(ap, fmt); if (vsprintf(buf, fmt, ap) < 0) { va_end(ap); return "vp_stack_push_num: vsprintf error"; } va_end(ap); return vp_stack_push_str(stack, buf); }
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); }
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); }
const char * vp_decode(char *args) { vp_stack_t stack; unsigned num = 0; unsigned i = 0; size_t length; char *str; char *buf; char *p; char *bp; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &str)); length = strlen(str); buf = (char *)malloc(length/2 + 2); if (buf == NULL) { return vp_stack_return_error(&_result, "malloc() error: %s", "Memory cannot allocate"); } p = str; bp = buf; for (i = 0; i < length; i++, p++) { if (isdigit(*p)) num |= (*p & 15); else num |= (*p & 15) + 9; if (i % 2) { *bp++ = num; num = 0; } else { num <<= 4; } } *bp = '\0'; vp_stack_push_str(&_result, buf); free(buf); return vp_stack_return(&_result); }
const char * vp_decode(char *args) { vp_stack_t stack; unsigned num; unsigned i, bi; size_t length, max_buf; char *str; char *buf; char *p; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_str(&stack, &str)); length = strlen(str); max_buf = length/2 + 2; buf = (char *)malloc(max_buf); if (buf == NULL) { return vp_stack_return_error(&_result, "malloc() error: %s", "Memory cannot allocate"); } p = str; bi = 0; num = 0; for (i = 0; i < length; i++, p++) { if (isdigit((int)*p)) num |= (*p & 15); else num |= (*p & 15) + 9; if (i % 2 == 0) { num <<= 4; continue; } /* Write character. */ if (num == 0) { /* Convert NULL character. */ max_buf += 1; buf = (char *)realloc(buf, max_buf); if (buf == NULL) { return vp_stack_return_error( &_result, "realloc() error: %s", "Memory cannot allocate"); } buf[bi] = '^'; bi++; buf[bi] = '@'; bi++; } else { buf[bi] = num; bi++; } num = 0; } buf[bi] = '\0'; vp_stack_push_str(&_result, buf); free(buf); return vp_stack_return(&_result); }
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); }