ctf_pwn/io/stdio/
mod.rs

1mod ncurses_bridge;
2mod shell_bridge;
3
4use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
5pub use ncurses_bridge::*;
6pub use shell_bridge::*;
7use std::io;
8use thiserror::Error;
9
10use crate::io::pipe;
11use tokio::io::{AsyncRead, AsyncWrite};
12use tokio::sync::mpsc;
13
14pub trait TerminalBridge {
15    //TODO: if reader or writer does not have timeout this might get stuck
16    async fn bridge<R: AsyncRead + Send + Unpin, W: AsyncWrite + Send + Unpin>(
17        reader: &mut R,
18        writer: &mut W,
19    );
20}
21
22#[derive(Error, Debug)]
23pub enum TerminalError {
24    #[error("IO error: {0}")]
25    Io(#[from] io::Error),
26
27    #[error("String Send error: {0}")]
28    StringSend(#[from] mpsc::error::SendError<String>),
29
30    #[error("Bytes Send error: {0}")]
31    BytesSend(#[from] mpsc::error::SendError<Vec<u8>>),
32
33    #[error("Recv error: {0}")]
34    Recv(#[from] mpsc::error::TryRecvError),
35
36    #[error("Pipe error: {0}")]
37    Pipe(#[from] pipe::PipeError),
38
39    #[error("format error {0}")]
40    FmtError(#[from] std::fmt::Error),
41
42    #[error("Stop signal")]
43    Terminate,
44}
45
46type TerminalResult<T> = Result<T, TerminalError>;
47
48fn is_ctr_key(key_event: KeyEvent) -> bool {
49    key_event.kind == KeyEventKind::Press && key_event.modifiers == KeyModifiers::CONTROL
50}
51
52pub(crate) fn is_terminate_process(key_event: KeyEvent) -> bool {
53    return is_ctr_key(key_event) && key_event.code == KeyCode::Char('c');
54}
55
56pub(crate) fn is_stop_terminal(key_event: KeyEvent) -> bool {
57    return is_ctr_key(key_event) && key_event.code == KeyCode::Char('d');
58}