1/********************************************************************** 2 3 io/wait.c - 4 5 $Author: kosaki $ 6 created at: Tue Jul 14 21:53:18 2009 7 8 All the files in this distribution are covered under the Ruby's 9 license (see the file COPYING). 10 11**********************************************************************/ 12 13#include "ruby.h" 14#include "ruby/io.h" 15#ifdef HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18#include <fcntl.h> 19 20#ifdef F_GETFL 21static int 22io_nonblock_mode(int fd) 23{ 24 int f = fcntl(fd, F_GETFL); 25 if (f == -1) rb_sys_fail(0); 26 return f; 27} 28#else 29#define io_nonblock_mode(fd) ((void)(fd), 0) 30#endif 31 32#ifdef F_GETFL 33static VALUE 34rb_io_nonblock_p(VALUE io) 35{ 36 rb_io_t *fptr; 37 GetOpenFile(io, fptr); 38 if (io_nonblock_mode(fptr->fd) & O_NONBLOCK) 39 return Qtrue; 40 return Qfalse; 41} 42#else 43#define rb_io_nonblock_p rb_f_notimplement 44#endif 45 46#ifdef F_SETFL 47static void 48io_nonblock_set(int fd, int f, int nb) 49{ 50 if (nb) { 51 if ((f & O_NONBLOCK) != 0) 52 return; 53 f |= O_NONBLOCK; 54 } 55 else { 56 if ((f & O_NONBLOCK) == 0) 57 return; 58 f &= ~O_NONBLOCK; 59 } 60 if (fcntl(fd, F_SETFL, f) == -1) 61 rb_sys_fail(0); 62} 63 64static VALUE 65rb_io_nonblock_set(VALUE io, VALUE nb) 66{ 67 rb_io_t *fptr; 68 GetOpenFile(io, fptr); 69 io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb)); 70 return io; 71} 72 73static VALUE 74io_nonblock_restore(VALUE arg) 75{ 76 int *restore = (int *)arg; 77 if (fcntl(restore[0], F_SETFL, restore[1]) == -1) 78 rb_sys_fail(0); 79 return Qnil; 80} 81 82static VALUE 83rb_io_nonblock_block(int argc, VALUE *argv, VALUE io) 84{ 85 int nb = 1; 86 rb_io_t *fptr; 87 int f, restore[2]; 88 89 GetOpenFile(io, fptr); 90 if (argc > 0) { 91 VALUE v; 92 rb_scan_args(argc, argv, "01", &v); 93 nb = RTEST(v); 94 } 95 f = io_nonblock_mode(fptr->fd); 96 restore[0] = fptr->fd; 97 restore[1] = f; 98 io_nonblock_set(fptr->fd, f, nb); 99 return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore); 100} 101#else 102#define rb_io_nonblock_set rb_f_notimplement 103#define rb_io_nonblock_block rb_f_notimplement 104#endif 105 106void 107Init_nonblock(void) 108{ 109 VALUE io = rb_cIO; 110 111 rb_define_method(io, "nonblock?", rb_io_nonblock_p, 0); 112 rb_define_method(io, "nonblock=", rb_io_nonblock_set, 1); 113 rb_define_method(io, "nonblock", rb_io_nonblock_block, -1); 114} 115