static mrb_value mrb_io_s_pipe(mrb_state *mrb, mrb_value klass) { mrb_value r = mrb_nil_value(); mrb_value w = mrb_nil_value(); struct mrb_io *fptr_r; struct mrb_io *fptr_w; int pipes[2]; if (mrb_pipe(mrb, pipes) == -1) { mrb_sys_fail(mrb, "pipe"); } r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); mrb_iv_set(mrb, r, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); fptr_r = mrb_io_alloc(mrb); fptr_r->fd = pipes[0]; fptr_r->readable = 1; fptr_r->writable = 0; fptr_r->sync = 0; DATA_TYPE(r) = &mrb_io_type; DATA_PTR(r) = fptr_r; w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); mrb_iv_set(mrb, w, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); fptr_w = mrb_io_alloc(mrb); fptr_w->fd = pipes[1]; fptr_w->readable = 0; fptr_w->writable = 1; fptr_w->sync = 1; DATA_TYPE(w) = &mrb_io_type; DATA_PTR(w) = fptr_w; return mrb_assoc_new(mrb, r, w); }
mrb_value mrb_io_initialize(mrb_state *mrb, mrb_value io) { struct mrb_io *fptr; mrb_int fd, flags; mrb_value mode, opt; DATA_TYPE(io) = &mrb_io_type; DATA_PTR(io) = NULL; mode = opt = mrb_nil_value(); mrb_get_args(mrb, "i|So", &fd, &mode, &opt); if (mrb_nil_p(mode)) { mode = mrb_str_new_cstr(mrb, "r"); } if (mrb_nil_p(opt)) { opt = mrb_hash_new(mrb); } flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode)); mrb_iv_set(mrb, io, mrb_intern(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); mrb_iv_set(mrb, io, mrb_intern(mrb, "@pos"), mrb_fixnum_value(0)); fptr = DATA_PTR(io); if (fptr == NULL) { fptr = mrb_io_alloc(mrb); } fptr->fd = fd; DATA_PTR(io) = fptr; return io; }
mrb_value mrb_io_bless(mrb_state *mrb, mrb_value io) { if (mrb_type(io) != MRB_TT_DATA) { mrb_raise(mrb, E_TYPE_ERROR, "expected IO object"); return mrb_nil_value(); } DATA_TYPE(io) = &mrb_io_type; DATA_PTR(io) = NULL; DATA_PTR(io) = mrb_io_alloc(mrb); return io; }
mrb_value mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy) { mrb_value orig; mrb_value buf; struct mrb_io *fptr_copy; struct mrb_io *fptr_orig; mrb_bool failed = TRUE; mrb_get_args(mrb, "o", &orig); fptr_orig = io_get_open_fptr(mrb, orig); fptr_copy = (struct mrb_io *)DATA_PTR(copy); if (fptr_orig == fptr_copy) return copy; if (fptr_copy != NULL) { fptr_finalize(mrb, fptr_copy, FALSE); mrb_free(mrb, fptr_copy); } fptr_copy = (struct mrb_io *)mrb_io_alloc(mrb); DATA_TYPE(copy) = &mrb_io_type; DATA_PTR(copy) = fptr_copy; buf = mrb_iv_get(mrb, orig, mrb_intern_cstr(mrb, "@buf")); mrb_iv_set(mrb, copy, mrb_intern_cstr(mrb, "@buf"), buf); fptr_copy->fd = mrb_dup(mrb, fptr_orig->fd, &failed); if (failed) { mrb_sys_fail(mrb, 0); } mrb_fd_cloexec(mrb, fptr_copy->fd); if (fptr_orig->fd2 != -1) { fptr_copy->fd2 = mrb_dup(mrb, fptr_orig->fd2, &failed); if (failed) { close(fptr_copy->fd); mrb_sys_fail(mrb, 0); } mrb_fd_cloexec(mrb, fptr_copy->fd2); } fptr_copy->pid = fptr_orig->pid; fptr_copy->readable = fptr_orig->readable; fptr_copy->writable = fptr_orig->writable; fptr_copy->sync = fptr_orig->sync; fptr_copy->is_socket = fptr_orig->is_socket; return copy; }
mrb_value mrb_io_initialize(mrb_state *mrb, mrb_value io) { struct mrb_io *fptr; mrb_int fd; mrb_value mode, opt; int flags; mode = opt = mrb_nil_value(); mrb_get_args(mrb, "i|So", &fd, &mode, &opt); if (mrb_nil_p(mode)) { mode = mrb_str_new_cstr(mrb, "r"); } if (mrb_nil_p(opt)) { opt = mrb_hash_new(mrb); } flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode)); mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0)); fptr = DATA_PTR(io); if (fptr != NULL) { fptr_finalize(mrb, fptr, 0); mrb_free(mrb, fptr); } fptr = mrb_io_alloc(mrb); DATA_TYPE(io) = &mrb_io_type; DATA_PTR(io) = fptr; fptr->fd = fd; fptr->writable = ((flags & FMODE_WRITABLE) != 0); fptr->sync = 0; return io; }
mrb_value mrb_io_s_popen(mrb_state *mrb, mrb_value klass) { mrb_value cmd, io, result; mrb_value mode = mrb_str_new_cstr(mrb, "r"); mrb_value opt = mrb_hash_new(mrb); struct mrb_io *fptr; const char *pname; int pid, flags, fd, write_fd = -1; int pr[2] = { -1, -1 }; int pw[2] = { -1, -1 }; int doexec; int saved_errno; mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt); io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); pname = mrb_string_value_cstr(mrb, &cmd); flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode)); doexec = (strcmp("-", pname) != 0); if ((flags & FMODE_READABLE) && pipe(pr) == -1) { mrb_sys_fail(mrb, "pipe"); } if ((flags & FMODE_WRITABLE) && pipe(pw) == -1) { if (pr[0] != -1) close(pr[0]); if (pr[1] != -1) close(pr[1]); mrb_sys_fail(mrb, "pipe"); } if (!doexec) { // XXX fflush(stdin); fflush(stdout); fflush(stderr); } result = mrb_nil_value(); switch (pid = fork()) { case 0: /* child */ if (flags & FMODE_READABLE) { close(pr[0]); if (pr[1] != 1) { dup2(pr[1], 1); close(pr[1]); } } if (flags & FMODE_WRITABLE) { close(pw[1]); if (pw[0] != 0) { dup2(pw[0], 0); close(pw[0]); } } if (doexec) { for (fd = 3; fd < NOFILE; fd++) { close(fd); } mrb_proc_exec(pname); mrb_raisef(mrb, E_IO_ERROR, "command not found: %S", cmd); _exit(127); } result = mrb_nil_value(); break; default: /* parent */ if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) { close(pr[1]); fd = pr[0]; close(pw[0]); write_fd = pw[1]; } else if (flags & FMODE_READABLE) { close(pr[1]); fd = pr[0]; } else { close(pw[0]); fd = pw[1]; } mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0)); fptr = mrb_io_alloc(mrb); fptr->fd = fd; fptr->fd2 = write_fd; fptr->pid = pid; fptr->writable = ((flags & FMODE_WRITABLE) != 0); fptr->sync = 0; DATA_TYPE(io) = &mrb_io_type; DATA_PTR(io) = fptr; result = io; break; case -1: /* error */ saved_errno = errno; if (flags & FMODE_READABLE) { close(pr[0]); close(pr[1]); } if (flags & FMODE_WRITABLE) { close(pw[0]); close(pw[1]); } errno = saved_errno; mrb_sys_fail(mrb, "pipe_open failed."); break; } return result; }
mrb_value mrb_io_s_popen(mrb_state *mrb, mrb_value klass) { mrb_value cmd, io; mrb_value mode = mrb_str_new_cstr(mrb, "r"); mrb_value opt = mrb_hash_new(mrb); struct mrb_io *fptr; const char *pname; int pid = 0, flags; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES saAttr; HANDLE ifd[2]; HANDLE ofd[2]; int doexec; int opt_in, opt_out, opt_err; ifd[0] = INVALID_HANDLE_VALUE; ifd[1] = INVALID_HANDLE_VALUE; ofd[0] = INVALID_HANDLE_VALUE; ofd[1] = INVALID_HANDLE_VALUE; mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt); io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); pname = mrb_string_value_cstr(mrb, &cmd); flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode)); doexec = (strcmp("-", pname) != 0); opt_in = option_to_fd(mrb, opt, "in"); opt_out = option_to_fd(mrb, opt, "out"); opt_err = option_to_fd(mrb, opt, "err"); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (flags & FMODE_READABLE) { if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0) || !SetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)) { mrb_sys_fail(mrb, "pipe"); } } if (flags & FMODE_WRITABLE) { if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0) || !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)) { mrb_sys_fail(mrb, "pipe"); } } if (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 (flags & FMODE_READABLE) { si.hStdOutput = ofd[1]; si.hStdError = ofd[1]; } if (flags & FMODE_WRITABLE) { si.hStdInput = ifd[0]; } if (!CreateProcess( NULL, (char*)pname, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) { CloseHandle(ifd[0]); CloseHandle(ifd[1]); CloseHandle(ofd[0]); CloseHandle(ofd[1]); mrb_raisef(mrb, E_IO_ERROR, "command not found: %S", cmd); } CloseHandle(pi.hThread); CloseHandle(ifd[0]); CloseHandle(ofd[1]); pid = pi.dwProcessId; } mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, "")); fptr = mrb_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 = ((flags & FMODE_READABLE) != 0); fptr->writable = ((flags & FMODE_WRITABLE) != 0); fptr->sync = 0; DATA_TYPE(io) = &mrb_io_type; DATA_PTR(io) = fptr; return io; }