Add termios struct for flags (default taken from stty sane/cooked)
This commit is contained in:
parent
e0b403ef7a
commit
e5144a8e6e
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -183,7 +183,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pty_driver"
|
||||
name = "pty_server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dev_driver_rpc",
|
||||
|
50
src/main.rs
50
src/main.rs
@ -1,3 +1,5 @@
|
||||
mod termios;
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
@ -8,10 +10,12 @@ use std::{
|
||||
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use slab::Slab;
|
||||
use termios::Termios;
|
||||
|
||||
struct Pty {
|
||||
input_buffer: Mutex<Vec<u8>>,
|
||||
output_buffer: Mutex<Vec<u8>>,
|
||||
termios: Termios,
|
||||
}
|
||||
|
||||
impl Pty {
|
||||
@ -19,6 +23,7 @@ impl Pty {
|
||||
Pty {
|
||||
input_buffer: Mutex::new(Vec::new()),
|
||||
output_buffer: Mutex::new(Vec::new()),
|
||||
termios: Termios::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,16 +36,41 @@ impl Pty {
|
||||
}
|
||||
|
||||
fn write_master(&self, data: &[u8]) -> Result<(), ()> {
|
||||
if !self.termios.cflags.cread {
|
||||
return Ok(())
|
||||
}
|
||||
let mut input_buffer = self.input_buffer.lock();
|
||||
let mut output_buffer = self.output_buffer.lock();
|
||||
for &byte in data {
|
||||
output_buffer.push(byte);
|
||||
if byte == 8 {
|
||||
for &(mut byte) in data {
|
||||
if self.termios.iflags.istrip {
|
||||
byte &= 0x7F;
|
||||
}
|
||||
if byte == b'\r' && self.termios.iflags.igncr {
|
||||
continue;
|
||||
} else if byte == b'\r' && self.termios.iflags.icrnl {
|
||||
byte = b'\n';
|
||||
} else if byte == b'\n' && self.termios.iflags.inlcr {
|
||||
byte = b'\r';
|
||||
}
|
||||
if byte as char == self.termios.verase && self.termios.lflags.icanon {
|
||||
if self.termios.lflags.echoe {
|
||||
output_buffer.push(byte);
|
||||
}
|
||||
if input_buffer.last() != Some(&b'\n') {
|
||||
input_buffer.pop();
|
||||
}
|
||||
} else if byte as char == self.termios.vkill && self.termios.lflags.icanon {
|
||||
while input_buffer.last().is_some() && input_buffer.last() != Some(&b'\n') {
|
||||
if self.termios.lflags.echok {
|
||||
output_buffer.push(8);
|
||||
}
|
||||
input_buffer.pop();
|
||||
}
|
||||
} else {
|
||||
input_buffer.push(byte);
|
||||
if self.termios.lflags.echo || (byte == b'\n' && self.termios.lflags.echonl) {
|
||||
output_buffer.push(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -60,7 +90,19 @@ impl Pty {
|
||||
}
|
||||
|
||||
fn write_slave(&self, data: &[u8]) -> Result<(), ()> {
|
||||
self.output_buffer.lock().extend(data);
|
||||
let mut output_buffer = self.output_buffer.lock();
|
||||
for &byte in data {
|
||||
if self.termios.oflags.opost {
|
||||
if byte == b'\n' && self.termios.oflags.onlcr {
|
||||
output_buffer.push(b'\r');
|
||||
output_buffer.push(b'\n');
|
||||
} else if byte == b'\r' && self.termios.oflags.ocrnl {
|
||||
output_buffer.push(b'\n');
|
||||
} else {
|
||||
output_buffer.push(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
212
src/termios.rs
Normal file
212
src/termios.rs
Normal file
@ -0,0 +1,212 @@
|
||||
#[allow(unused)]
|
||||
pub struct Iflags {
|
||||
pub brkint: bool,
|
||||
pub icrnl: bool,
|
||||
pub ignbrk: bool,
|
||||
pub igncr: bool,
|
||||
pub ignpar: bool,
|
||||
pub inlcr: bool,
|
||||
pub inpck: bool,
|
||||
pub istrip: bool,
|
||||
pub ixany: bool,
|
||||
pub ixoff: bool,
|
||||
pub ixon: bool,
|
||||
pub parmark: bool,
|
||||
}
|
||||
|
||||
impl Default for Iflags {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
brkint: false,
|
||||
icrnl: true,
|
||||
ignbrk: false,
|
||||
igncr: false,
|
||||
ignpar: true,
|
||||
inlcr: false,
|
||||
inpck: true,
|
||||
istrip: false,
|
||||
ixany: false,
|
||||
ixoff: false,
|
||||
ixon: false,
|
||||
parmark: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct Oflags {
|
||||
pub opost: bool,
|
||||
pub onlcr: bool,
|
||||
pub ocrnl: bool,
|
||||
pub onocr: bool,
|
||||
pub onlret: bool,
|
||||
pub ofdel: bool,
|
||||
pub nldly: NlDelay,
|
||||
pub crdly: CrDelay,
|
||||
pub tabdly: TabDelay,
|
||||
pub bsdly: BsDelay,
|
||||
pub vtdly: VtDelay,
|
||||
pub ffdly: FfDelay,
|
||||
}
|
||||
|
||||
impl Default for Oflags {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
opost: true,
|
||||
onlcr: true,
|
||||
ocrnl: false,
|
||||
onocr: false,
|
||||
onlret: false,
|
||||
ofdel: false,
|
||||
nldly: NlDelay::Nl0,
|
||||
crdly: CrDelay::Cr0,
|
||||
tabdly: TabDelay::Tab0,
|
||||
bsdly: BsDelay::Bs0,
|
||||
vtdly: VtDelay::Vt0,
|
||||
ffdly: FfDelay::Ff0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum NlDelay {
|
||||
Nl0,
|
||||
Nl1,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum CrDelay {
|
||||
Cr0,
|
||||
Cr1,
|
||||
Cr2,
|
||||
Cr3,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum TabDelay {
|
||||
Tab0,
|
||||
Tab1,
|
||||
Tab2,
|
||||
Tab3,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum BsDelay {
|
||||
Bs0,
|
||||
Bs1,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum VtDelay {
|
||||
Vt0,
|
||||
Vt1,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum FfDelay {
|
||||
Ff0,
|
||||
Ff1,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct Cflags {
|
||||
pub csize: CharSize,
|
||||
pub cstopb: bool,
|
||||
pub cread: bool,
|
||||
pub parenb: bool,
|
||||
pub parodd: bool,
|
||||
pub hupcl: bool,
|
||||
pub clocal: bool,
|
||||
}
|
||||
|
||||
impl Default for Cflags {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
csize: CharSize::Cs8,
|
||||
cstopb: false,
|
||||
cread: true,
|
||||
parenb: false,
|
||||
parodd: false,
|
||||
hupcl: true,
|
||||
clocal: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub enum CharSize {
|
||||
Cs5,
|
||||
Cs6,
|
||||
Cs7,
|
||||
Cs8,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct Lflags {
|
||||
pub echo: bool,
|
||||
pub echoe: bool,
|
||||
pub echok: bool,
|
||||
pub echonl: bool,
|
||||
pub icanon: bool,
|
||||
pub iexten: bool,
|
||||
pub isig: bool,
|
||||
pub noflsh: bool,
|
||||
pub tostop: bool,
|
||||
}
|
||||
|
||||
impl Default for Lflags {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
echo: true,
|
||||
echoe: true,
|
||||
echok: true,
|
||||
echonl: false,
|
||||
icanon: true,
|
||||
iexten: true,
|
||||
isig: true,
|
||||
noflsh: false,
|
||||
tostop: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct Termios {
|
||||
pub iflags: Iflags,
|
||||
pub oflags: Oflags,
|
||||
pub cflags: Cflags,
|
||||
pub lflags: Lflags,
|
||||
pub veof: char,
|
||||
pub veol: char,
|
||||
pub verase: char,
|
||||
pub vintr: char,
|
||||
pub vkill: char,
|
||||
pub vmin: u32,
|
||||
pub vquit: char,
|
||||
pub vstart: char,
|
||||
pub vstop: char,
|
||||
pub vsusp: char,
|
||||
pub vtime: u32,
|
||||
}
|
||||
|
||||
impl Default for Termios {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
iflags: Iflags::default(),
|
||||
oflags: Oflags::default(),
|
||||
cflags: Cflags::default(),
|
||||
lflags: Lflags::default(),
|
||||
veof: '\u{4}', //ctrl-D (EOT)
|
||||
veol: '\n',
|
||||
verase: '\u{8}', //ctrl-H (BS)
|
||||
vintr: '\u{3}', //ctrl-C (ETX)
|
||||
vkill: '\u{15}', //ctrl-U (NAK)
|
||||
vmin: 0,
|
||||
vquit: '\u{1C}', //ctrl-\
|
||||
vstart: '\u{11}', // ctrl-S (XONN)
|
||||
vstop: '\u{13}', // ctrl-Q (XOFF)
|
||||
vsusp: '\u{1A}', // ctrl-Z (SUB)
|
||||
vtime: 0,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user