Ruby 1.9.3p327(2012-11-10revision37606)
ext/io/nonblock/nonblock.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io/wait.c -
00004 
00005   $Author: kosaki $
00006   created at: Tue Jul 14 21:53:18 2009
00007 
00008   All the files in this distribution are covered under the Ruby's
00009   license (see the file COPYING).
00010 
00011 **********************************************************************/
00012 
00013 #include "ruby.h"
00014 #include "ruby/io.h"
00015 #ifdef HAVE_UNISTD_H
00016 #include <unistd.h>
00017 #endif
00018 #include <fcntl.h>
00019 
00020 #ifdef F_GETFL
00021 static int
00022 io_nonblock_mode(int fd)
00023 {
00024     int f = fcntl(fd, F_GETFL);
00025     if (f == -1) rb_sys_fail(0);
00026     return f;
00027 }
00028 #else
00029 #define io_nonblock_mode(fd) ((void)(fd), 0)
00030 #endif
00031 
00032 #ifdef F_GETFL
00033 static VALUE
00034 rb_io_nonblock_p(VALUE io)
00035 {
00036     rb_io_t *fptr;
00037     GetOpenFile(io, fptr);
00038     if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
00039         return Qtrue;
00040     return Qfalse;
00041 }
00042 #else
00043 #define rb_io_nonblock_p rb_f_notimplement
00044 #endif
00045 
00046 #ifdef F_SETFL
00047 static void
00048 io_nonblock_set(int fd, int f, int nb)
00049 {
00050     if (nb) {
00051         if ((f & O_NONBLOCK) != 0)
00052             return;
00053         f |= O_NONBLOCK;
00054     }
00055     else {
00056         if ((f & O_NONBLOCK) == 0)
00057             return;
00058         f &= ~O_NONBLOCK;
00059     }
00060     if (fcntl(fd, F_SETFL, f) == -1)
00061         rb_sys_fail(0);
00062 }
00063 
00064 static VALUE
00065 rb_io_nonblock_set(VALUE io, VALUE nb)
00066 {
00067     rb_io_t *fptr;
00068     GetOpenFile(io, fptr);
00069     io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
00070     return io;
00071 }
00072 
00073 static VALUE
00074 io_nonblock_restore(VALUE arg)
00075 {
00076     int *restore = (int *)arg;
00077     if (fcntl(restore[0], F_SETFL, restore[1]) == -1)
00078         rb_sys_fail(0);
00079     return Qnil;
00080 }
00081 
00082 static VALUE
00083 rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
00084 {
00085     int nb = 1;
00086     rb_io_t *fptr;
00087     int f, restore[2];
00088 
00089     GetOpenFile(io, fptr);
00090     if (argc > 0) {
00091         VALUE v;
00092         rb_scan_args(argc, argv, "01", &v);
00093         nb = RTEST(v);
00094     }
00095     f = io_nonblock_mode(fptr->fd);
00096     restore[0] = fptr->fd;
00097     restore[1] = f;
00098     io_nonblock_set(fptr->fd, f, nb);
00099     return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore);
00100 }
00101 #else
00102 #define rb_io_nonblock_set rb_f_notimplement
00103 #define rb_io_nonblock_block rb_f_notimplement
00104 #endif
00105 
00106 void
00107 Init_nonblock(void)
00108 {
00109     VALUE io = rb_cIO;
00110 
00111     rb_define_method(io, "nonblock?", rb_io_nonblock_p, 0);
00112     rb_define_method(io, "nonblock=", rb_io_nonblock_set, 1);
00113     rb_define_method(io, "nonblock", rb_io_nonblock_block, -1);
00114 }
00115