getsがechoするようになった(readlineと同じような動作)のはいつからだろう?(追記:誤解でした。常にgetsはechoしていたようです)
あるプログラムで、パスワードを入力させようとしていて、ふと気づいたのだが、Ruby(1.8.x)でgetsを使うと、入力がecho backされてしまうので、かなり気持ち悪い。
すげー誤解している可能性も高いのだが、昔はそうじゃなかった気がする。でも今のRuby1.8.xのgetsって、Linuxの環境では入力をecho backするようなのだけど、それはいつからなのだろう?というのは、Ruby-listのパスワードのようなものを readline しようと思っています。のスレッドなどを読むと、1999年時点では、readlineは通常echoして、getsはechoしてないようなのだが。。。
(追記:誤解でした。1997年のMLの記事を読んでいて、getsもstty -echoが必要だという記述を発見。で、以前はgetpass(3)を呼ぶ拡張モジュールなんていうのもあったらしい。というわけで、以下はかなり徒労 orz..)
Re: echo しない readlineにあるように、
system "stty -echo" str = gets system "stty echo"
とするのだろうか?確かにこれは動作する(CentOS4.4 : ruby 1.8.1 + kernel 2.6.9とか)。
しかし、getsを使うということは標準入力につながるのだから、コマンドの出力をパイプしたものやファイルをリダイレクトしたものが標準入力につながっていると、こんなことになる。
$ cat t.rb system "stty -echo" str = gets system "stty echo" p str $ ruby t.rb "aaaa\n" (←入力したデータを表示。改行がついている) $ ruby t.rb t.rb "system \"stty -echo\"\n" $ cat t.rb | ruby t.rb stty: 標準入力: 無効な引数です stty: 標準入力: 無効な引数です "system \"stty -echo\"\n" $ ruby t.rb < t.rb stty: 標準入力: デバイスに対する不適切なioctlです stty: 標準入力: デバイスに対する不適切なioctlです "system \"stty -echo\"\n"
これが、引用先のもともとの例であるようにreadlineを使ったでも、パイプやリダイレクトでは同様のメッセージが表示される。
$ cat t.rb require "readline" system "stty -echo" str = Readline::readline("") system "stty echo" p str $ ruby t.rb "aaa" (←入力したデータを表示。改行はついていない) $ ruby t.rb t.rb "da" (←入力待ちになるので、入力したデータを表示) $ cat t.rb | ruby t.rb stty: 標準入力: 無効な引数です stty: 標準入力: 無効な引数です "require \"readline\"" $ ruby t.rb < t.rb stty: 標準入力: デバイスに対する不適切なioctlです stty: 標準入力: デバイスに対する不適切なioctlです "require \"readline\""
取り込んだデータに改行がつくか付かないかは別として、唯一の違いは、
$ ruby t.rb t.rb
とした場合で、この場合、getsならば、引数で指定されたファイルの1行目が表示されるが、現状のreadlineでは、コマンドラインの入力待ちになる。
getsだと、入力されたパスワードから、余分な改行をchopする手間(というほどではないけど)があるので、readlineを使うかなぁ。
ところで、Windowsだとどうするんだ?sttyなんて無いけど。fcntlなのか?