From d481323b9211cc0823fba407253d0432fa7f1734 Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 20 Nov 2007 08:12:34 +0000 Subject: * io.c (rb_io_close_on_exec_p): new method IO#close_on_exec?. (rb_io_set_close_on_exec): new method IO#close_on_exec=. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13983 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- io.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 369f0b0e59..7b9b487318 100644 --- a/io.c +++ b/io.c @@ -2295,6 +2295,99 @@ rb_io_isatty(VALUE io) return Qtrue; } +/* + * call-seq: + * ios.close_on_exec? => true or false + * + * Returns true if ios will be closed on exec. + * + * f = open("/dev/null") + * f.close_on_exec? #=> false + * f.close_on_exec = true + * f.close_on_exec? #=> true + * f.close_on_exec = false + * f.close_on_exec? #=> false + */ + +static VALUE +rb_io_close_on_exec_p(VALUE io) +{ +#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) + rb_io_t *fptr; + VALUE write_io; + int fd, ret; + + write_io = GetWriteIO(io); + if (io != write_io) { + GetOpenFile(write_io, fptr); + if (fptr && 0 <= (fd = fptr->fd)) { + if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path); + if (!(ret & FD_CLOEXEC)) return Qfalse; + } + } + + GetOpenFile(io, fptr); + if (fptr && 0 <= (fd = fptr->fd)) { + if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path); + if (!(ret & FD_CLOEXEC)) return Qfalse; + } + return Qtrue; +#else + rb_notimplement(); + return Qnil; /* not reached */ +#endif +} + +/* + * call-seq: + * ios.close_on_exec = bool => true or false + * + * Sets a close-on-exec flag. + * + * f = open("/dev/null") + * f.close_on_exec = true + * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory + * f.closed? #=> false + */ + +static VALUE +rb_io_set_close_on_exec(VALUE io, VALUE arg) +{ +#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) + int flag = RTEST(arg) ? FD_CLOEXEC : 0; + rb_io_t *fptr; + VALUE write_io; + int fd, ret; + + write_io = GetWriteIO(io); + if (io != write_io) { + GetOpenFile(write_io, fptr); + if (fptr && 0 <= (fd = fptr->fd)) { + if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail(fptr->path); + if ((ret & FD_CLOEXEC) != flag) { + ret = (ret & ~FD_CLOEXEC) | flag; + ret = fcntl(fd, F_SETFD, ret); + if (ret == -1) rb_sys_fail(fptr->path); + } + } + + } + + GetOpenFile(io, fptr); + if (fptr && 0 <= (fd = fptr->fd)) { + if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail(fptr->path); + if ((ret & FD_CLOEXEC) != flag) { + ret = (ret & ~FD_CLOEXEC) | flag; + ret = fcntl(fd, F_SETFD, ret); + if (ret == -1) rb_sys_fail(fptr->path); + } + } +#else + rb_notimplement(); +#endif + return Qnil; +} + #define FMODE_PREP (1<<16) #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP) #define PREP_STDIO_NAME(f) ((f)->path) @@ -6021,6 +6114,9 @@ Init_IO(void) rb_define_method(rb_cIO, "eof", rb_io_eof, 0); rb_define_method(rb_cIO, "eof?", rb_io_eof, 0); + rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0); + rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1); + rb_define_method(rb_cIO, "close", rb_io_close_m, 0); rb_define_method(rb_cIO, "closed?", rb_io_closed, 0); rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0); -- cgit v1.2.3