mrb_value mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass) { mrb_int fd; mrb_get_args(mrb, "i", &fd); if (close(fd) == -1) { mrb_sys_fail(mrb, "close"); } return mrb_fixnum_value(0); }
mrb_value mrb_io_close_write(mrb_state *mrb, mrb_value self) { struct mrb_io *fptr; fptr = io_get_open_fptr(mrb, self); if (close((int)fptr->fd2) == -1) { mrb_sys_fail(mrb, "close"); } return mrb_nil_value(); }
int main(int argc, char *argv[]) { mrb_state *mrb = mrb_open(); mrb_value ARGV = mrb_ary_new_capa(mrb, argc); int i; int return_value; #ifdef HACONIWA_SECURE_RUN if(check_match_owner(argc, argv) < 0) { mrb_raise(mrb, E_RUNTIME_ERROR, "haconiwa runner and hacofile's owner would not be matched: This run prohibited on secure-run build"); exit(2); } #endif if(setuid(geteuid()) < 0) { mrb_sys_fail(mrb, "setuid"); exit(2); } if(setgid(getegid()) < 0) { mrb_sys_fail(mrb, "setgid"); exit(2); } for (i = 0; i < argc; i++) { mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i])); } mrb_define_global_const(mrb, "ARGV", ARGV); // call __main__(ARGV) mrb_funcall(mrb, mrb_top_self(mrb), "__main__", 1, ARGV); return_value = EXIT_SUCCESS; if (mrb->exc) { mrb_print_error(mrb); return_value = EXIT_FAILURE; } mrb_close(mrb); return return_value; }
mrb_value mrb_file__getwd(mrb_state *mrb, mrb_value klass) { mrb_value path; path = mrb_str_buf_new(mrb, MAXPATHLEN); if (GETCWD(RSTRING_PTR(path), MAXPATHLEN) == NULL) { mrb_sys_fail(mrb, "getcwd(2)"); } mrb_str_resize(mrb, path, strlen(RSTRING_PTR(path))); return path; }
static mrb_value mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self) { struct sockaddr_storage ss; socklen_t salen; salen = sizeof(ss); if (getsockname(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0) mrb_sys_fail(mrb, "getsockname"); return mrb_str_new(mrb, (void *)&ss, salen); }
static mrb_value mrb_f_waitpid(mrb_state *mrb, mrb_value klass) { mrb_int pid, flags = 0; int status; mrb_get_args(mrb, "i|i", &pid, &flags); if ((pid = mrb_waitpid(pid, flags, &status)) < 0) mrb_sys_fail(mrb, "waitpid failed"); return mrb_fixnum_value(pid); }
mrb_value mrb_filetest_s_size(mrb_state *mrb, mrb_value klass) { struct stat st; mrb_value obj; mrb_get_args(mrb, "o", &obj); if (mrb_stat(mrb, obj, &st) < 0) mrb_sys_fail(mrb, "mrb_stat"); return mrb_fixnum_value(st.st_size); }
static mrb_value mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self) { int fd, flags; mrb_value bool; #ifdef _WIN32 u_long mode = 1; #endif mrb_get_args(mrb, "o", &bool); fd = socket_fd(mrb, self); #ifdef _WIN32 flags = ioctlsocket(fd, FIONBIO, &mode); if (flags != NO_ERROR) mrb_sys_fail(mrb, "ioctlsocket"); #else flags = fcntl(fd, F_GETFL, 0); if (flags == 1) mrb_sys_fail(mrb, "fcntl"); if (mrb_test(bool)) flags |= O_NONBLOCK; else
mrb_value mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value io) { #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) struct mrb_io *fptr; int flag, ret; mrb_bool b; fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type); if (fptr->fd < 0) { mrb_raise(mrb, E_IO_ERROR, "closed stream"); } mrb_get_args(mrb, "b", &b); flag = b ? FD_CLOEXEC : 0; if (fptr->fd2 >= 0) { if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed"); if ((ret & FD_CLOEXEC) != flag) { ret = (ret & ~FD_CLOEXEC) | flag; ret = fcntl(fptr->fd2, F_SETFD, ret); if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed"); } } if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed"); if ((ret & FD_CLOEXEC) != flag) { ret = (ret & ~FD_CLOEXEC) | flag; ret = fcntl(fptr->fd, F_SETFD, ret); if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed"); } return mrb_bool_value(b); #else mrb_raise(mrb, E_NOTIMP_ERROR, "IO#close_on_exec= is not supported on the platform"); return mrb_nil_value(); #endif }
mrb_value mrb_io_sysread(mrb_state *mrb, mrb_value io) { struct mrb_io *fptr; mrb_value buf = mrb_nil_value(); mrb_int maxlen; int ret; mrb_get_args(mrb, "i|S", &maxlen, &buf); if (maxlen < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size"); } else if (maxlen == 0) { return mrb_str_new(mrb, NULL, maxlen); } if (mrb_nil_p(buf)) { buf = mrb_str_new(mrb, NULL, maxlen); } if (RSTRING_LEN(buf) != maxlen) { buf = mrb_str_resize(mrb, buf, maxlen); } else { mrb_str_modify(mrb, RSTRING(buf)); } fptr = (struct mrb_io *)io_get_open_fptr(mrb, io); if (!fptr->readable) { mrb_raise(mrb, E_IO_ERROR, "not opened for reading"); } ret = read(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen); switch (ret) { case 0: /* EOF */ if (maxlen == 0) { buf = mrb_str_new_cstr(mrb, ""); } else { mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File"); } break; case -1: /* Error */ mrb_sys_fail(mrb, "sysread failed"); break; default: if (RSTRING_LEN(buf) != ret) { buf = mrb_str_resize(mrb, buf, ret); } break; } return buf; }
mrb_value mrb_file__getwd(mrb_state *mrb, mrb_value klass) { mrb_value path; char buf[MAXPATHLEN], *utf8; if (GETCWD(buf, MAXPATHLEN) == NULL) { mrb_sys_fail(mrb, "getcwd(2)"); } utf8 = mrb_utf8_from_locale(buf, -1); path = mrb_str_new_cstr(mrb, utf8); mrb_utf8_free(utf8); return path; }
mrb_value mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self) { #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) struct mrb_io *fptr; int ret; fptr = io_get_open_fptr(mrb, self); if (fptr->fd2 >= 0) { if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed"); if (!(ret & FD_CLOEXEC)) return mrb_false_value(); } if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed"); if (!(ret & FD_CLOEXEC)) return mrb_false_value(); return mrb_true_value(); #else mrb_raise(mrb, E_NOTIMP_ERROR, "IO#close_on_exec? is not supported on the platform"); return mrb_false_value(); #endif }
static mrb_value mrb_basicsocket_recv(mrb_state *mrb, mrb_value self) { int n; mrb_int maxlen, flags = 0; mrb_value buf; mrb_get_args(mrb, "i|i", &maxlen, &flags); buf = mrb_str_buf_new(mrb, maxlen); n = recv(socket_fd(mrb, self), RSTRING_PTR(buf), maxlen, flags); if (n == -1) mrb_sys_fail(mrb, "recv"); mrb_str_resize(mrb, buf, n); return buf; }
static mrb_value mrb_wslay_event_context_client_init(mrb_state *mrb, mrb_value self) { mrb_value callbacks_obj; mrb_get_args(mrb, "o", &callbacks_obj); mrb_value recv_callback, send_callback, on_msg_recv_callback; recv_callback = mrb_iv_get(mrb, callbacks_obj, mrb_intern_lit(mrb, "@recv_callback")); if (mrb_type(recv_callback) != MRB_TT_PROC) { mrb_raise(mrb, E_ARGUMENT_ERROR, "recv_callback missing"); } send_callback = mrb_iv_get(mrb, callbacks_obj, mrb_intern_lit(mrb, "@send_callback")); if (mrb_type(send_callback) != MRB_TT_PROC) { mrb_raise(mrb, E_ARGUMENT_ERROR, "send_callback missing"); } on_msg_recv_callback = mrb_iv_get(mrb, callbacks_obj, mrb_intern_lit(mrb, "@on_msg_recv_callback")); if (mrb_type(on_msg_recv_callback) != MRB_TT_PROC) { mrb_raise(mrb, E_ARGUMENT_ERROR, "on_msg_recv_callback missing"); } mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "callbacks"), callbacks_obj); mrb_wslay_user_data *data = (mrb_wslay_user_data *) mrb_malloc(mrb, sizeof(mrb_wslay_user_data)); mrb_data_init(self, data, &mrb_wslay_user_data_type); data->mrb = mrb; data->recv_callback = recv_callback; data->send_callback = send_callback; data->on_msg_recv_callback = on_msg_recv_callback; struct wslay_event_callbacks client_callbacks = { mrb_wslay_event_recv_callback, mrb_wslay_event_send_callback, mrb_wslay_event_genmask_callback, NULL, NULL, NULL, mrb_wslay_event_on_msg_recv_callback }; int err = wslay_event_context_client_init(&data->ctx, &client_callbacks, data); if (err == WSLAY_ERR_NOMEM) { mrb_sys_fail(mrb, "wslay_event_context_client_init"); } else if (err != 0) { return MRB_WSLAY_ERROR(mrb_fixnum_value(err)); } return self; }
static mrb_value mrb_file_s_rename(mrb_state *mrb, mrb_value obj) { mrb_value from, to; const char *src, *dst; mrb_get_args(mrb, "SS", &from, &to); src = mrb_string_value_cstr(mrb, &from); dst = mrb_string_value_cstr(mrb, &to); if (rename(src, dst) < 0) { if (CHMOD(dst, 0666) == 0 && UNLINK(dst) == 0 && rename(src, dst) == 0) { return mrb_fixnum_value(0); } mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to))); } return mrb_fixnum_value(0); }
static mrb_value mrb_file_s_unlink(mrb_state *mrb, mrb_value obj) { mrb_value *argv; mrb_value pathv; mrb_int argc, i; const char *path; mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { pathv = mrb_convert_type(mrb, argv[i], MRB_TT_STRING, "String", "to_str"); path = mrb_string_value_cstr(mrb, &pathv); if (UNLINK(path) < 0) { mrb_sys_fail(mrb, path); } } return mrb_fixnum_value(argc); }
static mrb_value mrb_basicsocket_send(mrb_state *mrb, mrb_value self) { int n; mrb_int flags; mrb_value dest, mesg; dest = mrb_nil_value(); mrb_get_args(mrb, "Si|S", &mesg, &flags, &dest); if (mrb_nil_p(dest)) { n = send(socket_fd(mrb, self), RSTRING_PTR(mesg), RSTRING_LEN(mesg), flags); } else { n = sendto(socket_fd(mrb, self), RSTRING_PTR(mesg), RSTRING_LEN(mesg), flags, (const void *)RSTRING_PTR(dest), RSTRING_LEN(dest)); } if (n == -1) mrb_sys_fail(mrb, "send"); return mrb_fixnum_value(n); }
static mrb_value trap(mrb_state *mrb, mrb_value mod, int sig, sighandler_t func, mrb_value command) { sighandler_t oldfunc; mrb_value oldcmd; mrb_value trap_list; mrb_sym id_trap_list; if (sig == 0) { /* EXIT */ oldfunc = SIG_ERR; } else { oldfunc = mrb_signal(mrb, sig, func); if (oldfunc == SIG_ERR) mrb_sys_fail(mrb, signo2signm(sig)); } id_trap_list = mrb_intern_lit(mrb, "trap_list"); trap_list = mrb_iv_get(mrb, mod, id_trap_list); oldcmd = mrb_ary_ref(mrb, trap_list, (mrb_int)sig); if (mrb_nil_p(oldcmd)) { if (oldfunc == sighandler) oldcmd = mrb_str_new_cstr(mrb, "DEFAULT"); else oldcmd = mrb_nil_value(); } else if (mrb_type(oldcmd) == MRB_TT_TRUE) { if (oldfunc == SIG_IGN) oldcmd = mrb_str_new_cstr(mrb, "IGNORE"); else if (oldfunc == SIG_DFL) oldcmd = mrb_str_new_cstr(mrb, "SYSTEM_DEFAULT"); else if (oldfunc == sighandler) oldcmd = mrb_str_new_cstr(mrb, "DEFAULT"); else oldcmd = mrb_nil_value(); } else if (mrb_undef_p(oldcmd)) { oldcmd = mrb_str_new_cstr(mrb, "EXIT"); } mrb_ary_set(mrb, trap_list, (mrb_int)sig, command); return oldcmd; }
static mrb_value mrb_wslay_event_send(mrb_state *mrb, mrb_value self) { mrb_wslay_user_data *data = (mrb_wslay_user_data *) DATA_PTR(self); mrb_assert(data); int err = wslay_event_send(data->ctx); if (err == WSLAY_ERR_NOMEM) { mrb_sys_fail(mrb, "wslay_event_send"); } else if (err == WSLAY_ERR_CALLBACK_FAILURE) { mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); } else if (err != 0) { return MRB_WSLAY_ERROR(mrb_fixnum_value(err)); } return self; }
static mrb_value mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self) { char opt[8]; int s; mrb_int family, level, optname; mrb_value c, data; socklen_t optlen; mrb_get_args(mrb, "ii", &level, &optname); s = socket_fd(mrb, self); optlen = sizeof(opt); if (getsockopt(s, level, optname, opt, &optlen) == -1) mrb_sys_fail(mrb, "getsockopt"); c = mrb_const_get(mrb, mrb_obj_value(mrb_class_get(mrb, "Socket")), mrb_intern_lit(mrb, "Option")); family = socket_family(s); data = mrb_str_new(mrb, opt, optlen); return mrb_funcall(mrb, c, "new", 4, mrb_fixnum_value(family), mrb_fixnum_value(level), mrb_fixnum_value(optname), data); }
static mrb_value mrb_wslay_event_queue_msg(mrb_state *mrb, mrb_value self) { mrb_wslay_user_data *data = (mrb_wslay_user_data *) DATA_PTR(self); mrb_assert(data); mrb_value msg; mrb_sym opcode; mrb_int opc; if (mrb_get_args(mrb, "S|n", &msg, &opcode) == 1) { if (mrb_str_is_utf8(msg)) { opc = WSLAY_TEXT_FRAME; } else { opc = WSLAY_BINARY_FRAME; } } else { opc = mrb_fixnum(MRB_GET_OPCODE(mrb_symbol_value(opcode))); } struct wslay_event_msg msgarg = { opc, (const uint8_t *) RSTRING_PTR(msg), RSTRING_LEN(msg) }; int err = wslay_event_queue_msg(data->ctx, &msgarg); if (err == WSLAY_ERR_NOMEM) { mrb_sys_fail(mrb, "wslay_event_queue_msg"); } else if (err == WSLAY_ERR_NO_MORE_MSG) { mrb_raise(mrb, E_WSLAY_ERROR, "further message queueing is not allowed"); } else if (err == WSLAY_ERR_INVALID_ARGUMENT) { mrb_raise(mrb, E_WSLAY_ERROR, "the given message is invalid"); } else if (err != 0) { return MRB_WSLAY_ERROR(mrb_fixnum_value(err)); } return self; }
static mrb_value mrb_file_realpath(mrb_state *mrb, mrb_value klass) { mrb_value pathname, dir_string, s, result; int argc; char *cpath; argc = mrb_get_args(mrb, "S|S", &pathname, &dir_string); if (argc == 2) { s = mrb_str_dup(mrb, dir_string); s = mrb_str_append(mrb, s, mrb_str_new_cstr(mrb, FILE_SEPARATOR)); s = mrb_str_append(mrb, s, pathname); pathname = s; } cpath = mrb_str_to_cstr(mrb, pathname); result = mrb_str_buf_new(mrb, PATH_MAX); if (realpath(cpath, RSTRING_PTR(result)) == NULL) mrb_sys_fail(mrb, cpath); mrb_str_resize(mrb, result, strlen(RSTRING_PTR(result))); return result; }
static mrb_value mrb_uri_parser_get_port(mrb_state *mrb, mrb_value self) { char *name, *proto = (char*)"tcp"; mrb_get_args(mrb, "z|z", &name, &proto); errno = 0; struct servent *answer = getservbyname(name, proto); if (answer != NULL) { return mrb_fixnum_value(ntohs(answer->s_port)); } else { if (errno == 0) { return mrb_nil_value(); } else { mrb_sys_fail(mrb, "getservbyname"); } } return self; }
static mrb_value mrb_file_s_chmod(mrb_state *mrb, mrb_value klass) { mrb_int mode; mrb_int argc, i; mrb_value *filenames; int ai = mrb_gc_arena_save(mrb); mrb_get_args(mrb, "i*", &mode, &filenames, &argc); for (i = 0; i < argc; i++) { const char *utf8_path = mrb_str_to_cstr(mrb, filenames[i]); char *path = mrb_locale_from_utf8(utf8_path, -1); if (CHMOD(path, mode) == -1) { mrb_locale_free(path); mrb_sys_fail(mrb, utf8_path); } mrb_locale_free(path); } mrb_gc_arena_restore(mrb, ai); return mrb_fixnum_value(argc); }
static mrb_value mrb_file_basename(mrb_state *mrb, mrb_value klass) { // NOTE: Do not use mrb_locale_from_utf8 here #if defined(_WIN32) || defined(_WIN64) char bname[_MAX_DIR]; char extname[_MAX_EXT]; char *path; size_t ridx; char buffer[_MAX_DIR + _MAX_EXT]; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_str_to_cstr(mrb, s); ridx = strlen(path); if (ridx > 0) { ridx--; while (ridx > 0 && (path[ridx] == '/' || path[ridx] == '\\')) { path[ridx] = '\0'; ridx--; } if (strncmp(path, "/", 2) == 0) { return mrb_str_new_cstr(mrb, path); } } _splitpath((const char*)path, NULL, NULL, bname, extname); snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname); return mrb_str_new_cstr(mrb, buffer); #else char *bname, *path; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_str_to_cstr(mrb, s); if ((bname = basename(path)) == NULL) { mrb_sys_fail(mrb, "basename"); } if (strncmp(bname, "//", 3) == 0) bname[1] = '\0'; /* patch for Cygwin */ return mrb_str_new_cstr(mrb, bname); #endif }
static mrb_value mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self) { #ifdef HAVE_GETPEEREID mrb_value ary; gid_t egid; uid_t euid; int s; s = socket_fd(mrb, self); if (getpeereid(s, &euid, &egid) != 0) mrb_sys_fail(mrb, "getpeereid"); ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)euid)); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)egid)); return ary; #else mrb_raise(mrb, E_RUNTIME_ERROR, "getpeereid is not avaialble on this system"); return mrb_nil_value(); #endif }
static mrb_value mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self) { int n; mrb_int maxlen, flags = 0; mrb_value ary, buf, sa; socklen_t socklen; mrb_get_args(mrb, "i|i", &maxlen, &flags); buf = mrb_str_buf_new(mrb, maxlen); socklen = sizeof(struct sockaddr_storage); sa = mrb_str_buf_new(mrb, socklen); n = recvfrom(socket_fd(mrb, self), RSTRING_PTR(buf), maxlen, flags, (struct sockaddr *)RSTRING_PTR(sa), &socklen); if (n == -1) mrb_sys_fail(mrb, "recvfrom"); mrb_str_resize(mrb, buf, n); mrb_str_resize(mrb, sa, socklen); ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, buf); mrb_ary_push(mrb, ary, sa); return ary; }
static mrb_value mrb_file_dirname(mrb_state *mrb, mrb_value klass) { #if defined(_WIN32) || defined(_WIN64) char dname[_MAX_DIR], vname[_MAX_DRIVE]; char buffer[_MAX_DRIVE + _MAX_DIR]; char *path; size_t ridx; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, s), -1); _splitpath((const char*)path, vname, dname, NULL, NULL); snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname); mrb_locale_free(path); ridx = strlen(buffer); if (ridx == 0) { strncpy(buffer, ".", 2); /* null terminated */ } else if (ridx > 1) { ridx--; while (ridx > 0 && (buffer[ridx] == '/' || buffer[ridx] == '\\')) { buffer[ridx] = '\0'; /* remove last char */ ridx--; } } return mrb_str_new_cstr(mrb, buffer); #else char *dname, *path; mrb_value s; mrb_get_args(mrb, "S", &s); path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, s), -1); if ((dname = dirname(path)) == NULL) { mrb_locale_free(path); mrb_sys_fail(mrb, "dirname"); } mrb_locale_free(path); return mrb_str_new_cstr(mrb, dname); #endif }
void mrb_mruby_uri_parser_gem_init(mrb_state* mrb) { #ifdef _WIN32 WSADATA wsaData; errno = 0; int err = WSAStartup(MAKEWORD(2, 2), &wsaData); if (err != 0) { mrb_sys_fail(mrb, "WSAStartup"); } #endif struct RClass *uri_mod, *uri_error_class; uri_mod = mrb_define_module(mrb, "URI"); uri_error_class = mrb_define_class_under(mrb, uri_mod, "Error", E_RUNTIME_ERROR); mrb_define_class_under(mrb, uri_mod, "Malformed", uri_error_class); mrb_define_class_under(mrb, uri_mod, "HostNotPresent", uri_error_class); mrb_define_class_under(mrb, uri_mod, "HostNotParseable", uri_error_class); mrb_define_class_under(mrb, uri_mod, "ConnectMalformed", uri_error_class); mrb_define_class_under(mrb, uri_mod, "PortTooLarge", uri_error_class); mrb_define_module_function(mrb, uri_mod, "parse", mrb_http_parser_parse_url, MRB_ARGS_ARG(1, 1)); mrb_define_module_function(mrb, uri_mod, "get_port", mrb_uri_parser_get_port, MRB_ARGS_ARG(1, 1)); }
int mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode) { mrb_value emsg; int fd, retry = FALSE; char* fname = mrb_locale_from_utf8(pathname, -1); #ifdef O_CLOEXEC /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */ flags |= O_CLOEXEC; #elif defined O_NOINHERIT flags |= O_NOINHERIT; #endif reopen: fd = open(fname, (int)flags, (fmode_t)mode); if (fd == -1) { if (!retry) { switch (errno) { case ENFILE: case EMFILE: mrb_garbage_collect(mrb); retry = TRUE; goto reopen; } } emsg = mrb_format(mrb, "open %S", mrb_str_new_cstr(mrb, pathname)); mrb_str_modify(mrb, mrb_str_ptr(emsg)); mrb_sys_fail(mrb, RSTRING_PTR(emsg)); } mrb_locale_free(fname); if (fd <= 2) { mrb_fd_cloexec(mrb, fd); } return fd; }