Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

unixsocket.c
Go to the documentation of this file.
1 /************************************************
2
3 unixsocket.c -
4
5 created at: Thu Mar 31 12:21:29 JST 1994
6
7 Copyright (C) 1993-2007 Yukihiro Matsumoto
8
9 ************************************************/
10
11 #include "rubysocket.h"
12
13 #ifdef HAVE_SYS_UN_H
14 struct unixsock_arg {
15 struct sockaddr_un *sockaddr;
16 socklen_t sockaddrlen;
17 int fd;
18 };
19
20 static VALUE
21 unixsock_connect_internal(VALUE a)
22 {
23 struct unixsock_arg *arg = (struct unixsock_arg *)a;
24 return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr,
25 arg->sockaddrlen, 0);
26 }
27
28 VALUE
29 rsock_init_unixsock(VALUE sock, VALUE path, int server)
30 {
31 struct sockaddr_un sockaddr;
32 socklen_t sockaddrlen;
33 int fd, status;
34 rb_io_t *fptr;
35
36 SafeStringValue(path);
37 fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
38 if (fd < 0) {
39 rsock_sys_fail_path("socket(2)", path);
40 }
41
42 INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
43 if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
44 rb_raise(rb_eArgError, "too long unix socket path (%ldbytes given but %dbytes max)",
45 RSTRING_LEN(path), (int)sizeof(sockaddr.sun_path));
46 }
47 memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
48 sockaddrlen = rsock_unix_sockaddr_len(path);
49
50 if (server) {
51 status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
52 }
53 else {
54 int prot;
55 struct unixsock_arg arg;
56 arg.sockaddr = &sockaddr;
57 arg.sockaddrlen = sockaddrlen;
58 arg.fd = fd;
59 status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
60 if (prot) {
61 close(fd);
62 rb_jump_tag(prot);
63 }
64 }
65
66 if (status < 0) {
67 close(fd);
68 rsock_sys_fail_path("connect(2)", path);
69 }
70
71 if (server) {
72 if (listen(fd, SOMAXCONN) < 0) {
73 close(fd);
74 rsock_sys_fail_path("listen(2)", path);
75 }
76 }
77
78 rsock_init_sock(sock, fd);
79 if (server) {
80 GetOpenFile(sock, fptr);
81 fptr->pathv = rb_str_new_frozen(path);
82 }
83
84 return sock;
85 }
86
87 /*
88 * call-seq:
89 * UNIXSocket.new(path) => unixsocket
90 *
91 * Creates a new UNIX client socket connected to _path_.
92 *
93 * s = UNIXSocket.new("/tmp/sock")
94 * s.send "hello", 0
95 *
96 */
97 static VALUE
98 unix_init(VALUE sock, VALUE path)
99 {
100 return rsock_init_unixsock(sock, path, 0);
101 }
102
103 /*
104 * call-seq:
105 * unixsocket.path => path
106 *
107 * Returns the path of the local address of unixsocket.
108 *
109 * s = UNIXServer.new("/tmp/sock")
110 * p s.path #=> "/tmp/sock"
111 *
112 */
113 static VALUE
114 unix_path(VALUE sock)
115 {
116 rb_io_t *fptr;
117
118 GetOpenFile(sock, fptr);
119 if (NIL_P(fptr->pathv)) {
120 struct sockaddr_un addr;
121 socklen_t len = (socklen_t)sizeof(addr);
122 socklen_t len0 = len;
123 if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
124 rsock_sys_fail_path("getsockname(2)", fptr->pathv);
125 if (len0 < len) len = len0;
126 fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
127 }
128 return rb_str_dup(fptr->pathv);
129 }
130
131 /*
132 * call-seq:
133 * unixsocket.recvfrom(maxlen [, flags]) => [mesg, unixaddress]
134 *
135 * Receives a message via _unixsocket_.
136 *
137 * _maxlen_ is the maximum number of bytes to receive.
138 *
139 * _flags_ should be a bitwise OR of Socket::MSG_* constants.
140 *
141 * s1 = Socket.new(:UNIX, :DGRAM, 0)
142 * s1_ai = Addrinfo.unix("/tmp/sock1")
143 * s1.bind(s1_ai)
144 *
145 * s2 = Socket.new(:UNIX, :DGRAM, 0)
146 * s2_ai = Addrinfo.unix("/tmp/sock2")
147 * s2.bind(s2_ai)
148 * s3 = UNIXSocket.for_fd(s2.fileno)
149 *
150 * s1.send "a", 0, s2_ai
151 * p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]]
152 *
153 */
154 static VALUE
155 unix_recvfrom(int argc, VALUE *argv, VALUE sock)
156 {
157 return rsock_s_recvfrom(sock, argc, argv, RECV_UNIX);
158 }
159
160 #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(SCM_RIGHTS)
161 #define FD_PASSING_BY_MSG_CONTROL 1
162 #else
163 #define FD_PASSING_BY_MSG_CONTROL 0
164 #endif
165
166 #if defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS)
167 #define FD_PASSING_BY_MSG_ACCRIGHTS 1
168 #else
169 #define FD_PASSING_BY_MSG_ACCRIGHTS 0
170 #endif
171
172 struct iomsg_arg {
173 int fd;
174 struct msghdr msg;
175 };
176
177 #if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
178 static VALUE
179 sendmsg_blocking(void *data)
180 {
181 struct iomsg_arg *arg = data;
182 return sendmsg(arg->fd, &arg->msg, 0);
183 }
184
185 /*
186 * call-seq:
187 * unixsocket.send_io(io) => nil
188 *
189 * Sends _io_ as file descriptor passing.
190 *
191 * s1, s2 = UNIXSocket.pair
192 *
193 * s1.send_io STDOUT
194 * stdout = s2.recv_io
195 *
196 * p STDOUT.fileno #=> 1
197 * p stdout.fileno #=> 6
198 *
199 * stdout.puts "hello" # outputs "hello\n" to standard output.
200 */
201 static VALUE
202 unix_send_io(VALUE sock, VALUE val)
203 {
204 int fd;
205 rb_io_t *fptr;
206 struct iomsg_arg arg;
207 struct iovec vec[1];
208 char buf[1];
209
210 #if FD_PASSING_BY_MSG_CONTROL
211 union {
212 struct cmsghdr hdr;
213 char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
214 } cmsg;
215 #endif
216
217 if (rb_obj_is_kind_of(val, rb_cIO)) {
218 rb_io_t *valfptr;
219 GetOpenFile(val, valfptr);
220 fd = valfptr->fd;
221 }
222 else if (FIXNUM_P(val)) {
223 fd = FIX2INT(val);
224 }
225 else {
226 rb_raise(rb_eTypeError, "neither IO nor file descriptor");
227 }
228
229 GetOpenFile(sock, fptr);
230
231 arg.msg.msg_name = NULL;
232 arg.msg.msg_namelen = 0;
233
234 /* Linux and Solaris doesn't work if msg_iov is NULL. */
235 buf[0] = '\0';
236 vec[0].iov_base = buf;
237 vec[0].iov_len = 1;
238 arg.msg.msg_iov = vec;
239 arg.msg.msg_iovlen = 1;
240
241 #if FD_PASSING_BY_MSG_CONTROL
242 arg.msg.msg_control = (caddr_t)&cmsg;
243 arg.msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof(int));
244 arg.msg.msg_flags = 0;
245 MEMZERO((char*)&cmsg, char, sizeof(cmsg));
246 cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
247 cmsg.hdr.cmsg_level = SOL_SOCKET;
248 cmsg.hdr.cmsg_type = SCM_RIGHTS;
249 memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
250 #else
251 arg.msg.msg_accrights = (caddr_t)&fd;
252 arg.msg.msg_accrightslen = sizeof(fd);
253 #endif
254
255 arg.fd = fptr->fd;
256 while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) {
257 if (!rb_io_wait_writable(arg.fd))
258 rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
259 }
260
261 return Qnil;
262 }
263 #else
264 #define unix_send_io rb_f_notimplement
265 #endif
266
267 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
268 static VALUE
269 recvmsg_blocking(void *data)
270 {
271 struct iomsg_arg *arg = data;
272 int flags = 0;
273 return rsock_recvmsg(arg->fd, &arg->msg, flags);
274 }
275
276 /*
277 * call-seq:
278 * unixsocket.recv_io([klass [, mode]]) => io
279 *
280 * UNIXServer.open("/tmp/sock") {|serv|
281 * UNIXSocket.open("/tmp/sock") {|c|
282 * s = serv.accept
283 *
284 * c.send_io STDOUT
285 * stdout = s.recv_io
286 *
287 * p STDOUT.fileno #=> 1
288 * p stdout.fileno #=> 7
289 *
290 * stdout.puts "hello" # outputs "hello\n" to standard output.
291 * }
292 * }
293 *
294 */
295 static VALUE
296 unix_recv_io(int argc, VALUE *argv, VALUE sock)
297 {
298 VALUE klass, mode;
299 rb_io_t *fptr;
300 struct iomsg_arg arg;
301 struct iovec vec[2];
302 char buf[1];
303
304 int fd;
305 #if FD_PASSING_BY_MSG_CONTROL
306 union {
307 struct cmsghdr hdr;
308 char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
309 } cmsg;
310 #endif
311
312 rb_scan_args(argc, argv, "02", &klass, &mode);
313 if (argc == 0)
314 klass = rb_cIO;
315 if (argc <= 1)
316 mode = Qnil;
317
318 GetOpenFile(sock, fptr);
319
320 arg.msg.msg_name = NULL;
321 arg.msg.msg_namelen = 0;
322
323 vec[0].iov_base = buf;
324 vec[0].iov_len = sizeof(buf);
325 arg.msg.msg_iov = vec;
326 arg.msg.msg_iovlen = 1;
327
328 #if FD_PASSING_BY_MSG_CONTROL
329 arg.msg.msg_control = (caddr_t)&cmsg;
330 arg.msg.msg_controllen = (socklen_t)CMSG_SPACE(sizeof(int));
331 arg.msg.msg_flags = 0;
332 cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
333 cmsg.hdr.cmsg_level = SOL_SOCKET;
334 cmsg.hdr.cmsg_type = SCM_RIGHTS;
335 fd = -1;
336 memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
337 #else
338 arg.msg.msg_accrights = (caddr_t)&fd;
339 arg.msg.msg_accrightslen = sizeof(fd);
340 fd = -1;
341 #endif
342
343 arg.fd = fptr->fd;
344 while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) {
345 if (!rb_io_wait_readable(arg.fd))
346 rsock_sys_fail_path("recvmsg(2)", fptr->pathv);
347 }
348
349 #if FD_PASSING_BY_MSG_CONTROL
350 if (arg.msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr)) {
351 rb_raise(rb_eSocket,
352 "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
353 (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
354 }
355 if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
356 rb_raise(rb_eSocket,
357 "file descriptor was not passed (cmsg_level=%d, %d expected)",
358 cmsg.hdr.cmsg_level, SOL_SOCKET);
359 }
360 if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
361 rb_raise(rb_eSocket,
362 "file descriptor was not passed (cmsg_type=%d, %d expected)",
363 cmsg.hdr.cmsg_type, SCM_RIGHTS);
364 }
365 if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) {
366 rb_raise(rb_eSocket,
367 "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
368 (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
369 }
370 if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
371 rb_raise(rb_eSocket,
372 "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
373 (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
374 }
375 if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
376 rsock_discard_cmsg_resource(&arg.msg, 0);
377 rb_raise(rb_eSocket,
378 "file descriptor was not passed (cmsg_len=%d, %d expected)",
379 (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
380 }
381 #else
382 if (arg.msg.msg_accrightslen != sizeof(fd)) {
383 rb_raise(rb_eSocket,
384 "file descriptor was not passed (accrightslen=%d, %d expected)",
385 arg.msg.msg_accrightslen, (int)sizeof(fd));
386 }
387 #endif
388
389 #if FD_PASSING_BY_MSG_CONTROL
390 memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int));
391 #endif
392 rb_fd_fix_cloexec(fd);
393
394 if (klass == Qnil)
395 return INT2FIX(fd);
396 else {
397 ID for_fd;
398 int ff_argc;
399 VALUE ff_argv[2];
400 CONST_ID(for_fd, "for_fd");
401 ff_argc = mode == Qnil ? 1 : 2;
402 ff_argv[0] = INT2FIX(fd);
403 ff_argv[1] = mode;
404 return rb_funcall2(klass, for_fd, ff_argc, ff_argv);
405 }
406 }
407 #else
408 #define unix_recv_io rb_f_notimplement
409 #endif
410
411 /*
412 * call-seq:
413 * unixsocket.addr => [address_family, unix_path]
414 *
415 * Returns the local address as an array which contains
416 * address_family and unix_path.
417 *
418 * Example
419 * serv = UNIXServer.new("/tmp/sock")
420 * p serv.addr #=> ["AF_UNIX", "/tmp/sock"]
421 */
422 static VALUE
423 unix_addr(VALUE sock)
424 {
425 rb_io_t *fptr;
426 struct sockaddr_un addr;
427 socklen_t len = (socklen_t)sizeof addr;
428 socklen_t len0 = len;
429
430 GetOpenFile(sock, fptr);
431
432 if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
433 rsock_sys_fail_path("getsockname(2)", fptr->pathv);
434 if (len0 < len) len = len0;
435 return rsock_unixaddr(&addr, len);
436 }
437
438 /*
439 * call-seq:
440 * unixsocket.peeraddr => [address_family, unix_path]
441 *
442 * Returns the remote address as an array which contains
443 * address_family and unix_path.
444 *
445 * Example
446 * serv = UNIXServer.new("/tmp/sock")
447 * c = UNIXSocket.new("/tmp/sock")
448 * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"]
449 */
450 static VALUE
451 unix_peeraddr(VALUE sock)
452 {
453 rb_io_t *fptr;
454 struct sockaddr_un addr;
455 socklen_t len = (socklen_t)sizeof addr;
456 socklen_t len0 = len;
457
458 GetOpenFile(sock, fptr);
459
460 if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
461 rsock_sys_fail_path("getpeername(2)", fptr->pathv);
462 if (len0 < len) len = len0;
463 return rsock_unixaddr(&addr, len);
464 }
465
466 /*
467 * call-seq:
468 * UNIXSocket.pair([type [, protocol]]) => [unixsocket1, unixsocket2]
469 * UNIXSocket.socketpair([type [, protocol]]) => [unixsocket1, unixsocket2]
470 *
471 * Creates a pair of sockets connected each other.
472 *
473 * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
474 *
475 * _protocol_ should be a protocol defined in the domain.
476 * 0 is default protocol for the domain.
477 *
478 * s1, s2 = UNIXSocket.pair
479 * s1.send "a", 0
480 * s1.send "b", 0
481 * p s2.recv(10) #=> "ab"
482 *
483 */
484 static VALUE
485 unix_s_socketpair(int argc, VALUE *argv, VALUE klass)
486 {
487 VALUE domain, type, protocol;
488 VALUE args[3];
489
490 domain = INT2FIX(PF_UNIX);
491 rb_scan_args(argc, argv, "02", &type, &protocol);
492 if (argc == 0)
493 type = INT2FIX(SOCK_STREAM);
494 if (argc <= 1)
495 protocol = INT2FIX(0);
496
497 args[0] = domain;
498 args[1] = type;
499 args[2] = protocol;
500
501 return rsock_sock_s_socketpair(3, args, klass);
502 }
503 #endif
504
505 void
506 rsock_init_unixsocket(void)
507 {
508 #ifdef HAVE_SYS_UN_H
509 /*
510 * Document-class: UNIXSocket < BasicSocket
511 *
512 * UNIXSocket represents a UNIX domain stream client socket.
513 */
514 rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
515 rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
516 rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
517 rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
518 rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
519 rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
520 rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
521 rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
522 rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
523 rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
524 #endif
525 }
rsock_init_unixsocket
void rsock_init_unixsocket(void)
Definition: unixsocket.c:506
rsock_init_unixsock
VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server)
SOMAXCONN
#define SOMAXCONN
Definition: constdefs.h:1704
rb_cBasicSocket
VALUE rb_cBasicSocket
Definition: init.c:13
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1655
sendmsg
int sendmsg(int, const struct msghdr *, int)
Definition: win32.c:3438
rb_io_t
Definition: io.h:61
msghdr
Definition: win32.h:235
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rsock_init_sock
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:43
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:118
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1351
rsock_sock_s_socketpair
VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
val
#define val
rsock_socket
int rsock_socket(int domain, int type, int proto)
Definition: init.c:285
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
msg
static char msg[50]
Definition: strerror.c:8
rb_io_t::fd
int fd
Definition: io.h:62
rb_io_wait_writable
int rb_io_wait_writable(int)
Definition: io.c:1103
argc
int argc
Definition: ruby.c:131
rb_cIO
RUBY_EXTERN VALUE rb_cIO
Definition: ruby.h:1569
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
socklen_t
int socklen_t
Definition: getaddrinfo.c:84
rsock_s_recvfrom
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:111
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
ID
unsigned long ID
Definition: ruby.h:89
Qnil
#define Qnil
Definition: ruby.h:427
type
int type
Definition: tcltklib.c:112
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:632
iovec
Definition: win32.h:231
rb_jump_tag
void rb_jump_tag(int tag)
Definition: eval.c:706
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1062
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
rb_eSocket
VALUE rb_eSocket
Definition: init.c:25
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rubysocket.h
sizeof
#define sizeof(x)
Definition: zlib.c:58
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:221
rsock_connect
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:386
rb_io_t::pathv
VALUE pathv
Definition: io.h:67
RECV_UNIX
Definition: rubysocket.h:332
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:545
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:833
rsock_sys_fail_path
void rsock_sys_fail_path(const char *mesg, VALUE path)
Definition: socket.c:35
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1428
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
NULL
#define NULL
Definition: _sdbm.c:103
rb_io_wait_readable
int rb_io_wait_readable(int)
Definition: io.c:1077
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
BLOCKING_REGION_FD
#define BLOCKING_REGION_FD(func, arg)
Definition: rubysocket.h:259
argv
char ** argv
Definition: ruby.c:132