2017-05-04 5 views
0

を標準入力には、Ctrl-Cを送信することによって、プロセスにSIGINTを送る:すなわちプロセスを開始し、標準入力にデータを送信するとstdoutからの読み取り経由で相互作用。例えば。 stdinにいくつかの行を送って、ctrl-cctrl-\を含めて、シグナルをプロセスに送信する必要があります。私は、例えばに入力を送信することができるよstd::process::Commannd使用私はいくつかの自動テスト用の端子を模倣する方法を探しています

catと私はまた、標準出力にその出力を見ているが、(I understand that is 3として)ctrl-cを送信することはシェルに送られSIGINTが発生することはありません。例えば。このプログラムは終了する必要があります。

use std::process::{Command, Stdio}; 
use std::io::Write; 

fn main() { 
    let mut child = Command::new("sh") 
     .arg("-c").arg("-i").arg("cat") 
     .stdin(Stdio::piped()) 
     .spawn().unwrap(); 
    let mut stdin = child.stdin.take().unwrap(); 
    stdin.write(&[3]).expect("cannot send ctrl-c"); 
    child.wait(); 
} 

私は問題がctrl-cを送信すると、一部のttyを必要としていることである疑いがあるとsh -iを経由して、それが唯一の「対話モード」であります。

私は完全に本格的に行く必要がありますか? termionまたはncurses

更新:私は元の質問にシェルと端末を混乱。私は今これをクリアした。またsshshであったはずです。

+1

Ctrl-Cを押すと、それらのキーを押してもアプリケーションに決して送られません。それらは端末によって処理され、端末はSIGINTをプロセスに送信することでそれに応答します。 SIGINTをプロセスに送信したいとします。 – sepp2k

+0

https://stackoverflow.com/questions/6108953/how-does-ctrl-c-terminate-a-child-process –

+0

@ sepp2k質問ありがとうございます。私はシェルがctrl-cをSIGINTに変換することを知っていましたが、何とかこのビットを質問に追加するのを忘れました。質問は今より明確になるはずです。私は '-i'オプションも追加しましたが、これは対話モードでshを実行する必要がありますが、それでも動作しません。 – hansaplast

答えて

0

多くの研究の後、私は自分自身でptyフォークを行うことはそれほど多くの仕事ではないことを理解しました。 pty-rsがありますが、バグがあり、維持されていないようです。

[dependencies] 
nix = {git = "https://github.com/nix-rust/nix.git"} 

次のコードがttyで猫を実行し、それから/読み込み、書き込み、Ctrlキーを送信します。

次のコードでは、今のためCargo.tomlニーズこれを、crates.ioにまだないpty module of nixを必要とします-C(3):

extern crate nix; 

use std::path::Path; 
use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname}; 
use nix::fcntl::{O_RDWR, open}; 
use nix::sys::stat; 
use nix::unistd::{fork, ForkResult, setsid, dup2}; 
use nix::libc::{STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; 
use std::os::unix::io::{AsRawFd, FromRawFd}; 
use std::io::prelude::*; 
use std::io::{BufReader, LineWriter}; 


fn run() -> std::io::Result<()> { 
    // Open a new PTY master 
    let master_fd = posix_openpt(O_RDWR)?; 

    // Allow a slave to be generated for it 
    grantpt(&master_fd)?; 
    unlockpt(&master_fd)?; 

    // Get the name of the slave 
    let slave_name = ptsname(&master_fd)?; 

    match fork() { 
     Ok(ForkResult::Child) => { 
      setsid()?; // create new session with child as session leader 
      let slave_fd = open(Path::new(&slave_name), O_RDWR, stat::Mode::empty())?; 

      // assign stdin, stdout, stderr to the tty, just like a terminal does 
      dup2(slave_fd, STDIN_FILENO)?; 
      dup2(slave_fd, STDOUT_FILENO)?; 
      dup2(slave_fd, STDERR_FILENO)?; 
      std::process::Command::new("cat").status()?; 
     } 
     Ok(ForkResult::Parent { child: _ }) => { 
      let f = unsafe { std::fs::File::from_raw_fd(master_fd.as_raw_fd()) }; 
      let mut reader = BufReader::new(&f); 
      let mut writer = LineWriter::new(&f); 

      writer.write_all(b"hello world\n")?; 
      let mut s = String::new(); 
      reader.read_line(&mut s)?; // what we just wrote in 
      reader.read_line(&mut s)?; // what cat wrote out 
      writer.write(&[3])?; // send ^C 
      writer.flush()?; 
      let mut buf = [0; 2]; // needs bytewise read as ^C has no newline 
      reader.read(&mut buf)?; 
      s += &String::from_utf8_lossy(&buf).to_string(); 
      println!("{}", s); 
      println!("cat exit code: {:?}", wait::wait()?); // make sure cat really exited 
     } 
     Err(_) => println!("error"), 
    } 
    Ok(()) 
} 

fn main() { 
    run().expect("could not execute command"); 
} 

出力:

hello world 
hello world 
^C 
cat exit code: Signaled(2906, SIGINT, false) 
0

-tオプションTWICEを追加して、疑似tty割り当てを強制してください。私。あなたが仮想端末を持っている場合

klar (16:14) ~>echo foo | ssh [email protected] tty 
not a tty 
klar (16:14) ~>echo foo | ssh -t -t [email protected] tty 
/dev/pts/0 

は、私はあなたがやってみたかったとして、それがSIGINTにそれを変換するべきだと思います。

あなたの簡単な例では、サーバーが終了する必要があり、その場合には、書き込み、後にもちょうど近くSTDINできました。この特定のケースでは、それはよりエレガントで、おそらくより信頼できるでしょう。

+0

しかし、最初に私は 'cat'(または他のコマンド)を' ssh'ではなく使いたいと思っています。 IMO私は本当にttyのフォークが必要です、そうでなければCtrl-Cなどは決して動かないでしょう、下の私の答えを見てください – hansaplast

関連する問題