1/********************************************************************** 2 3 io/wait.c - 4 5 $Author: nobu $ 6 created at: Tue Aug 28 09:08:06 JST 2001 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 16#include <sys/types.h> 17#if defined(HAVE_UNISTD_H) && (defined(__sun)) 18#include <unistd.h> 19#endif 20#if defined(HAVE_SYS_IOCTL_H) 21#include <sys/ioctl.h> 22#endif 23#if defined(FIONREAD_HEADER) 24#include FIONREAD_HEADER 25#endif 26 27#ifdef HAVE_RB_W32_IOCTLSOCKET 28#define ioctl ioctlsocket 29#define ioctl_arg u_long 30#define ioctl_arg2num(i) ULONG2NUM(i) 31#else 32#define ioctl_arg int 33#define ioctl_arg2num(i) INT2NUM(i) 34#endif 35 36#ifdef HAVE_RB_W32_IS_SOCKET 37#define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd) 38#else 39#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue) 40#endif 41 42static VALUE io_ready_p _((VALUE io)); 43static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io)); 44static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io)); 45void Init_wait _((void)); 46 47/* 48 * call-seq: 49 * io.nread -> int 50 * 51 * Returns number of bytes that can be read without blocking. 52 * Returns zero if no information available. 53 */ 54 55static VALUE 56io_nread(VALUE io) 57{ 58 rb_io_t *fptr; 59 int len; 60 ioctl_arg n; 61 62 GetOpenFile(io, fptr); 63 rb_io_check_readable(fptr); 64 len = rb_io_read_pending(fptr); 65 if (len > 0) return len; 66 if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0); 67 if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0); 68 if (n > 0) return ioctl_arg2num(n); 69 return INT2FIX(0); 70} 71 72/* 73 * call-seq: 74 * io.ready? -> true, false or nil 75 * 76 * Returns true if input available without blocking, or false. 77 * Returns nil if no information available. 78 */ 79 80static VALUE 81io_ready_p(VALUE io) 82{ 83 rb_io_t *fptr; 84 ioctl_arg n; 85 86 GetOpenFile(io, fptr); 87 rb_io_check_readable(fptr); 88 if (rb_io_read_pending(fptr)) return Qtrue; 89 if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qnil; 90 if (ioctl(fptr->fd, FIONREAD, &n)) return Qnil; 91 if (n > 0) return Qtrue; 92 return Qfalse; 93} 94 95/* 96 * call-seq: 97 * io.wait -> IO, true, false or nil 98 * io.wait(timeout) -> IO, true, false or nil 99 * 100 * Waits until input is available or times out and returns self or nil when 101 * EOF is reached. 102 */ 103 104static VALUE 105io_wait_readable(int argc, VALUE *argv, VALUE io) 106{ 107 rb_io_t *fptr; 108 int i; 109 ioctl_arg n; 110 VALUE timeout; 111 struct timeval timerec; 112 struct timeval *tv; 113 114 GetOpenFile(io, fptr); 115 rb_io_check_readable(fptr); 116 rb_scan_args(argc, argv, "01", &timeout); 117 if (NIL_P(timeout)) { 118 tv = NULL; 119 } 120 else { 121 timerec = rb_time_interval(timeout); 122 tv = &timerec; 123 } 124 125 if (rb_io_read_pending(fptr)) return Qtrue; 126 if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse; 127 i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv); 128 if (i < 0) 129 rb_sys_fail(0); 130 rb_io_check_closed(fptr); 131 if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0); 132 if (n > 0) return io; 133 return Qnil; 134} 135 136/* 137 * call-seq: 138 * io.wait_writable -> IO 139 * io.wait_writable(timeout) -> IO or nil 140 * 141 * Waits until IO writable is available or times out and returns self or 142 * nil when EOF is reached. 143 */ 144static VALUE 145io_wait_writable(int argc, VALUE *argv, VALUE io) 146{ 147 rb_io_t *fptr; 148 int i; 149 VALUE timeout; 150 struct timeval timerec; 151 struct timeval *tv; 152 153 GetOpenFile(io, fptr); 154 rb_io_check_writable(fptr); 155 rb_scan_args(argc, argv, "01", &timeout); 156 if (NIL_P(timeout)) { 157 tv = NULL; 158 } 159 else { 160 timerec = rb_time_interval(timeout); 161 tv = &timerec; 162 } 163 164 i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_OUT, tv); 165 if (i < 0) 166 rb_sys_fail(0); 167 rb_io_check_closed(fptr); 168 if (i & RB_WAITFD_OUT) 169 return io; 170 return Qnil; 171} 172 173/* 174 * IO wait methods 175 */ 176 177void 178Init_wait() 179{ 180 rb_define_method(rb_cIO, "nread", io_nread, 0); 181 rb_define_method(rb_cIO, "ready?", io_ready_p, 0); 182 rb_define_method(rb_cIO, "wait", io_wait_readable, -1); 183 rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1); 184 rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1); 185} 186