Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

console.c
Go to the documentation of this file.
1 /* -*- c-file-style: "ruby" -*- */
2 /*
3 * console IO module
4 */
5 #include "ruby.h"
6 #ifdef HAVE_RUBY_IO_H
7 #include "ruby/io.h"
8 #else
9 #include "rubyio.h"
10 /* assumes rb_io_t doesn't have pathv */
11 #include "util.h" /* for ruby_strdup() */
12 #endif
13
14 #ifndef HAVE_RB_IO_T
15 typedef OpenFile rb_io_t;
16 #endif
17
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #ifdef HAVE_FCNTL_H
22 #include <fcntl.h>
23 #endif
24 #ifdef HAVE_SYS_IOCTL_H
25 #include <sys/ioctl.h>
26 #endif
27
28 #ifndef RB_TYPE_P
29 #define RB_TYPE_P(obj, type) (TYPE(obj) == type)
30 #endif
31
32 #if defined HAVE_TERMIOS_H
33 # include <termios.h>
34 typedef struct termios conmode;
35
36 static int
37 setattr(int fd, conmode *t)
38 {
39 while (tcsetattr(fd, TCSAFLUSH, t)) {
40 if (errno != EINTR) return 0;
41 }
42 return 1;
43 }
44 # define getattr(fd, t) (tcgetattr(fd, t) == 0)
45 #elif defined HAVE_TERMIO_H
46 # include <termio.h>
47 typedef struct termio conmode;
48 # define setattr(fd, t) (ioctl(fd, TCSETAF, t) == 0)
49 # define getattr(fd, t) (ioctl(fd, TCGETA, t) == 0)
50 #elif defined HAVE_SGTTY_H
51 # include <sgtty.h>
52 typedef struct sgttyb conmode;
53 # ifdef HAVE_STTY
54 # define setattr(fd, t) (stty(fd, t) == 0)
55 # else
56 # define setattr(fd, t) (ioctl((fd), TIOCSETP, (t)) == 0)
57 # endif
58 # ifdef HAVE_GTTY
59 # define getattr(fd, t) (gtty(fd, t) == 0)
60 # else
61 # define getattr(fd, t) (ioctl((fd), TIOCGETP, (t)) == 0)
62 # endif
63 #elif defined _WIN32
64 #include <winioctl.h>
65 typedef DWORD conmode;
66
67 #ifdef HAVE_RB_W32_MAP_ERRNO
68 #define LAST_ERROR rb_w32_map_errno(GetLastError())
69 #else
70 #define LAST_ERROR EBADF
71 #endif
72 #define SET_LAST_ERROR (errno = LAST_ERROR, 0)
73
74 static int
75 setattr(int fd, conmode *t)
76 {
77 int x = SetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), *t);
78 if (!x) errno = LAST_ERROR;
79 return x;
80 }
81
82 static int
83 getattr(int fd, conmode *t)
84 {
85 int x = GetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), t);
86 if (!x) errno = LAST_ERROR;
87 return x;
88 }
89 #endif
90 #ifndef SET_LAST_ERROR
91 #define SET_LAST_ERROR (0)
92 #endif
93
94 #ifndef InitVM
95 #define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();}
96 #endif
97
98 static ID id_getc, id_console;
99
100 typedef struct {
101 int vmin;
102 int vtime;
103 } rawmode_arg_t;
104
105 static rawmode_arg_t *
106 rawmode_opt(int argc, VALUE *argv, rawmode_arg_t *opts)
107 {
108 rawmode_arg_t *optp = NULL;
109 VALUE vopts;
110 #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
111 rb_scan_args(argc, argv, "0:", &vopts);
112 #else
113 vopts = Qnil;
114 if (argc > 0) {
115 vopts = argv[--argc];
116 if (!NIL_P(vopts)) {
117 # ifdef HAVE_RB_CHECK_HASH_TYPE
118 vopts = rb_check_hash_type(vopts);
119 if (NIL_P(vopts)) ++argc;
120 # else
121 Check_Type(vopts, T_HASH);
122 # endif
123 }
124 }
125 rb_scan_args(argc, argv, "0");
126 #endif
127 if (!NIL_P(vopts)) {
128 VALUE vmin = rb_hash_aref(vopts, ID2SYM(rb_intern("min")));
129 VALUE vtime = rb_hash_aref(vopts, ID2SYM(rb_intern("time")));
130 /* default values by `stty raw` */
131 opts->vmin = 1;
132 opts->vtime = 0;
133 if (!NIL_P(vmin)) {
134 opts->vmin = NUM2INT(vmin);
135 optp = opts;
136 }
137 if (!NIL_P(vtime)) {
138 VALUE v10 = INT2FIX(10);
139 vtime = rb_funcall3(vtime, '*', 1, &v10);
140 opts->vtime = NUM2INT(vtime);
141 optp = opts;
142 }
143 }
144 return optp;
145 }
146
147 static void
148 set_rawmode(conmode *t, void *arg)
149 {
150 #ifdef HAVE_CFMAKERAW
151 cfmakeraw(t);
152 t->c_lflag &= ~(ECHOE|ECHOK);
153 #elif defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
154 t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
155 t->c_oflag &= ~OPOST;
156 t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
157 t->c_cflag &= ~(CSIZE|PARENB);
158 t->c_cflag |= CS8;
159 #elif defined HAVE_SGTTY_H
160 t->sg_flags &= ~ECHO;
161 t->sg_flags |= RAW;
162 #elif defined _WIN32
163 *t = 0;
164 #endif
165 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
166 if (arg) {
167 const rawmode_arg_t *r = arg;
168 if (r->vmin >= 0) t->c_cc[VMIN] = r->vmin;
169 if (r->vtime >= 0) t->c_cc[VTIME] = r->vtime;
170 }
171 #endif
172 }
173
174 static void
175 set_cookedmode(conmode *t, void *arg)
176 {
177 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
178 t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
179 t->c_oflag |= OPOST;
180 t->c_lflag |= (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
181 #elif defined HAVE_SGTTY_H
182 t->sg_flags |= ECHO;
183 t->sg_flags &= ~RAW;
184 #elif defined _WIN32
185 *t |= ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT;
186 #endif
187 }
188
189 static void
190 set_noecho(conmode *t, void *arg)
191 {
192 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
193 t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
194 #elif defined HAVE_SGTTY_H
195 t->sg_flags &= ~ECHO;
196 #elif defined _WIN32
197 *t &= ~ENABLE_ECHO_INPUT;
198 #endif
199 }
200
201 static void
202 set_echo(conmode *t, void *arg)
203 {
204 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
205 t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
206 #elif defined HAVE_SGTTY_H
207 t->sg_flags |= ECHO;
208 #elif defined _WIN32
209 *t |= ENABLE_ECHO_INPUT;
210 #endif
211 }
212
213 static int
214 echo_p(conmode *t)
215 {
216 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
217 return (t->c_lflag & (ECHO | ECHONL)) != 0;
218 #elif defined HAVE_SGTTY_H
219 return (t->sg_flags & ECHO) != 0;
220 #elif defined _WIN32
221 return (*t & ENABLE_ECHO_INPUT) != 0;
222 #endif
223 }
224
225 static int
226 set_ttymode(int fd, conmode *t, void (*setter)(conmode *, void *), void *arg)
227 {
228 conmode r;
229 if (!getattr(fd, t)) return 0;
230 r = *t;
231 setter(&r, arg);
232 return setattr(fd, &r);
233 }
234
235 #ifdef GetReadFile
236 #define GetReadFD(fptr) fileno(GetReadFile(fptr))
237 #else
238 #define GetReadFD(fptr) ((fptr)->fd)
239 #endif
240
241 #ifdef GetWriteFile
242 #define GetWriteFD(fptr) fileno(GetWriteFile(fptr))
243 #else
244 static inline int
245 get_write_fd(const rb_io_t *fptr)
246 {
247 VALUE wio = fptr->tied_io_for_writing;
248 rb_io_t *ofptr;
249 if (!wio) return fptr->fd;
250 GetOpenFile(wio, ofptr);
251 return ofptr->fd;
252 }
253 #define GetWriteFD(fptr) get_write_fd(fptr)
254 #endif
255
256 #define FD_PER_IO 2
257
258 static VALUE
259 ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void *arg)
260 {
261 rb_io_t *fptr;
262 int status = -1;
263 int error = 0;
264 int fd[FD_PER_IO];
265 conmode t[FD_PER_IO];
266 VALUE result = Qnil;
267
268 GetOpenFile(io, fptr);
269 fd[0] = GetReadFD(fptr);
270 if (fd[0] != -1) {
271 if (set_ttymode(fd[0], t+0, setter, arg)) {
272 status = 0;
273 }
274 else {
275 error = errno;
276 fd[0] = -1;
277 }
278 }
279 fd[1] = GetWriteFD(fptr);
280 if (fd[1] != -1 && fd[1] != fd[0]) {
281 if (set_ttymode(fd[1], t+1, setter, arg)) {
282 status = 0;
283 }
284 else {
285 error = errno;
286 fd[1] = -1;
287 }
288 }
289 if (status == 0) {
290 result = rb_protect(func, io, &status);
291 }
292 GetOpenFile(io, fptr);
293 if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) {
294 if (!setattr(fd[0], t+0)) {
295 error = errno;
296 status = -1;
297 }
298 }
299 if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(fptr)) {
300 if (!setattr(fd[1], t+1)) {
301 error = errno;
302 status = -1;
303 }
304 }
305 if (status) {
306 if (status == -1) {
307 errno = error;
308 rb_sys_fail(0);
309 }
310 rb_jump_tag(status);
311 }
312 return result;
313 }
314
315 /*
316 * call-seq:
317 * io.raw(min: nil, time: nil) {|io| }
318 *
319 * Yields +self+ within raw mode.
320 *
321 * STDIN.raw(&:gets)
322 *
323 * will read and return a line without echo back and line editing.
324 *
325 * You must require 'io/console' to use this method.
326 */
327 static VALUE
328 console_raw(int argc, VALUE *argv, VALUE io)
329 {
330 rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
331 return ttymode(io, rb_yield, set_rawmode, optp);
332 }
333
334 /*
335 * call-seq:
336 * io.raw!(min: nil, time: nil)
337 *
338 * Enables raw mode.
339 *
340 * If the terminal mode needs to be back, use io.raw { ... }.
341 *
342 * You must require 'io/console' to use this method.
343 */
344 static VALUE
345 console_set_raw(int argc, VALUE *argv, VALUE io)
346 {
347 conmode t;
348 rb_io_t *fptr;
349 int fd;
350 rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
351
352 GetOpenFile(io, fptr);
353 fd = GetReadFD(fptr);
354 if (!getattr(fd, &t)) rb_sys_fail(0);
355 set_rawmode(&t, optp);
356 if (!setattr(fd, &t)) rb_sys_fail(0);
357 return io;
358 }
359
360 /*
361 * call-seq:
362 * io.cooked {|io| }
363 *
364 * Yields +self+ within cooked mode.
365 *
366 * STDIN.cooked(&:gets)
367 *
368 * will read and return a line with echo back and line editing.
369 *
370 * You must require 'io/console' to use this method.
371 */
372 static VALUE
373 console_cooked(VALUE io)
374 {
375 return ttymode(io, rb_yield, set_cookedmode, NULL);
376 }
377
378 /*
379 * call-seq:
380 * io.cooked!
381 *
382 * Enables cooked mode.
383 *
384 * If the terminal mode needs to be back, use io.cooked { ... }.
385 *
386 * You must require 'io/console' to use this method.
387 */
388 static VALUE
389 console_set_cooked(VALUE io)
390 {
391 conmode t;
392 rb_io_t *fptr;
393 int fd;
394
395 GetOpenFile(io, fptr);
396 fd = GetReadFD(fptr);
397 if (!getattr(fd, &t)) rb_sys_fail(0);
398 set_cookedmode(&t, NULL);
399 if (!setattr(fd, &t)) rb_sys_fail(0);
400 return io;
401 }
402
403 static VALUE
404 getc_call(VALUE io)
405 {
406 return rb_funcall2(io, id_getc, 0, 0);
407 }
408
409 /*
410 * call-seq:
411 * io.getch(min: nil, time: nil) -> char
412 *
413 * Reads and returns a character in raw mode.
414 *
415 * You must require 'io/console' to use this method.
416 */
417 static VALUE
418 console_getch(int argc, VALUE *argv, VALUE io)
419 {
420 rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
421 return ttymode(io, getc_call, set_rawmode, optp);
422 }
423
424 /*
425 * call-seq:
426 * io.noecho {|io| }
427 *
428 * Yields +self+ with disabling echo back.
429 *
430 * STDIN.noecho(&:gets)
431 *
432 * will read and return a line without echo back.
433 *
434 * You must require 'io/console' to use this method.
435 */
436 static VALUE
437 console_noecho(VALUE io)
438 {
439 return ttymode(io, rb_yield, set_noecho, NULL);
440 }
441
442 /*
443 * call-seq:
444 * io.echo = flag
445 *
446 * Enables/disables echo back.
447 * On some platforms, all combinations of this flags and raw/cooked
448 * mode may not be valid.
449 *
450 * You must require 'io/console' to use this method.
451 */
452 static VALUE
453 console_set_echo(VALUE io, VALUE f)
454 {
455 conmode t;
456 rb_io_t *fptr;
457 int fd;
458
459 GetOpenFile(io, fptr);
460 fd = GetReadFD(fptr);
461 if (!getattr(fd, &t)) rb_sys_fail(0);
462 if (RTEST(f))
463 set_echo(&t, NULL);
464 else
465 set_noecho(&t, NULL);
466 if (!setattr(fd, &t)) rb_sys_fail(0);
467 return io;
468 }
469
470 /*
471 * call-seq:
472 * io.echo? -> true or false
473 *
474 * Returns +true+ if echo back is enabled.
475 *
476 * You must require 'io/console' to use this method.
477 */
478 static VALUE
479 console_echo_p(VALUE io)
480 {
481 conmode t;
482 rb_io_t *fptr;
483 int fd;
484
485 GetOpenFile(io, fptr);
486 fd = GetReadFD(fptr);
487 if (!getattr(fd, &t)) rb_sys_fail(0);
488 return echo_p(&t) ? Qtrue : Qfalse;
489 }
490
491 #if defined TIOCGWINSZ
492 typedef struct winsize rb_console_size_t;
493 #define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
494 #define setwinsize(fd, buf) (ioctl((fd), TIOCSWINSZ, (buf)) == 0)
495 #define winsize_row(buf) (buf)->ws_row
496 #define winsize_col(buf) (buf)->ws_col
497 #elif defined _WIN32
498 typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
499 #define getwinsize(fd, buf) ( \
500 GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), (buf)) || \
501 SET_LAST_ERROR)
502 #define winsize_row(buf) ((buf)->srWindow.Bottom - (buf)->srWindow.Top + 1)
503 #define winsize_col(buf) (buf)->dwSize.X
504 #endif
505
506 #if defined TIOCGWINSZ || defined _WIN32
507 #define USE_CONSOLE_GETSIZE 1
508 #endif
509
510 #ifdef USE_CONSOLE_GETSIZE
511 /*
512 * call-seq:
513 * io.winsize -> [rows, columns]
514 *
515 * Returns console size.
516 *
517 * You must require 'io/console' to use this method.
518 */
519 static VALUE
520 console_winsize(VALUE io)
521 {
522 rb_io_t *fptr;
523 int fd;
524 rb_console_size_t ws;
525
526 GetOpenFile(io, fptr);
527 fd = GetWriteFD(fptr);
528 if (!getwinsize(fd, &ws)) rb_sys_fail(0);
529 return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
530 }
531
532 /*
533 * call-seq:
534 * io.winsize = [rows, columns]
535 *
536 * Tries to set console size. The effect depends on the platform and
537 * the running environment.
538 *
539 * You must require 'io/console' to use this method.
540 */
541 static VALUE
542 console_set_winsize(VALUE io, VALUE size)
543 {
544 rb_io_t *fptr;
545 rb_console_size_t ws;
546 #if defined _WIN32
547 HANDLE wh;
548 int newrow, newcol;
549 #endif
550 VALUE row, col, xpixel, ypixel;
551 #if defined TIOCSWINSZ
552 int fd;
553 #endif
554
555 GetOpenFile(io, fptr);
556 size = rb_Array(size);
557 rb_scan_args((int)RARRAY_LEN(size), RARRAY_PTR(size), "22",
558 &row, &col, &xpixel, &ypixel);
559 #if defined TIOCSWINSZ
560 fd = GetWriteFD(fptr);
561 ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
562 #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
563 SET(row);
564 SET(col);
565 SET(xpixel);
566 SET(ypixel);
567 #undef SET
568 if (!setwinsize(fd, &ws)) rb_sys_fail(0);
569 #elif defined _WIN32
570 wh = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr));
571 newrow = (SHORT)NUM2UINT(row);
572 newcol = (SHORT)NUM2UINT(col);
573 if (!getwinsize(GetReadFD(fptr), &ws)) {
574 rb_sys_fail("GetConsoleScreenBufferInfo");
575 }
576 if ((ws.dwSize.X < newcol && (ws.dwSize.X = newcol, 1)) ||
577 (ws.dwSize.Y < newrow && (ws.dwSize.Y = newrow, 1))) {
578 if (!(SetConsoleScreenBufferSize(wh, ws.dwSize) || SET_LAST_ERROR)) {
579 rb_sys_fail("SetConsoleScreenBufferInfo");
580 }
581 }
582 ws.srWindow.Left = 0;
583 ws.srWindow.Top = 0;
584 ws.srWindow.Right = newcol;
585 ws.srWindow.Bottom = newrow;
586 if (!(SetConsoleWindowInfo(wh, FALSE, &ws.srWindow) || SET_LAST_ERROR)) {
587 rb_sys_fail("SetConsoleWindowInfo");
588 }
589 #endif
590 return io;
591 }
592 #endif
593
594 /*
595 * call-seq:
596 * io.iflush
597 *
598 * Flushes input buffer in kernel.
599 *
600 * You must require 'io/console' to use this method.
601 */
602 static VALUE
603 console_iflush(VALUE io)
604 {
605 rb_io_t *fptr;
606 int fd;
607
608 GetOpenFile(io, fptr);
609 fd = GetReadFD(fptr);
610 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
611 if (tcflush(fd, TCIFLUSH)) rb_sys_fail(0);
612 #endif
613 (void)fd;
614 return io;
615 }
616
617 /*
618 * call-seq:
619 * io.oflush
620 *
621 * Flushes output buffer in kernel.
622 *
623 * You must require 'io/console' to use this method.
624 */
625 static VALUE
626 console_oflush(VALUE io)
627 {
628 rb_io_t *fptr;
629 int fd;
630
631 GetOpenFile(io, fptr);
632 fd = GetWriteFD(fptr);
633 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
634 if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0);
635 #endif
636 (void)fd;
637 return io;
638 }
639
640 /*
641 * call-seq:
642 * io.ioflush
643 *
644 * Flushes input and output buffers in kernel.
645 *
646 * You must require 'io/console' to use this method.
647 */
648 static VALUE
649 console_ioflush(VALUE io)
650 {
651 rb_io_t *fptr;
652 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
653 int fd1, fd2;
654 #endif
655
656 GetOpenFile(io, fptr);
657 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
658 fd1 = GetReadFD(fptr);
659 fd2 = GetWriteFD(fptr);
660 if (fd2 != -1 && fd1 != fd2) {
661 if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0);
662 if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0);
663 }
664 else {
665 if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0);
666 }
667 #endif
668 return io;
669 }
670
671 /*
672 * call-seq:
673 * IO.console -> #<File:/dev/tty>
674 *
675 * Returns an File instance opened console.
676 *
677 * You must require 'io/console' to use this method.
678 */
679 static VALUE
680 console_dev(VALUE klass)
681 {
682 VALUE con = 0;
683 rb_io_t *fptr;
684
685 if (klass == rb_cIO) klass = rb_cFile;
686 if (rb_const_defined(klass, id_console)) {
687 con = rb_const_get(klass, id_console);
688 if (RB_TYPE_P(con, T_FILE)) {
689 if ((fptr = RFILE(con)->fptr) && GetReadFD(fptr) != -1)
690 return con;
691 }
692 rb_mod_remove_const(klass, ID2SYM(id_console));
693 }
694 {
695 VALUE args[2];
696 #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
697 # define CONSOLE_DEVICE "/dev/tty"
698 #elif defined _WIN32
699 # define CONSOLE_DEVICE "con$"
700 # define CONSOLE_DEVICE_FOR_READING "conin$"
701 # define CONSOLE_DEVICE_FOR_WRITING "conout$"
702 #endif
703 #ifndef CONSOLE_DEVICE_FOR_READING
704 # define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
705 #endif
706 #ifdef CONSOLE_DEVICE_FOR_WRITING
707 VALUE out;
708 rb_io_t *ofptr;
709 #endif
710 int fd;
711
712 #ifdef CONSOLE_DEVICE_FOR_WRITING
713 fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
714 if (fd < 0) return Qnil;
715 rb_update_max_fd(fd);
716 args[1] = INT2FIX(O_WRONLY);
717 args[0] = INT2NUM(fd);
718 out = rb_class_new_instance(2, args, klass);
719 #endif
720 fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
721 if (fd < 0) {
722 #ifdef CONSOLE_DEVICE_FOR_WRITING
723 rb_io_close(out);
724 #endif
725 return Qnil;
726 }
727 rb_update_max_fd(fd);
728 args[1] = INT2FIX(O_RDWR);
729 args[0] = INT2NUM(fd);
730 con = rb_class_new_instance(2, args, klass);
731 GetOpenFile(con, fptr);
732 #ifdef HAVE_RUBY_IO_H
733 fptr->pathv = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
734 #else
735 fptr->path = ruby_strdup(CONSOLE_DEVICE);
736 #endif
737 #ifdef CONSOLE_DEVICE_FOR_WRITING
738 GetOpenFile(out, ofptr);
739 # ifdef HAVE_RB_IO_GET_WRITE_IO
740 ofptr->pathv = fptr->pathv;
741 fptr->tied_io_for_writing = out;
742 # else
743 fptr->f2 = ofptr->f;
744 ofptr->f = 0;
745 # endif
746 ofptr->mode |= FMODE_SYNC;
747 #endif
748 fptr->mode |= FMODE_SYNC;
749 rb_const_set(klass, id_console, con);
750 }
751 return con;
752 }
753
754 /*
755 * call-seq:
756 * io.getch(min: nil, time: nil) -> char
757 *
758 * See IO#getch.
759 */
760 static VALUE
761 io_getch(int argc, VALUE *argv, VALUE io)
762 {
763 return rb_funcall2(io, rb_intern("getc"), argc, argv);
764 }
765
766 /*
767 * IO console methods
768 */
769 void
770 Init_console(void)
771 {
772 id_getc = rb_intern("getc");
773 id_console = rb_intern("console");
774 InitVM(console);
775 }
776
777 void
778 InitVM_console(void)
779 {
780 rb_define_method(rb_cIO, "raw", console_raw, -1);
781 rb_define_method(rb_cIO, "raw!", console_set_raw, -1);
782 rb_define_method(rb_cIO, "cooked", console_cooked, 0);
783 rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0);
784 rb_define_method(rb_cIO, "getch", console_getch, -1);
785 rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
786 rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
787 rb_define_method(rb_cIO, "noecho", console_noecho, 0);
788 rb_define_method(rb_cIO, "winsize", console_winsize, 0);
789 rb_define_method(rb_cIO, "winsize=", console_set_winsize, 1);
790 rb_define_method(rb_cIO, "iflush", console_iflush, 0);
791 rb_define_method(rb_cIO, "oflush", console_oflush, 0);
792 rb_define_method(rb_cIO, "ioflush", console_ioflush, 0);
793 rb_define_singleton_method(rb_cIO, "console", console_dev, 0);
794 {
795 VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
796 rb_define_method(mReadable, "getch", io_getch, -1);
797 }
798 }
get_write_fd
static int get_write_fd(const rb_io_t *fptr)
Definition: console.c:245
SET
#define SET(a, b, c, d, k, s, Ti)
rawmode_arg_t::vmin
int vmin
Definition: console.c:101
GetReadFD
#define GetReadFD(fptr)
Definition: console.c:238
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
FALSE
#define FALSE
Definition: nkf.h:174
rawmode_arg_t
Definition: console.c:100
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1288
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:183
FD_PER_IO
#define FD_PER_IO
Definition: console.c:256
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
Init_console
void Init_console(void)
Definition: console.c:770
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:631
rawmode_opt
static rawmode_arg_t * rawmode_opt(int argc, VALUE *argv, rawmode_arg_t *opts)
Definition: console.c:106
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
set_echo
static void set_echo(conmode *t, void *arg)
Definition: console.c:202
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:228
InitVM
#define InitVM(ext)
Definition: ruby.h:1789
set_cookedmode
static void set_cookedmode(conmode *t, void *arg)
Definition: console.c:175
rb_io_t
struct rb_io_t rb_io_t
Qtrue
#define Qtrue
Definition: ruby.h:426
rb_io_t
Definition: io.h:61
ttymode
static VALUE ttymode(VALUE io, VALUE(*func)(VALUE), void(*setter)(conmode *, void *), void *arg)
Definition: console.c:259
ruby.h
console_getch
static VALUE console_getch(int argc, VALUE *argv, VALUE io)
Definition: console.c:418
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:984
rb_cFile
VALUE rb_cFile
Definition: file.c:139
GetWriteFD
#define GetWriteFD(fptr)
Definition: console.c:253
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
echo_p
static int echo_p(conmode *t)
Definition: console.c:214
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
id_getc
static ID id_getc
Definition: console.c:98
T_HASH
#define T_HASH
Definition: ruby.h:485
rb_const_defined
int rb_const_defined(VALUE, ID)
Definition: variable.c:2124
id_console
static ID id_console
Definition: console.c:98
RFILE
#define RFILE(obj)
Definition: ruby.h:1129
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:118
rubyio.h
io.h
InitVM_console
void InitVM_console(void)
Definition: console.c:778
rb_io_t::mode
int mode
Definition: io.h:64
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
rb_Array
VALUE rb_Array(VALUE)
Definition: object.c:3014
console_ioflush
static VALUE console_ioflush(VALUE io)
Definition: console.c:649
rb_class_new_instance
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1855
DWORD
IUnknown DWORD
Definition: win32ole.c:149
CONSOLE_DEVICE_FOR_READING
#define CONSOLE_DEVICE_FOR_READING
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:457
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
rb_io_t::fd
int fd
Definition: io.h:62
unistd.h
console_echo_p
static VALUE console_echo_p(VALUE io)
Definition: console.c:479
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
SET_LAST_ERROR
#define SET_LAST_ERROR
Definition: console.c:91
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
console_set_echo
static VALUE console_set_echo(VALUE io, VALUE f)
Definition: console.c:453
console_set_cooked
static VALUE console_set_cooked(VALUE io)
Definition: console.c:389
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
rb_cIO
RUBY_EXTERN VALUE rb_cIO
Definition: ruby.h:1569
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
errno
int errno
getc_call
static VALUE getc_call(VALUE io)
Definition: console.c:404
rawmode_arg_t::vtime
int vtime
Definition: console.c:102
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:588
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
ID
unsigned long ID
Definition: ruby.h:89
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:72
Qnil
#define Qnil
Definition: ruby.h:427
rb_const_set
void rb_const_set(VALUE, ID, VALUE)
Definition: variable.c:2160
set_ttymode
static int set_ttymode(int fd, conmode *t, void(*setter)(conmode *, void *), void *arg)
Definition: console.c:226
rb_io_close
VALUE rb_io_close(VALUE)
Definition: io.c:4292
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
result
static VALUE result
Definition: nkf.c:40
console_cooked
static VALUE console_cooked(VALUE io)
Definition: console.c:373
console_noecho
static VALUE console_noecho(VALUE io)
Definition: console.c:437
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
rb_jump_tag
void rb_jump_tag(int tag)
Definition: eval.c:706
console_raw
static VALUE console_raw(int argc, VALUE *argv, VALUE io)
Definition: console.c:328
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:766
size
int size
Definition: encoding.c:49
f
#define f
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:697
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:907
rb_funcall3
#define rb_funcall3
Definition: ruby.h:1457
rb_io_t::pathv
VALUE pathv
Definition: io.h:67
RTEST
#define RTEST(v)
Definition: ruby.h:437
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:1920
T_FILE
#define T_FILE
Definition: ruby.h:488
console_iflush
static VALUE console_iflush(VALUE io)
Definition: console.c:603
console_set_raw
static VALUE console_set_raw(int argc, VALUE *argv, VALUE io)
Definition: console.c:345
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:105
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
console_dev
static VALUE console_dev(VALUE klass)
Definition: console.c:680
rb_intern
#define rb_intern(str)
io_getch
static VALUE io_getch(int argc, VALUE *argv, VALUE io)
Definition: console.c:761
NULL
#define NULL
Definition: _sdbm.c:103
console_oflush
static VALUE console_oflush(VALUE io)
Definition: console.c:626
set_rawmode
static void set_rawmode(conmode *t, void *arg)
Definition: console.c:148
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
set_noecho
static void set_noecho(conmode *t, void *arg)
Definition: console.c:190
argv
char ** argv
Definition: ruby.c:132