diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 0a2fb8057..ff247346a 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -261,48 +261,6 @@ io_fd_cloexec(mrb_state *mrb, int fd) #endif } -#if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) -static int -io_cloexec_pipe(mrb_state *mrb, int fildes[2]) -{ - int ret = pipe(fildes); - if (ret == -1) - return -1; - io_fd_cloexec(mrb, fildes[0]); - io_fd_cloexec(mrb, fildes[1]); - return ret; -} - -static int -io_pipe(mrb_state *mrb, int pipes[2]) -{ - int ret = io_cloexec_pipe(mrb, pipes); - if (ret == -1) { - if (errno == EMFILE || errno == ENFILE) { - mrb_garbage_collect(mrb); - ret = io_cloexec_pipe(mrb, pipes); - } - } - return ret; -} - -static int -io_process_exec(const char *pname) -{ - const char *s = pname; - - while (*s == ' ' || *s == '\t' || *s == '\n') - s++; - - if (!*s) { - errno = ENOENT; - return -1; - } - - execl("/bin/sh", "sh", "-c", pname, (char*)NULL); - return -1; -} -#endif static void io_free(mrb_state *mrb, void *ptr) @@ -397,153 +355,92 @@ parse_popen_args(mrb_state *mrb, struct popen_params *p) p->opt_err = option_to_fd(mrb, kv.opt_err); } -#if defined(_WIN32) static mrb_value io_s_popen(mrb_state *mrb, mrb_value klass) { struct popen_params p; p.klass = klass; - - parse_popen_args(mrb, &p); - - struct mrb_io *fptr; int pid = 0; - STARTUPINFO si; - PROCESS_INFORMATION pi; - - HANDLE ifd[2]; - HANDLE ofd[2]; - - ifd[0] = INVALID_HANDLE_VALUE; - ifd[1] = INVALID_HANDLE_VALUE; - ofd[0] = INVALID_HANDLE_VALUE; - ofd[1] = INVALID_HANDLE_VALUE; + int pr[2] = { -1, -1 }; /* read pipe: parent reads, child writes */ + int pw[2] = { -1, -1 }; /* write pipe: parent writes, child reads */ + int readable, writable; + int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; mrb->c->ci->mid = 0; + parse_popen_args(mrb, &p); - SECURITY_ATTRIBUTES saAttr; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; + readable = OPEN_READABLE_P(p.flags); + writable = OPEN_WRITABLE_P(p.flags); - if (OPEN_READABLE_P(p.flags)) { - if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0) - || !SetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)) { + /* Create pipes for communication */ + if (readable) { + if (mrb_io_hal_pipe(mrb, pr) == -1) { mrb_sys_fail(mrb, "pipe"); } } - if (OPEN_WRITABLE_P(p.flags)) { - if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0) - || !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)) { + if (writable) { + if (mrb_io_hal_pipe(mrb, pw) == -1) { + if (pr[0] != -1) { + mrb_io_hal_close(mrb, pr[0]); + mrb_io_hal_close(mrb, pr[1]); + } mrb_sys_fail(mrb, "pipe"); } } + /* Set up child process file descriptors */ if (p.doexec) { - ZeroMemory(&pi, sizeof(pi)); - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags |= STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - si.dwFlags |= STARTF_USESTDHANDLES; - if (OPEN_READABLE_P(p.flags)) { - si.hStdOutput = ofd[1]; - si.hStdError = ofd[1]; - } - if (OPEN_WRITABLE_P(p.flags)) { - si.hStdInput = ifd[0]; - } - if (!CreateProcess( - NULL, (char*)p.cmd, NULL, NULL, - TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) { - CloseHandle(ifd[0]); - CloseHandle(ifd[1]); - CloseHandle(ofd[0]); - CloseHandle(ofd[1]); + /* Child stdin: either write pipe read end or opt_in */ + stdin_fd = (p.opt_in != -1) ? p.opt_in : (writable ? pw[0] : -1); + + /* Child stdout: either read pipe write end or opt_out */ + stdout_fd = (p.opt_out != -1) ? p.opt_out : (readable ? pr[1] : -1); + + /* Child stderr: opt_err or stdout */ + stderr_fd = (p.opt_err != -1) ? p.opt_err : stdout_fd; + + /* Spawn child process using HAL */ + if (mrb_io_hal_spawn_process(mrb, p.cmd, stdin_fd, stdout_fd, stderr_fd, &pid) == -1) { + int saved_errno = errno; + if (readable) { + mrb_io_hal_close(mrb, pr[0]); + mrb_io_hal_close(mrb, pr[1]); + } + if (writable) { + mrb_io_hal_close(mrb, pw[0]); + mrb_io_hal_close(mrb, pw[1]); + } + errno = saved_errno; mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", p.cmd); } - CloseHandle(pi.hThread); - CloseHandle(ifd[0]); - CloseHandle(ofd[1]); - pid = pi.dwProcessId; + + /* Close child ends of pipes in parent */ + if (readable) { + mrb_io_hal_close(mrb, pr[1]); /* close write end */ + } + if (writable) { + mrb_io_hal_close(mrb, pw[0]); /* close read end */ + } } + /* Set up parent IO object */ mrb_value io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); - fptr = io_alloc(mrb); - fptr->fd = _open_osfhandle((intptr_t)ofd[0], 0); - fptr->fd2 = _open_osfhandle((intptr_t)ifd[1], 0); - fptr->pid = pid; - fptr->readable = OPEN_READABLE_P(p.flags); - fptr->writable = OPEN_WRITABLE_P(p.flags); - io_init_buf(mrb, fptr); - - DATA_TYPE(io) = &mrb_io_type; - DATA_PTR(io) = fptr; - return io; -} -#else - -static void -popen_child_setup(mrb_state *mrb, int readable, int writable, int *pr, int *pw, struct popen_params *p) -{ - if (p->opt_in != -1) { - dup2(p->opt_in, 0); - } - if (p->opt_out != -1) { - dup2(p->opt_out, 1); - } - if (p->opt_err != -1) { - dup2(p->opt_err, 2); - } - if (readable) { - close(pr[0]); - if (pr[1] != 1) { - dup2(pr[1], 1); - close(pr[1]); - } - } - if (writable) { - close(pw[1]); - if (pw[0] != 0) { - dup2(pw[0], 0); - close(pw[0]); - } - } - if (p->doexec) { - for (int fd = 3; fd < NOFILE; fd++) { - close(fd); - } - io_process_exec(p->cmd); - mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", p->cmd); - _exit(127); - } -} - -static mrb_value -popen_parent_setup(mrb_state *mrb, int readable, int writable, int *pr, int *pw, int pid, struct popen_params *p) -{ - int fd, write_fd = -1; + struct mrb_io *fptr = io_alloc(mrb); if (readable && writable) { - close(pr[1]); - fd = pr[0]; - close(pw[0]); - write_fd = pw[1]; + fptr->fd = pr[0]; /* parent reads from here */ + fptr->fd2 = pw[1]; /* parent writes to here */ } else if (readable) { - close(pr[1]); - fd = pr[0]; + fptr->fd = pr[0]; /* parent reads from here */ + fptr->fd2 = -1; } else { - close(pw[0]); - fd = pw[1]; + fptr->fd = pw[1]; /* parent writes to here */ + fptr->fd2 = -1; } - mrb_value io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(p->klass), NULL, &mrb_io_type)); - struct mrb_io *fptr = io_alloc(mrb); - fptr->fd = fd; - fptr->fd2 = write_fd; fptr->pid = pid; fptr->readable = readable; fptr->writable = writable; @@ -553,73 +450,7 @@ popen_parent_setup(mrb_state *mrb, int readable, int writable, int *pr, int *pw, DATA_PTR(io) = fptr; return io; } - -static mrb_value -io_s_popen(mrb_state *mrb, mrb_value klass) -{ - struct popen_params p; - p.klass = klass; - int pid; - int pr[2] = { -1, -1 }; - int pw[2] = { -1, -1 }; - - mrb->c->ci->mid = 0; - parse_popen_args(mrb, &p); - - int readable = OPEN_READABLE_P(p.flags); - int writable = OPEN_WRITABLE_P(p.flags); - - if (readable) { - if (pipe(pr) == -1) { - mrb_sys_fail(mrb, "pipe"); - } - io_fd_cloexec(mrb, pr[0]); - io_fd_cloexec(mrb, pr[1]); - } - - if (writable) { - if (pipe(pw) == -1) { - if (pr[0] != -1) close(pr[0]); - if (pr[1] != -1) close(pr[1]); - mrb_sys_fail(mrb, "pipe"); - } - io_fd_cloexec(mrb, pw[0]); - io_fd_cloexec(mrb, pw[1]); - } - - if (!p.doexec) { - fflush(stdout); - fflush(stderr); - } - - switch (pid = fork()) { - case 0: /* child */ - popen_child_setup(mrb, readable, writable, pr, pw, &p); - return mrb_nil_value(); - - default: /* parent */ - return popen_parent_setup(mrb, readable, writable, pr, pw, pid, &p); - - case -1: /* error */ - { - int saved_errno = errno; - if (readable) { - close(pr[0]); - close(pr[1]); - } - if (writable) { - close(pw[0]); - close(pw[1]); - } - errno = saved_errno; - mrb_sys_fail(mrb, "pipe_open failed"); - } - break; - } - return mrb_nil_value(); /* not reached */ -} -#endif /* _WIN32 */ -#endif /* TARGET_OS_IPHONE */ +#endif /* MRB_NO_IO_POPEN */ static int symdup(mrb_state *mrb, int fd, mrb_bool *failed) @@ -1410,7 +1241,7 @@ io_s_pipe(mrb_state *mrb, mrb_value klass) { int pipes[2]; - if (io_pipe(mrb, pipes) == -1) { + if (mrb_io_hal_pipe(mrb, pipes) == -1) { mrb_sys_fail(mrb, "pipe"); }