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]]
|
[[package]]
|
||||||
name = "pty_driver"
|
name = "pty_server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dev_driver_rpc",
|
"dev_driver_rpc",
|
||||||
|
48
src/main.rs
48
src/main.rs
@ -1,3 +1,5 @@
|
|||||||
|
mod termios;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -8,10 +10,12 @@ use std::{
|
|||||||
|
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
|
use termios::Termios;
|
||||||
|
|
||||||
struct Pty {
|
struct Pty {
|
||||||
input_buffer: Mutex<Vec<u8>>,
|
input_buffer: Mutex<Vec<u8>>,
|
||||||
output_buffer: Mutex<Vec<u8>>,
|
output_buffer: Mutex<Vec<u8>>,
|
||||||
|
termios: Termios,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pty {
|
impl Pty {
|
||||||
@ -19,6 +23,7 @@ impl Pty {
|
|||||||
Pty {
|
Pty {
|
||||||
input_buffer: Mutex::new(Vec::new()),
|
input_buffer: Mutex::new(Vec::new()),
|
||||||
output_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<(), ()> {
|
fn write_master(&self, data: &[u8]) -> Result<(), ()> {
|
||||||
|
if !self.termios.cflags.cread {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
let mut input_buffer = self.input_buffer.lock();
|
let mut input_buffer = self.input_buffer.lock();
|
||||||
let mut output_buffer = self.output_buffer.lock();
|
let mut output_buffer = self.output_buffer.lock();
|
||||||
for &byte in data {
|
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);
|
output_buffer.push(byte);
|
||||||
if byte == 8 {
|
}
|
||||||
if input_buffer.last() != Some(&b'\n') {
|
if input_buffer.last() != Some(&b'\n') {
|
||||||
input_buffer.pop();
|
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 {
|
} else {
|
||||||
input_buffer.push(byte);
|
input_buffer.push(byte);
|
||||||
|
if self.termios.lflags.echo || (byte == b'\n' && self.termios.lflags.echonl) {
|
||||||
|
output_buffer.push(byte);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -60,7 +90,19 @@ impl Pty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_slave(&self, data: &[u8]) -> Result<(), ()> {
|
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(())
|
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