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 | ||||
| 
 | ||||
| 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 | ||||
| static ID id___send__; | ||||
|  | @ -845,6 +848,80 @@ io_getch(int argc, VALUE *argv, VALUE io) | |||
|     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 | ||||
|  */ | ||||
|  | @ -853,6 +930,9 @@ Init_console(void) | |||
| { | ||||
| #undef rb_intern | ||||
|     id_getc = rb_intern("getc"); | ||||
| #if ENABLE_IO_GETPASS | ||||
|     id_gets = rb_intern("gets"); | ||||
| #endif | ||||
|     id_console = rb_intern("console"); | ||||
|     id_close = rb_intern("close"); | ||||
|     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_set, 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); | ||||
|     { | ||||
| 	VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable"); | ||||
| 	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_io_get_write_io: 1.9.1 | ||||
|   # rb_cloexec_open: 2.0.0 | ||||
|   $defs << "-D""ENABLE_IO_GETPASS=1" | ||||
|   create_makefile("io/console") {|conf| | ||||
|     conf << "\n""VK_HEADER = #{vk_header}\n" | ||||
|   } | ||||
|  |  | |||
|  | @ -180,6 +180,16 @@ class TestIO_Console < Test::Unit::TestCase | |||
|     } | ||||
|   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 | ||||
|     helper {|m, s| | ||||
|       m.print "a" | ||||
|  | @ -269,18 +279,19 @@ class TestIO_Console < Test::Unit::TestCase | |||
|     r, w, pid = PTY.spawn(EnvUtil.rubybin, "-rio/console", "-e", src) | ||||
|   rescue RuntimeError | ||||
|     skip $! | ||||
|   else | ||||
|     if block_given? | ||||
|       yield r, w, pid | ||||
|     else | ||||
|       result = [] | ||||
|       n.times {result << r.gets.chomp} | ||||
|       Process.wait(pid) | ||||
|     if block_given? | ||||
|       yield result | ||||
|     else | ||||
|       result | ||||
|     end | ||||
|   ensure | ||||
|     r.close if r | ||||
|     w.close if w | ||||
|     Process.wait(pid) if pid | ||||
|   end | ||||
| end if defined?(PTY) and defined?(IO::console) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 nobu
						nobu