PTY ライブラリを使用して Ruby でターミナル エミュレータを作成しています。/dev/tty0
キーボードに接続されたデバイスファイルです。私はこのようにシェルを生成しています:
shell = PTY.spawn 'env TERM=ansi COLUMNS=63 LINES=21 sh -i < /dev/tty0'
ほとんどの場合は機能しますが、サブプロセスがシェルで開始されると、shell[0]
そのサブプロセスにキーボード入力が出力されません。例: を"cat\nasdf"
介して送信するshell[1]
と、を介し"cat"
て戻ってきますshell[0]
が、そうで"asdf"
はありません。なぜこれが起こっているのですか? どうすれば修正できますか?
編集:
これが私のコードです。ChumbyScreen
私がこれを書いている組み込みデバイスの画面を制御する外部モジュールです(「Chumby」と呼ばれます)。このwrite
メソッドは、文字を画面に配置します。
require 'pty'
def handle_escape(io)
actions = 'ABCDEFGHJKSTfmnsulh'
str, action = '', nil
loop do
c = io.read(1)
if actions.include? c
action = c
break
else
str += c
end
end
case action
when 'J'
ChumbyScreen.x = 0
end
end
system '[ -e /dev/tty0 ] || mknod /dev/tty0 c 4 0'
shell = PTY.spawn 'env TERM=ansi COLUMNS=63 LINES=21 sh -i < /dev/tty0'
loop do
c = shell[0].read(1)
if c == "\e"
c2 = shell[0].read(1)
if c2 == '['
handle_escape shell[0]
next
else
c += c2
end
end
ChumbyScreen.write c
end
shodanexの答えを読んだ後、私はこれを試しました:
require 'pty'
def handle_escape(io)
actions = 'ABCDEFGHJKSTfmnsulh'
str, action = '', nil
loop do
c = io.read(1)
if actions.include? c
action = c
break
else
str += c
end
end
case action
when 'J'
ChumbyScreen.x = 0
end
end
system '[ -e /dev/tty0 ] || mknod /dev/tty0 c 4 0'
shell = PTY.spawn 'env TERM=ansi COLUMNS=63 LINES=21 sh -i'
Thread.new do
k = open '/dev/tty0', File::RDONLY
loop do
shell[1].write k.read(1)
end
end.priority = 1
loop do
c = shell[0].read(1)
if c == "\e"
c2 = shell[0].read(1)
if c2 == '['
handle_escape shell[0]
next
else
c += c2
end
end
ChumbyScreen.write c
end
動作しますが、Enter キーを押すまで入力した文字が表示されません。何らかの形で行バッファリングする必要があります - どうすればこれを乗り越えられますか? また、Control-C と Control-D は何もしません。eof を送信してプロセスを終了する必要があります。