Ruby  2.1.10p492(2016-04-01revision54464)
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 
99 
100 typedef struct {
101  int vmin;
102  int vtime;
103 } rawmode_arg_t;
104 
105 static rawmode_arg_t *
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
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
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
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
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
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
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
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
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
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
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
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
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
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_const_remove(klass, 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
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
762 {
763  return rb_funcall2(io, rb_intern("getc"), argc, argv);
764 }
765 
766 /*
767  * IO console methods
768  */
769 void
771 {
772  id_getc = rb_intern("getc");
773  id_console = rb_intern("console");
774  InitVM(console);
775 }
776 
777 void
779 {
780  rb_define_method(rb_cIO, "raw", console_raw, -1);
782  rb_define_method(rb_cIO, "cooked", console_cooked, 0);
784  rb_define_method(rb_cIO, "getch", console_getch, -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);
794  {
795  VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
796  rb_define_method(mReadable, "getch", io_getch, -1);
797  }
798 }
#define RB_TYPE_P(obj, type)
static int get_write_fd(const rb_io_t *fptr)
Definition: console.c:245
#define SET(a, b, c, d, k, s, Ti)
RARRAY_PTR(q->result)[0]
#define GetReadFD(fptr)
Definition: console.c:238
rb_funcall2(argv[0], id_yield, argc-1, argv+1)
#define FALSE
Definition: nkf.h:174
#define rb_funcall3
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1857
#define FD_PER_IO
Definition: console.c:256
void Init_console(void)
Definition: console.c:770
static rawmode_arg_t * rawmode_opt(int argc, VALUE *argv, rawmode_arg_t *opts)
Definition: console.c:106
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1646
static void set_echo(conmode *t, void *arg)
Definition: console.c:202
C_block * out
Definition: crypt.c:308
static void set_cookedmode(conmode *t, void *arg)
Definition: console.c:175
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
struct rb_io_t rb_io_t
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
Definition: io.h:61
static VALUE ttymode(VALUE io, VALUE(*func)(VALUE), void(*setter)(conmode *, void *), void *arg)
Definition: console.c:259
static VALUE console_getch(int argc, VALUE *argv, VALUE io)
Definition: console.c:418
int status
Definition: tcltklib.c:2197
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:988
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1070
rb_yield(i)
void rb_update_max_fd(int fd)
Definition: io.c:183
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
#define RFILE(obj)
#define GetWriteFD(fptr)
Definition: console.c:253
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
static int echo_p(conmode *t)
Definition: console.c:214
static ID id_getc
Definition: console.c:98
#define T_HASH
return Qtrue
Definition: tcltklib.c:9618
#define T_FILE
static ID id_console
Definition: console.c:98
r
Definition: bigdecimal.c:1212
#define rb_str_new2
int size
Definition: encoding.c:49
#define InitVM(ext)
#define ID2SYM(x)
#define GetOpenFile(obj, fp)
Definition: io.h:118
void InitVM_console(void)
Definition: console.c:778
int mode
Definition: io.h:64
static VALUE console_ioflush(VALUE io)
Definition: console.c:649
return Qfalse
Definition: tcltklib.c:6790
#define RARRAY_LEN(a)
#define Qnil
Definition: enum.c:67
IUnknown DWORD
Definition: win32ole.c:149
#define CONSOLE_DEVICE_FOR_READING
char * ruby_strdup(const char *)
Definition: util.c:461
unsigned long ID
Definition: ripper.y:89
Check_Type(i, T_ARRAY)
#define INT2FIX(i)
int fd
Definition: io.h:62
static VALUE console_echo_p(VALUE io)
Definition: console.c:479
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:597
#define SET_LAST_ERROR
Definition: console.c:91
VALUE arg
Definition: enum.c:2427
static VALUE console_set_echo(VALUE io, VALUE f)
Definition: console.c:453
static VALUE console_set_cooked(VALUE io)
Definition: console.c:389
VALUE * argv
Definition: tcltklib.c:1969
#define RTEST(v)
int errno
static VALUE getc_call(VALUE io)
Definition: console.c:404
int rb_const_defined(VALUE, ID)
Definition: variable.c:2127
VP_EXPORT void
Definition: bigdecimal.c:5207
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
#define NUM2UINT(x)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:620
VALUE tied_io_for_writing
Definition: io.h:72
void rb_const_set(VALUE, ID, VALUE)
Definition: variable.c:2163
static int set_ttymode(int fd, conmode *t, void(*setter)(conmode *, void *), void *arg)
Definition: console.c:226
int argc
Definition: tcltklib.c:1968
static VALUE console_cooked(VALUE io)
Definition: console.c:373
static VALUE console_noecho(VALUE io)
Definition: console.c:437
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
void rb_jump_tag(int tag)
Definition: eval.c:706
static VALUE console_raw(int argc, VALUE *argv, VALUE io)
Definition: console.c:328
RUBY_EXTERN VALUE rb_cIO
Definition: ripper.y:1577
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:747
RUBY_EXTERN VALUE rb_cFile
Definition: ripper.y:1572
#define f
args[0]
Definition: enum.c:585
VALUE pathv
Definition: io.h:67
VALUE rb_const_remove(VALUE, ID)
Definition: variable.c:1942
klass
Definition: tcltklib.c:3496
#define INT2NUM(x)
static VALUE console_iflush(VALUE io)
Definition: console.c:603
gz io
Definition: zlib.c:2263
static VALUE console_set_raw(int argc, VALUE *argv, VALUE io)
Definition: console.c:345
int t
Definition: ripper.c:14879
#define NUM2INT(x)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:228
#define FMODE_SYNC
Definition: io.h:105
VALUE rb_io_close(VALUE)
Definition: io.c:4315
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:706
VALUE opts
Definition: tcltklib.c:6160
unsigned long VALUE
Definition: ripper.y:88
static VALUE console_dev(VALUE klass)
Definition: console.c:680
#define rb_intern(str)
static VALUE io_getch(int argc, VALUE *argv, VALUE io)
Definition: console.c:761
#define NULL
Definition: _sdbm.c:102
static VALUE console_oflush(VALUE io)
Definition: console.c:626
static void set_rawmode(conmode *t, void *arg)
Definition: console.c:148
volatile VALUE result
Definition: enum.c:1989
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
static void set_noecho(conmode *t, void *arg)
Definition: console.c:190
VALUE rb_Array(VALUE)
Definition: object.c:3038