mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	retry IO#getpass
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52948 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									dc331ca5c0
								
							
						
					
					
						commit
						8f620b9b17
					
				
					 3 changed files with 102 additions and 4 deletions
				
			
		|  | @ -74,6 +74,9 @@ getattr(int fd, conmode *t) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| static ID id_getc, id_console, id_close, id_min, id_time; | static ID id_getc, id_console, id_close, id_min, id_time; | ||||||
|  | #if ENABLE_IO_GETPASS | ||||||
|  | static ID id_gets; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifndef HAVE_RB_F_SEND | #ifndef HAVE_RB_F_SEND | ||||||
| static ID id___send__; | static ID id___send__; | ||||||
|  | @ -845,6 +848,80 @@ io_getch(int argc, VALUE *argv, VALUE io) | ||||||
|     return rb_funcall2(io, id_getc, argc, argv); |     return rb_funcall2(io, id_getc, argc, argv); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if ENABLE_IO_GETPASS | ||||||
|  | static VALUE | ||||||
|  | puts_call(VALUE io) | ||||||
|  | { | ||||||
|  |     return rb_io_write(io, rb_default_rs); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static VALUE | ||||||
|  | getpass_call(VALUE io) | ||||||
|  | { | ||||||
|  |     return ttymode(io, rb_io_gets, set_noecho, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | prompt(int argc, VALUE *argv, VALUE io) | ||||||
|  | { | ||||||
|  |     if (argc > 0 && !NIL_P(argv[0])) { | ||||||
|  | 	VALUE str = argv[0]; | ||||||
|  | 	StringValueCStr(str); | ||||||
|  | 	rb_check_safe_obj(str); | ||||||
|  | 	rb_io_write(io, str); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static VALUE | ||||||
|  | str_chomp(VALUE str) | ||||||
|  | { | ||||||
|  |     if (!NIL_P(str)) { | ||||||
|  | 	str = rb_funcallv(str, rb_intern("chomp!"), 0, 0); | ||||||
|  |     } | ||||||
|  |     return str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * call-seq: | ||||||
|  |  *   io.getpass(prompt=nil)       -> string | ||||||
|  |  * | ||||||
|  |  * Reads and returns a line without echo back. | ||||||
|  |  * Prints +prompt+ unless it is +nil+. | ||||||
|  |  * | ||||||
|  |  * You must require 'io/console' to use this method. | ||||||
|  |  */ | ||||||
|  | static VALUE | ||||||
|  | console_getpass(int argc, VALUE *argv, VALUE io) | ||||||
|  | { | ||||||
|  |     VALUE str, wio; | ||||||
|  | 
 | ||||||
|  |     rb_check_arity(argc, 0, 1); | ||||||
|  |     wio = rb_io_get_write_io(io); | ||||||
|  |     if (wio == io && io == rb_stdin) wio = rb_stderr; | ||||||
|  |     prompt(argc, argv, wio); | ||||||
|  |     str = rb_ensure(getpass_call, io, puts_call, wio); | ||||||
|  |     return str_chomp(str); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * call-seq: | ||||||
|  |  *   io.getpass(prompt=nil)       -> string | ||||||
|  |  * | ||||||
|  |  * See IO#getpass. | ||||||
|  |  */ | ||||||
|  | static VALUE | ||||||
|  | io_getpass(int argc, VALUE *argv, VALUE io) | ||||||
|  | { | ||||||
|  |     VALUE str; | ||||||
|  | 
 | ||||||
|  |     rb_check_arity(argc, 0, 1); | ||||||
|  |     prompt(argc, argv, io); | ||||||
|  |     str = str_chomp(rb_funcallv(io, id_gets, 0, 0)); | ||||||
|  |     puts_call(io); | ||||||
|  |     return str; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * IO console methods |  * IO console methods | ||||||
|  */ |  */ | ||||||
|  | @ -853,6 +930,9 @@ Init_console(void) | ||||||
| { | { | ||||||
| #undef rb_intern | #undef rb_intern | ||||||
|     id_getc = rb_intern("getc"); |     id_getc = rb_intern("getc"); | ||||||
|  | #if ENABLE_IO_GETPASS | ||||||
|  |     id_gets = rb_intern("gets"); | ||||||
|  | #endif | ||||||
|     id_console = rb_intern("console"); |     id_console = rb_intern("console"); | ||||||
|     id_close = rb_intern("close"); |     id_close = rb_intern("close"); | ||||||
|     id_min = rb_intern("min"); |     id_min = rb_intern("min"); | ||||||
|  | @ -884,9 +964,15 @@ InitVM_console(void) | ||||||
|     rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0); |     rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0); | ||||||
|     rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1); |     rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1); | ||||||
|     rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1); |     rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1); | ||||||
|  | #if ENABLE_IO_GETPASS | ||||||
|  |     rb_define_method(rb_cIO, "getpass", console_getpass, -1); | ||||||
|  | #endif | ||||||
|     rb_define_singleton_method(rb_cIO, "console", console_dev, -1); |     rb_define_singleton_method(rb_cIO, "console", console_dev, -1); | ||||||
|     { |     { | ||||||
| 	VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable"); | 	VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable"); | ||||||
| 	rb_define_method(mReadable, "getch", io_getch, -1); | 	rb_define_method(mReadable, "getch", io_getch, -1); | ||||||
|  | #if ENABLE_IO_GETPASS | ||||||
|  | 	rb_define_method(mReadable, "getpass", io_getpass, -1); | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ if ok | ||||||
|   # rb_check_hash_type: 1.9.3 |   # rb_check_hash_type: 1.9.3 | ||||||
|   # rb_io_get_write_io: 1.9.1 |   # rb_io_get_write_io: 1.9.1 | ||||||
|   # rb_cloexec_open: 2.0.0 |   # rb_cloexec_open: 2.0.0 | ||||||
|  |   $defs << "-D""ENABLE_IO_GETPASS=1" | ||||||
|   create_makefile("io/console") {|conf| |   create_makefile("io/console") {|conf| | ||||||
|     conf << "\n""VK_HEADER = #{vk_header}\n" |     conf << "\n""VK_HEADER = #{vk_header}\n" | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -180,6 +180,16 @@ class TestIO_Console < Test::Unit::TestCase | ||||||
|     } |     } | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def test_getpass | ||||||
|  |     skip unless IO.method_defined?("getpass") | ||||||
|  |     run_pty("p IO.console.getpass('> ')") do |r, w| | ||||||
|  |       assert_equal("> ", r.readpartial(10)) | ||||||
|  |       w.print "asdf\n" | ||||||
|  |       assert_equal("\r\n", r.gets) | ||||||
|  |       assert_equal("\"asdf\"", r.gets.chomp) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def test_iflush |   def test_iflush | ||||||
|     helper {|m, s| |     helper {|m, s| | ||||||
|       m.print "a" |       m.print "a" | ||||||
|  | @ -270,17 +280,18 @@ class TestIO_Console < Test::Unit::TestCase | ||||||
|   rescue RuntimeError |   rescue RuntimeError | ||||||
|     skip $! |     skip $! | ||||||
|   else |   else | ||||||
|     result = [] |  | ||||||
|     n.times {result << r.gets.chomp} |  | ||||||
|     Process.wait(pid) |  | ||||||
|     if block_given? |     if block_given? | ||||||
|       yield result |       yield r, w, pid | ||||||
|     else |     else | ||||||
|  |       result = [] | ||||||
|  |       n.times {result << r.gets.chomp} | ||||||
|  |       Process.wait(pid) | ||||||
|       result |       result | ||||||
|     end |     end | ||||||
|   ensure |   ensure | ||||||
|     r.close if r |     r.close if r | ||||||
|     w.close if w |     w.close if w | ||||||
|  |     Process.wait(pid) if pid | ||||||
|   end |   end | ||||||
| end if defined?(PTY) and defined?(IO::console) | end if defined?(PTY) and defined?(IO::console) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 nobu
						nobu