Factor out termios and the line discipline into their own crates
This commit is contained in:
parent
84786479c2
commit
142c1d2aab
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -68,6 +68,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-io"
|
name = "embedded-io"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -113,12 +119,28 @@ dependencies = [
|
|||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.158"
|
version = "0.2.158"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "line_discipline"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
@ -193,6 +215,7 @@ dependencies = [
|
|||||||
"dev_driver_rpc",
|
"dev_driver_rpc",
|
||||||
"devfs_rpc",
|
"devfs_rpc",
|
||||||
"file_rpc",
|
"file_rpc",
|
||||||
|
"line_discipline",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"slab",
|
"slab",
|
||||||
"syslog_rpc",
|
"syslog_rpc",
|
||||||
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
dev_driver_rpc = { version = "0.1.0", path = "../dev_driver_rpc" }
|
dev_driver_rpc = { version = "0.1.0", path = "../dev_driver_rpc" }
|
||||||
devfs_rpc = { version = "0.1.0", path = "../devfs/devfs_rpc" }
|
devfs_rpc = { version = "0.1.0", path = "../devfs/devfs_rpc" }
|
||||||
file_rpc = { version = "0.1.0", path = "../file_rpc" }
|
file_rpc = { version = "0.1.0", path = "../file_rpc" }
|
||||||
|
line_discipline = { version = "0.1.0", path = "../line_discipline" }
|
||||||
parking_lot = "0.12.3"
|
parking_lot = "0.12.3"
|
||||||
slab = "0.4.9"
|
slab = "0.4.9"
|
||||||
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
|
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
|
||||||
|
189
src/main.rs
189
src/main.rs
@ -1,23 +1,20 @@
|
|||||||
mod termios;
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow, collections::HashMap, io::empty, os::mikros::{ipc, syscalls}, path::{Path, PathBuf}, sync::{
|
borrow::Cow,
|
||||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
collections::HashMap,
|
||||||
Arc,
|
os::mikros::{ipc, syscalls},
|
||||||
}
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use file_rpc::PollEvents;
|
use file_rpc::PollEvents;
|
||||||
|
use line_discipline::LineDiscipline;
|
||||||
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,
|
line_discipline: Mutex<LineDiscipline>,
|
||||||
output_paused: AtomicBool,
|
|
||||||
column: AtomicUsize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pty {
|
impl Pty {
|
||||||
@ -25,169 +22,48 @@ 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(),
|
line_discipline: Mutex::new(LineDiscipline::new()),
|
||||||
output_paused: AtomicBool::new(false),
|
|
||||||
column: AtomicUsize::new(0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_master(&self, len: usize) -> Result<Vec<u8>, ()> {
|
fn read_master(&self, len: usize) -> Vec<u8> {
|
||||||
if self.output_paused.load(Ordering::Relaxed) {
|
if self.line_discipline.lock().output_paused() {
|
||||||
return Ok(vec![]);
|
return Vec::new();
|
||||||
}
|
}
|
||||||
let mut output_buffer = self.output_buffer.lock();
|
let mut output_buffer = self.output_buffer.lock();
|
||||||
|
output_buffer.extend_from_slice(&self.line_discipline.lock().get_terminal_output());
|
||||||
let buf_len = output_buffer.len();
|
let buf_len = output_buffer.len();
|
||||||
let rem_buf = output_buffer.split_off(usize::min(buf_len, len));
|
let rem_buf = output_buffer.split_off(usize::min(buf_len, len));
|
||||||
let buf = std::mem::replace(&mut *output_buffer, rem_buf);
|
std::mem::replace(&mut *output_buffer, rem_buf)
|
||||||
Ok(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_master(&self, data: &[u8]) -> Result<(), ()> {
|
fn write_master(&self, data: &[u8]) {
|
||||||
if !self.termios.cflags.cread {
|
self.line_discipline.lock().process_terminal_input(data);
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
for &(mut ch) in data {
|
|
||||||
if self.termios.iflags.istrip {
|
|
||||||
ch &= 0x7F;
|
|
||||||
}
|
|
||||||
if ch == b'\r' && self.termios.iflags.igncr {
|
|
||||||
continue;
|
|
||||||
} else if ch == b'\r' && self.termios.iflags.icrnl {
|
|
||||||
ch = b'\n';
|
|
||||||
} else if ch == b'\n' && self.termios.iflags.inlcr {
|
|
||||||
ch = b'\r';
|
|
||||||
}
|
|
||||||
if ch as char == self.termios.verase && self.termios.lflags.icanon {
|
|
||||||
let buf_last = self.input_buffer.lock().last().copied();
|
|
||||||
if let Some(erased_ch) = buf_last {
|
|
||||||
let erased_ch = erased_ch as char;
|
|
||||||
if erased_ch != '\n' {
|
|
||||||
self.input_buffer.lock().pop();
|
|
||||||
self.erase_char(erased_ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ch as char == self.termios.vkill && self.termios.lflags.icanon {
|
|
||||||
let buf_last = self.input_buffer.lock().last().copied();
|
|
||||||
if let Some(erased_ch) = buf_last {
|
|
||||||
let erased_ch = erased_ch as char;
|
|
||||||
if erased_ch != '\n' {
|
|
||||||
self.input_buffer.lock().pop();
|
|
||||||
self.erase_char(erased_ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ch as char == self.termios.vstop && self.termios.iflags.ixon {
|
|
||||||
self.output_paused.store(true, Ordering::Relaxed);
|
|
||||||
} else if (ch as char == self.termios.vstart && self.termios.iflags.ixon)
|
|
||||||
|| (self.termios.iflags.ixany && self.output_paused.load(Ordering::Relaxed))
|
|
||||||
{
|
|
||||||
self.output_paused.store(false, Ordering::Relaxed);
|
|
||||||
} else {
|
|
||||||
self.input_buffer.lock().push(ch);
|
|
||||||
if self.termios.lflags.echo || (ch == b'\n' && self.termios.lflags.echonl) {
|
|
||||||
let mut output_buffer = self.output_buffer.lock();
|
|
||||||
if Self::is_nonprinting_control(ch as char) {
|
|
||||||
output_buffer.push(b'^');
|
|
||||||
output_buffer.push(ch + b'@');
|
|
||||||
self.column.fetch_add(2, Ordering::Relaxed);
|
|
||||||
} else if ch == b'\t' {
|
|
||||||
let curr_col = self.column.load(Ordering::Relaxed);
|
|
||||||
let num_cols = 8 - (curr_col % 8);
|
|
||||||
for _ in 0..num_cols {
|
|
||||||
output_buffer.push(b' ');
|
|
||||||
}
|
|
||||||
self.column.fetch_add(num_cols, Ordering::Relaxed);
|
|
||||||
} else {
|
|
||||||
output_buffer.push(ch);
|
|
||||||
self.column.fetch_add(1, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_slave(&self, len: usize) -> Result<Vec<u8>, ()> {
|
fn read_slave(&self, len: usize) -> Vec<u8> {
|
||||||
while !self.input_buffer.lock().contains(&b'\n') {
|
while !self.input_buffer.lock().contains(&b'\n') {
|
||||||
ipc::process_messages();
|
ipc::process_messages();
|
||||||
|
let mut input_buffer = self.input_buffer.lock();
|
||||||
|
input_buffer.extend_from_slice(&self.line_discipline.lock().get_program_input());
|
||||||
}
|
}
|
||||||
let mut input_buffer = self.input_buffer.lock();
|
let mut input_buffer = self.input_buffer.lock();
|
||||||
|
input_buffer.extend_from_slice(&self.line_discipline.lock().get_program_input());
|
||||||
let Some(line_end) = input_buffer.iter().position(|&x| x == b'\n') else {
|
let Some(line_end) = input_buffer.iter().position(|&x| x == b'\n') else {
|
||||||
return Ok(vec![]);
|
return Vec::new();
|
||||||
};
|
};
|
||||||
let rem_buf = input_buffer.split_off(usize::min(len, line_end + 1));
|
let rem_buf = input_buffer.split_off(usize::min(len, line_end + 1));
|
||||||
let buf = std::mem::replace(&mut *input_buffer, rem_buf);
|
std::mem::replace(&mut *input_buffer, rem_buf)
|
||||||
Ok(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_slave(&self, data: &[u8]) -> Result<(), ()> {
|
fn write_slave(&self, data: &[u8]) {
|
||||||
let mut output_buffer = self.output_buffer.lock();
|
self.line_discipline.lock().process_program_output(data);
|
||||||
for &byte in data {
|
|
||||||
if self.termios.oflags.opost {
|
|
||||||
if byte == b'\n' && self.termios.oflags.onlcr {
|
|
||||||
if self.column.load(Ordering::Relaxed) != 0 {
|
|
||||||
output_buffer.push(b'\r');
|
|
||||||
}
|
|
||||||
output_buffer.push(b'\n');
|
|
||||||
self.column.store(0, Ordering::Relaxed);
|
|
||||||
} else if byte == b'\r' && self.termios.oflags.ocrnl {
|
|
||||||
output_buffer.push(b'\n');
|
|
||||||
if self.termios.oflags.onlret {
|
|
||||||
self.column.store(0, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output_buffer.push(byte);
|
|
||||||
}
|
|
||||||
} else if (byte == b'\n' && self.termios.oflags.onlret) || byte == b'\r' {
|
|
||||||
self.column.store(0, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_nonprinting_control(ch: char) -> bool {
|
|
||||||
ch.is_ascii_control() && ch != '\r' && ch != '\n' && ch != '\t'
|
|
||||||
}
|
|
||||||
|
|
||||||
fn erase_char(&self, ch: char) {
|
|
||||||
if !self.termios.lflags.echoe {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut output_buffer = self.output_buffer.lock();
|
|
||||||
if Self::is_nonprinting_control(ch) {
|
|
||||||
output_buffer.push(8);
|
|
||||||
output_buffer.push(8);
|
|
||||||
self.column.fetch_sub(2, Ordering::Relaxed);
|
|
||||||
} else if ch == '\t' {
|
|
||||||
let curr_col = self.column.load(Ordering::Relaxed);
|
|
||||||
let mut before_tab_cols = 0;
|
|
||||||
let mut after_tab = false;
|
|
||||||
let input_buffer = self.input_buffer.lock();
|
|
||||||
for &byte in input_buffer.iter().rev() {
|
|
||||||
if Self::is_nonprinting_control(byte as char) {
|
|
||||||
before_tab_cols += 2;
|
|
||||||
} else if byte == b'\t' {
|
|
||||||
after_tab = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
before_tab_cols += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let num_cols = if after_tab {
|
|
||||||
8 - before_tab_cols
|
|
||||||
} else {
|
|
||||||
curr_col - before_tab_cols
|
|
||||||
};
|
|
||||||
for _ in 0..num_cols {
|
|
||||||
output_buffer.push(8);
|
|
||||||
}
|
|
||||||
self.column.fetch_sub(num_cols, Ordering::Relaxed);
|
|
||||||
} else {
|
|
||||||
output_buffer.push(8);
|
|
||||||
self.column.fetch_sub(1, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn curr_slave_poll(&self) -> PollEvents {
|
fn curr_slave_poll(&self) -> PollEvents {
|
||||||
|
self.input_buffer
|
||||||
|
.lock()
|
||||||
|
.extend_from_slice(&self.line_discipline.lock().get_program_input());
|
||||||
let mut events = PollEvents::POLLOUT;
|
let mut events = PollEvents::POLLOUT;
|
||||||
if self.input_buffer.lock().contains(&b'\n') {
|
if self.input_buffer.lock().contains(&b'\n') {
|
||||||
events |= PollEvents::POLLIN;
|
events |= PollEvents::POLLIN;
|
||||||
@ -196,6 +72,9 @@ impl Pty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn curr_master_poll(&self) -> PollEvents {
|
fn curr_master_poll(&self) -> PollEvents {
|
||||||
|
self.output_buffer
|
||||||
|
.lock()
|
||||||
|
.extend_from_slice(&self.line_discipline.lock().get_terminal_output());
|
||||||
let mut events = PollEvents::POLLOUT;
|
let mut events = PollEvents::POLLOUT;
|
||||||
if !self.output_buffer.lock().is_empty() {
|
if !self.output_buffer.lock().is_empty() {
|
||||||
events |= PollEvents::POLLIN;
|
events |= PollEvents::POLLIN;
|
||||||
@ -239,11 +118,11 @@ impl file_rpc::Server for Serv {
|
|||||||
if fd as usize >= usize::MAX / 2 {
|
if fd as usize >= usize::MAX / 2 {
|
||||||
let ptys = self.ptys.read();
|
let ptys = self.ptys.read();
|
||||||
let pty = &ptys[fd as usize - usize::MAX / 2];
|
let pty = &ptys[fd as usize - usize::MAX / 2];
|
||||||
pty.read_slave(len).map(|x| x.into())
|
Ok(pty.read_slave(len).into())
|
||||||
} else {
|
} else {
|
||||||
let ptys = self.ptys.read();
|
let ptys = self.ptys.read();
|
||||||
let pty = &ptys[fd as usize];
|
let pty = &ptys[fd as usize];
|
||||||
pty.read_master(len).map(|x| x.into())
|
Ok(pty.read_master(len).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,11 +130,13 @@ impl file_rpc::Server for Serv {
|
|||||||
if fd as usize >= usize::MAX / 2 {
|
if fd as usize >= usize::MAX / 2 {
|
||||||
let ptys = self.ptys.read();
|
let ptys = self.ptys.read();
|
||||||
let pty = &ptys[fd as usize - usize::MAX / 2];
|
let pty = &ptys[fd as usize - usize::MAX / 2];
|
||||||
pty.write_slave(data)
|
pty.write_slave(data);
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let ptys = self.ptys.read();
|
let ptys = self.ptys.read();
|
||||||
let pty = &ptys[fd as usize];
|
let pty = &ptys[fd as usize];
|
||||||
pty.write_master(data)
|
pty.write_master(data);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
212
src/termios.rs
212
src/termios.rs
@ -1,212 +0,0 @@
|
|||||||
#[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: true,
|
|
||||||
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