From: "Mark J. Reed" Date: 2003-12-22T14:31:54+09:00 Subject: Re: FAQ? raw i/o in Ruby --zhXaljGHf11kAtnf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Well, I don't know how useful this is, but here's an extension that wraps the POSIX termios structure. With it, you can enable cbreak mode (character-at-a-time input) in a way that mirrors C usage: require 'termios' t = $stdin.getattr t.lflag &= ~Termios::ICANON $stdin.setattr(0, t) After which, $stdin.getc will return the next key pressed without waiting for a newline, at least on a UNIX system. -Mark --zhXaljGHf11kAtnf Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="termios.c" #include #include VALUE cTermios; VALUE tio_get_c_iflag(VALUE self) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); return INT2NUM(ctio->c_iflag); } VALUE tio_set_c_iflag(VALUE self, VALUE c_iflag) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_iflag = NUM2INT(c_iflag); return c_iflag; } VALUE tio_get_c_ispeed(VALUE self) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); return INT2NUM(ctio->c_ispeed); } VALUE tio_set_c_ispeed(VALUE self, VALUE c_ispeed) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_ispeed = NUM2INT(c_ispeed); return c_ispeed; } VALUE tio_get_c_oflag(VALUE self) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); return INT2NUM(ctio->c_oflag); } VALUE tio_set_c_oflag(VALUE self, VALUE c_oflag) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_oflag = NUM2INT(c_oflag); return c_oflag; } VALUE tio_get_c_ospeed(VALUE self) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); return INT2NUM(ctio->c_ospeed); } VALUE tio_set_c_ospeed(VALUE self, VALUE c_ospeed) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_ospeed = NUM2INT(c_ospeed); return c_ospeed; } VALUE tio_get_c_lflag(VALUE self) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); return INT2NUM(ctio->c_lflag); } VALUE tio_set_c_lflag(VALUE self, VALUE c_lflag) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_lflag = NUM2INT(c_lflag); return c_lflag; } VALUE tio_get_c_line(VALUE self) { struct termios *ctio; char c_line[2]; Data_Get_Struct(self, struct termios, ctio); c_line[0] = ctio->c_line; c_line[1] = '\0'; return rb_str_new2(c_line); } VALUE tio_set_c_line(VALUE self, VALUE c_line) { struct termios *ctio; Data_Get_Struct(self, struct termios, ctio); ctio->c_line = STR2CSTR(c_line)[0]; return c_line; } VALUE tio_get_c_cc(VALUE self) { struct termios *ctio; VALUE rcc = rb_array_new2(NCCS); int i; char ccc[2]; Data_Get_Struct(self, struct termios, ctio); ccc[1] = '\0'; for (i=0; ic_cc[i]; rb_ary_store(rcc, i, rb_str_new2(ccc)); } return rcc; } VALUE tio_set_c_cc(VALUE self, VALUE c_cc) { struct termios *ctio; int i; Data_Get_Struct(self, struct termios, ctio); for (i=0; ic_cc[i] = STR2CSTR(rb_ary_entry(c_cc, i))[0]; } return c_cc; } VALUE rio_tcgetattr(VALUE self) { int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0)); struct termios *ctio = ALLOC(struct termios); if (0 == tcgetattr(fd, ctio)) { return Data_Wrap_Struct(cTermios, 0, free, ctio); } else { FREE(ctio); rb_sys_fail("Could not retrieve attributes"); return Qnil; } } VALUE rio_tcsetattr(VALUE self, VALUE optact, VALUE rtio) { int fd = NUM2INT(rb_funcall(self, rb_intern("fileno"), 0)); struct termios *ctio; Data_Get_Struct(rtio, struct termios, ctio); if (0 == tcsetattr(fd, NUM2INT(optact), ctio)) { return Qtrue; } else { rb_sys_fail("Could not set attributes"); return Qnil; } } void Init_termios() { cTermios = rb_define_class("Termios", rb_cObject); /* new IO methods */ rb_define_method(rb_cIO, "getattr", rio_tcgetattr, 0); rb_define_method(rb_cIO, "setattr", rio_tcsetattr, 2); /* accessor methods for the structure */ rb_define_method(cTermios, "iflag", tio_get_c_iflag, 0); rb_define_method(cTermios, "iflag=", tio_set_c_iflag, 1); rb_define_method(cTermios, "oflag", tio_get_c_oflag, 0); rb_define_method(cTermios, "oflag=", tio_set_c_oflag, 1); rb_define_method(cTermios, "lflag", tio_get_c_lflag, 0); rb_define_method(cTermios, "lflag=", tio_set_c_lflag, 1); rb_define_method(cTermios, "line", tio_get_c_line, 0); rb_define_method(cTermios, "line=", tio_set_c_line, 1); rb_define_method(cTermios, "cc", tio_get_c_cc, 0); rb_define_method(cTermios, "cc=", tio_set_c_cc, 1); rb_define_method(cTermios, "ispeed", tio_get_c_ispeed, 0); rb_define_method(cTermios, "ispeed=", tio_set_c_ispeed, 1); rb_define_method(cTermios, "ospeed", tio_get_c_ospeed, 0); rb_define_method(cTermios, "ospeed=", tio_set_c_ospeed, 1); /* constants */ rb_define_const(cTermios, "NCCS", INT2NUM(NCCS)); rb_define_const(cTermios, "VINTR", INT2NUM(VINTR)); rb_define_const(cTermios, "VQUIT", INT2NUM(VQUIT)); rb_define_const(cTermios, "VERASE", INT2NUM(VERASE)); rb_define_const(cTermios, "VKILL", INT2NUM(VKILL)); rb_define_const(cTermios, "VEOF", INT2NUM(VEOF)); rb_define_const(cTermios, "VTIME", INT2NUM(VTIME)); rb_define_const(cTermios, "VMIN", INT2NUM(VMIN)); rb_define_const(cTermios, "VSWTC", INT2NUM(VSWTC)); rb_define_const(cTermios, "VSTART", INT2NUM(VSTART)); rb_define_const(cTermios, "VSTOP", INT2NUM(VSTOP)); rb_define_const(cTermios, "VSUSP", INT2NUM(VSUSP)); rb_define_const(cTermios, "VEOL", INT2NUM(VEOL)); rb_define_const(cTermios, "VREPRINT", INT2NUM(VREPRINT)); rb_define_const(cTermios, "VDISCARD", INT2NUM(VDISCARD)); rb_define_const(cTermios, "VWERASE", INT2NUM(VWERASE)); rb_define_const(cTermios, "VLNEXT", INT2NUM(VLNEXT)); rb_define_const(cTermios, "VEOL2", INT2NUM(VEOL2)); rb_define_const(cTermios, "IGNBRK", INT2NUM(IGNBRK)); rb_define_const(cTermios, "BRKINT", INT2NUM(BRKINT)); rb_define_const(cTermios, "IGNPAR", INT2NUM(IGNPAR)); rb_define_const(cTermios, "PARMRK", INT2NUM(PARMRK)); rb_define_const(cTermios, "INPCK", INT2NUM(INPCK)); rb_define_const(cTermios, "ISTRIP", INT2NUM(ISTRIP)); rb_define_const(cTermios, "INLCR", INT2NUM(INLCR)); rb_define_const(cTermios, "IGNCR", INT2NUM(IGNCR)); rb_define_const(cTermios, "ICRNL", INT2NUM(ICRNL)); rb_define_const(cTermios, "IUCLC", INT2NUM(IUCLC)); rb_define_const(cTermios, "IXON", INT2NUM(IXON)); rb_define_const(cTermios, "IXANY", INT2NUM(IXANY)); rb_define_const(cTermios, "IXOFF", INT2NUM(IXOFF)); rb_define_const(cTermios, "IMAXBEL", INT2NUM(IMAXBEL)); rb_define_const(cTermios, "OPOST", INT2NUM(OPOST)); rb_define_const(cTermios, "OLCUC", INT2NUM(OLCUC)); rb_define_const(cTermios, "ONLCR", INT2NUM(ONLCR)); rb_define_const(cTermios, "OCRNL", INT2NUM(OCRNL)); rb_define_const(cTermios, "ONOCR", INT2NUM(ONOCR)); rb_define_const(cTermios, "ONLRET", INT2NUM(ONLRET)); rb_define_const(cTermios, "OFILL", INT2NUM(OFILL)); rb_define_const(cTermios, "OFDEL", INT2NUM(OFDEL)); rb_define_const(cTermios, "NLDLY", INT2NUM(NLDLY)); rb_define_const(cTermios, "NL0", INT2NUM( NL0)); rb_define_const(cTermios, "NL1", INT2NUM( NL1)); rb_define_const(cTermios, "CRDLY", INT2NUM(CRDLY)); rb_define_const(cTermios, "CR0", INT2NUM( CR0)); rb_define_const(cTermios, "CR1", INT2NUM( CR1)); rb_define_const(cTermios, "CR2", INT2NUM( CR2)); rb_define_const(cTermios, "CR3", INT2NUM( CR3)); rb_define_const(cTermios, "TABDLY", INT2NUM(TABDLY)); rb_define_const(cTermios, "TAB0", INT2NUM( TAB0)); rb_define_const(cTermios, "TAB1", INT2NUM( TAB1)); rb_define_const(cTermios, "TAB2", INT2NUM( TAB2)); rb_define_const(cTermios, "TAB3", INT2NUM( TAB3)); rb_define_const(cTermios, "BSDLY", INT2NUM(BSDLY)); rb_define_const(cTermios, "BS0", INT2NUM( BS0)); rb_define_const(cTermios, "BS1", INT2NUM( BS1)); rb_define_const(cTermios, "FFDLY", INT2NUM(FFDLY)); rb_define_const(cTermios, "FF0", INT2NUM( FF0)); rb_define_const(cTermios, "FF1", INT2NUM( FF1)); rb_define_const(cTermios, "VTDLY", INT2NUM(VTDLY)); rb_define_const(cTermios, "VT0", INT2NUM( VT0)); rb_define_const(cTermios, "VT1", INT2NUM( VT1)); rb_define_const(cTermios, "XTABS", INT2NUM(XTABS)); rb_define_const(cTermios, "CBAUD", INT2NUM(CBAUD)); rb_define_const(cTermios, "B0", INT2NUM( B0)); rb_define_const(cTermios, "B50", INT2NUM( B50)); rb_define_const(cTermios, "B75", INT2NUM( B75)); rb_define_const(cTermios, "B110", INT2NUM( B110)); rb_define_const(cTermios, "B134", INT2NUM( B134)); rb_define_const(cTermios, "B150", INT2NUM( B150)); rb_define_const(cTermios, "B200", INT2NUM( B200)); rb_define_const(cTermios, "B300", INT2NUM( B300)); rb_define_const(cTermios, "B600", INT2NUM( B600)); rb_define_const(cTermios, "B1200", INT2NUM( B1200)); rb_define_const(cTermios, "B1800", INT2NUM( B1800)); rb_define_const(cTermios, "B2400", INT2NUM( B2400)); rb_define_const(cTermios, "B4800", INT2NUM( B4800)); rb_define_const(cTermios, "B9600", INT2NUM( B9600)); rb_define_const(cTermios, "B19200", INT2NUM( B19200)); rb_define_const(cTermios, "B38400", INT2NUM( B38400)); rb_define_const(cTermios, "EXTA", INT2NUM(EXTA)); rb_define_const(cTermios, "EXTB", INT2NUM(EXTB)); rb_define_const(cTermios, "CSIZE", INT2NUM(CSIZE)); rb_define_const(cTermios, "CS5", INT2NUM( CS5)); rb_define_const(cTermios, "CS6", INT2NUM( CS6)); rb_define_const(cTermios, "CS7", INT2NUM( CS7)); rb_define_const(cTermios, "CS8", INT2NUM( CS8)); rb_define_const(cTermios, "CSTOPB", INT2NUM(CSTOPB)); rb_define_const(cTermios, "CREAD", INT2NUM(CREAD)); rb_define_const(cTermios, "PARENB", INT2NUM(PARENB)); rb_define_const(cTermios, "PARODD", INT2NUM(PARODD)); rb_define_const(cTermios, "HUPCL", INT2NUM(HUPCL)); rb_define_const(cTermios, "CLOCAL", INT2NUM(CLOCAL)); rb_define_const(cTermios, "CBAUDEX", INT2NUM(CBAUDEX)); rb_define_const(cTermios, "B57600", INT2NUM( B57600)); rb_define_const(cTermios, "B115200", INT2NUM( B115200)); rb_define_const(cTermios, "B230400", INT2NUM( B230400)); rb_define_const(cTermios, "B460800", INT2NUM( B460800)); rb_define_const(cTermios, "B500000", INT2NUM( B500000)); rb_define_const(cTermios, "B576000", INT2NUM( B576000)); rb_define_const(cTermios, "B921600", INT2NUM( B921600)); rb_define_const(cTermios, "B1000000", INT2NUM( B1000000)); rb_define_const(cTermios, "B1152000", INT2NUM( B1152000)); rb_define_const(cTermios, "B1500000", INT2NUM( B1500000)); rb_define_const(cTermios, "B2000000", INT2NUM( B2000000)); rb_define_const(cTermios, "B2500000", INT2NUM( B2500000)); rb_define_const(cTermios, "B3000000", INT2NUM( B3000000)); rb_define_const(cTermios, "B3500000", INT2NUM( B3500000)); rb_define_const(cTermios, "B4000000", INT2NUM( B4000000)); rb_define_const(cTermios, "CIBAUD", INT2NUM(CIBAUD)); rb_define_const(cTermios, "CRTSCTS", INT2NUM(CRTSCTS)); rb_define_const(cTermios, "ISIG", INT2NUM(ISIG)); rb_define_const(cTermios, "ICANON", INT2NUM(ICANON)); rb_define_const(cTermios, "XCASE", INT2NUM(XCASE)); rb_define_const(cTermios, "ECHO", INT2NUM(ECHO)); rb_define_const(cTermios, "ECHOE", INT2NUM(ECHOE)); rb_define_const(cTermios, "ECHOK", INT2NUM(ECHOK)); rb_define_const(cTermios, "ECHONL", INT2NUM(ECHONL)); rb_define_const(cTermios, "NOFLSH", INT2NUM(NOFLSH)); rb_define_const(cTermios, "TOSTOP", INT2NUM(TOSTOP)); rb_define_const(cTermios, "ECHOCTL", INT2NUM(ECHOCTL)); rb_define_const(cTermios, "ECHOPRT", INT2NUM(ECHOPRT)); rb_define_const(cTermios, "ECHOKE", INT2NUM(ECHOKE)); rb_define_const(cTermios, "FLUSHO", INT2NUM(FLUSHO)); rb_define_const(cTermios, "PENDIN", INT2NUM(PENDIN)); rb_define_const(cTermios, "IEXTEN", INT2NUM(IEXTEN)); rb_define_const(cTermios, "TCOOFF", INT2NUM(TCOOFF)); rb_define_const(cTermios, "TCOON", INT2NUM(TCOON)); rb_define_const(cTermios, "TCIOFF", INT2NUM(TCIOFF)); rb_define_const(cTermios, "TCION", INT2NUM(TCION)); rb_define_const(cTermios, "TCIFLUSH", INT2NUM(TCIFLUSH)); rb_define_const(cTermios, "TCOFLUSH", INT2NUM(TCOFLUSH)); rb_define_const(cTermios, "TCIOFLUSH", INT2NUM(TCIOFLUSH)); rb_define_const(cTermios, "TCSANOW", INT2NUM(TCSANOW)); rb_define_const(cTermios, "TCSADRAIN", INT2NUM(TCSADRAIN)); rb_define_const(cTermios, "TCSAFLUSH", INT2NUM(TCSAFLUSH)); } --zhXaljGHf11kAtnf Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="extconf.rb" require 'mkmf' create_makefile('termios') --zhXaljGHf11kAtnf--