|  | @@ -1,5 +1,3 @@
 | 
											
												
													
														|  | -use core::iter::repeat;
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |  use alloc::{
 |  |  use alloc::{
 | 
											
												
													
														|  |      collections::vec_deque::VecDeque,
 |  |      collections::vec_deque::VecDeque,
 | 
											
												
													
														|  |      sync::{Arc, Weak},
 |  |      sync::{Arc, Weak},
 | 
											
										
											
												
													
														|  | @@ -42,6 +40,7 @@ const VEOL2: usize = 16;
 | 
											
												
													
														|  |  /* c_iflag bits */
 |  |  /* c_iflag bits */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  bitflags! {
 |  |  bitflags! {
 | 
											
												
													
														|  | 
 |  | +    #[derive(Debug)]
 | 
											
												
													
														|  |      pub struct TermioIFlags: u16 {
 |  |      pub struct TermioIFlags: u16 {
 | 
											
												
													
														|  |          /// Ignore break condition
 |  |          /// Ignore break condition
 | 
											
												
													
														|  |          const IGNBRK = 0x0001;
 |  |          const IGNBRK = 0x0001;
 | 
											
										
											
												
													
														|  | @@ -70,6 +69,7 @@ bitflags! {
 | 
											
												
													
														|  |          const IUTF8 = 0x4000;
 |  |          const IUTF8 = 0x4000;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    #[derive(Debug)]
 | 
											
												
													
														|  |      pub struct TermioOFlags: u16 {
 |  |      pub struct TermioOFlags: u16 {
 | 
											
												
													
														|  |          /// Perform output processing
 |  |          /// Perform output processing
 | 
											
												
													
														|  |          const OPOST = 0x0001;
 |  |          const OPOST = 0x0001;
 | 
											
										
											
												
													
														|  | @@ -84,6 +84,7 @@ bitflags! {
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  bitflags! {
 |  |  bitflags! {
 | 
											
												
													
														|  | 
 |  | +    #[derive(Debug)]
 | 
											
												
													
														|  |      pub struct TermioLFlags: u16 {
 |  |      pub struct TermioLFlags: u16 {
 | 
											
												
													
														|  |          const ISIG = 0x0001;
 |  |          const ISIG = 0x0001;
 | 
											
												
													
														|  |          const ICANON = 0x0002;
 |  |          const ICANON = 0x0002;
 | 
											
										
											
												
													
														|  | @@ -113,6 +114,7 @@ const HUPCL: u32 = 0x00000400;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  const N_TTY: u8 = 0;
 |  |  const N_TTY: u8 = 0;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +#[derive(Debug)]
 | 
											
												
													
														|  |  pub struct Termios {
 |  |  pub struct Termios {
 | 
											
												
													
														|  |      iflag: TermioIFlags,
 |  |      iflag: TermioIFlags,
 | 
											
												
													
														|  |      oflag: TermioOFlags,
 |  |      oflag: TermioOFlags,
 | 
											
										
											
												
													
														|  | @@ -323,10 +325,10 @@ impl Termios {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn get_user(&self) -> UserTermios {
 |  |      fn get_user(&self) -> UserTermios {
 | 
											
												
													
														|  |          UserTermios {
 |  |          UserTermios {
 | 
											
												
													
														|  | -            iflag: self.iflag.bits() as u16,
 |  | 
 | 
											
												
													
														|  | -            oflag: self.oflag.bits() as u16,
 |  | 
 | 
											
												
													
														|  | -            cflag: self.cflag as u16,
 |  | 
 | 
											
												
													
														|  | -            lflag: self.lflag.bits() as u16,
 |  | 
 | 
											
												
													
														|  | 
 |  | +            iflag: self.iflag.bits() as u32,
 | 
											
												
													
														|  | 
 |  | +            oflag: self.oflag.bits() as u32,
 | 
											
												
													
														|  | 
 |  | +            cflag: self.cflag,
 | 
											
												
													
														|  | 
 |  | +            lflag: self.lflag.bits() as u32,
 | 
											
												
													
														|  |              line: self.line,
 |  |              line: self.line,
 | 
											
												
													
														|  |              cc: self.cc,
 |  |              cc: self.cc,
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -362,10 +364,10 @@ pub struct UserWindowSize {
 | 
											
												
													
														|  |  #[repr(C)]
 |  |  #[repr(C)]
 | 
											
												
													
														|  |  #[derive(Debug, Clone, Copy)]
 |  |  #[derive(Debug, Clone, Copy)]
 | 
											
												
													
														|  |  pub struct UserTermios {
 |  |  pub struct UserTermios {
 | 
											
												
													
														|  | -    iflag: u16,
 |  | 
 | 
											
												
													
														|  | -    oflag: u16,
 |  | 
 | 
											
												
													
														|  | -    cflag: u16,
 |  | 
 | 
											
												
													
														|  | -    lflag: u16,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    iflag: u32,
 | 
											
												
													
														|  | 
 |  | +    oflag: u32,
 | 
											
												
													
														|  | 
 |  | +    cflag: u32,
 | 
											
												
													
														|  | 
 |  | +    lflag: u32,
 | 
											
												
													
														|  |      line: u8,
 |  |      line: u8,
 | 
											
												
													
														|  |      cc: [u8; NCCS],
 |  |      cc: [u8; NCCS],
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
										
											
												
													
														|  | @@ -390,7 +392,7 @@ impl Terminal {
 | 
											
												
													
														|  |              inner: Spin::new(TerminalInner {
 |  |              inner: Spin::new(TerminalInner {
 | 
											
												
													
														|  |                  termio: Termios::new_standard(),
 |  |                  termio: Termios::new_standard(),
 | 
											
												
													
														|  |                  session: Weak::new(),
 |  |                  session: Weak::new(),
 | 
											
												
													
														|  | -                buffer: repeat(0).take(BUFFER_SIZE).collect(),
 |  | 
 | 
											
												
													
														|  | 
 |  | +                buffer: VecDeque::with_capacity(BUFFER_SIZE),
 | 
											
												
													
														|  |              }),
 |  |              }),
 | 
											
												
													
														|  |              cv: CondVar::new(),
 |  |              cv: CondVar::new(),
 | 
											
												
													
														|  |              device,
 |  |              device,
 | 
											
										
											
												
													
														|  | @@ -463,9 +465,9 @@ impl Terminal {
 | 
											
												
													
														|  |              self.echo_char(inner, ch);
 |  |              self.echo_char(inner, ch);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        // If ICANON is set, we notify all waiting processes.
 |  | 
 | 
											
												
													
														|  | -        // If ICANON is not set but we have a new line, there are data ready, we notify as well.
 |  | 
 | 
											
												
													
														|  | -        if ch == b'\n' || inner.termio.icanon() {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        // If ICANON is not set, we notify all waiting processes.
 | 
											
												
													
														|  | 
 |  | +        // If ICANON is set but we have a new line, there are data ready, we notify as well.
 | 
											
												
													
														|  | 
 |  | +        if ch == b'\n' || !inner.termio.icanon() {
 | 
											
												
													
														|  |              self.cv.notify_all();
 |  |              self.cv.notify_all();
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
										
											
												
													
														|  | @@ -532,9 +534,11 @@ impl Terminal {
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
 |  |      pub fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
 | 
											
												
													
														|  | -        'block: {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let mut tmp_buffer = [0u8; 32];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let data = 'block: {
 | 
											
												
													
														|  |              if buffer.available() == 0 {
 |  |              if buffer.available() == 0 {
 | 
											
												
													
														|  | -                break 'block;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                break 'block &tmp_buffer[..0];
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              let mut inner = self.inner.lock_irq();
 |  |              let mut inner = self.inner.lock_irq();
 | 
											
										
											
												
													
														|  | @@ -547,38 +551,37 @@ impl Terminal {
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              if inner.buffer.is_empty() {
 |  |              if inner.buffer.is_empty() {
 | 
											
												
													
														|  | -                break 'block;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                break 'block &tmp_buffer[..0];
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            if !inner.termio.icanon() {
 |  | 
 | 
											
												
													
														|  | -                let ch = inner.buffer.pop_front().unwrap();
 |  | 
 | 
											
												
													
														|  | -                buffer.fill(&[ch])?.allow_partial();
 |  | 
 | 
											
												
													
														|  | -                break 'block;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            let length = if inner.termio.icanon() {
 | 
											
												
													
														|  | 
 |  | +                // Canonical mode, return data until we see a newline.
 | 
											
												
													
														|  | 
 |  | +                // TODO!!: We should wait if we don't see one.
 | 
											
												
													
														|  | 
 |  | +                inner
 | 
											
												
													
														|  | 
 |  | +                    .buffer
 | 
											
												
													
														|  | 
 |  | +                    .iter()
 | 
											
												
													
														|  | 
 |  | +                    .position(|&ch| ch == b'\n')
 | 
											
												
													
														|  | 
 |  | +                    .map(|pos| pos + 1)
 | 
											
												
													
														|  | 
 |  | +                    .unwrap_or(inner.buffer.len())
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                buffer.available().min(inner.buffer.len())
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            // TODO!!!!!!: Change this. We need to loop until we've got enough data.
 | 
											
												
													
														|  | 
 |  | +            let length = length.min(tmp_buffer.len());
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            for (ch, r) in inner
 | 
											
												
													
														|  | 
 |  | +                .buffer
 | 
											
												
													
														|  | 
 |  | +                .drain(..length)
 | 
											
												
													
														|  | 
 |  | +                .zip(tmp_buffer.iter_mut().take(length))
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                *r = ch;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            // Canonical mode, return data until we see a newline.
 |  | 
 | 
											
												
													
														|  | -            let length = inner
 |  | 
 | 
											
												
													
														|  | -                .buffer
 |  | 
 | 
											
												
													
														|  | -                .iter()
 |  | 
 | 
											
												
													
														|  | -                .position(|&ch| ch == b'\n')
 |  | 
 | 
											
												
													
														|  | -                .map(|pos| pos + 1)
 |  | 
 | 
											
												
													
														|  | -                .unwrap_or(inner.buffer.len());
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            let (first, second) = inner.buffer.as_slices();
 |  | 
 | 
											
												
													
														|  | -            let first_data = first
 |  | 
 | 
											
												
													
														|  | -                .split_at_checked(length)
 |  | 
 | 
											
												
													
														|  | -                .map_or(first, |(data, _)| data);
 |  | 
 | 
											
												
													
														|  | -            let second_data = second
 |  | 
 | 
											
												
													
														|  | -                .split_at_checked(length - first_data.len())
 |  | 
 | 
											
												
													
														|  | -                .map_or(second, |(data, _)| data);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            buffer.fill(first_data)?.allow_partial();
 |  | 
 | 
											
												
													
														|  | -            buffer.fill(second_data)?.allow_partial();
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            inner.buffer.drain(..buffer.wrote());
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | 
 |  | +            &tmp_buffer[..length]
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        Ok(buffer.wrote())
 |  | 
 | 
											
												
													
														|  | 
 |  | +        buffer.fill(data).map(|result| result.allow_partial())
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn ioctl(&self, request: TerminalIORequest) -> KResult<()> {
 |  |      pub fn ioctl(&self, request: TerminalIORequest) -> KResult<()> {
 | 
											
										
											
												
													
														|  | @@ -595,9 +598,10 @@ impl Terminal {
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              TerminalIORequest::SetProcessGroup(pgid) => {
 |  |              TerminalIORequest::SetProcessGroup(pgid) => {
 | 
											
												
													
														|  | 
 |  | +                let pgid = pgid.read()?;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |                  let inner = self.inner.lock();
 |  |                  let inner = self.inner.lock();
 | 
											
												
													
														|  |                  let session = inner.session.upgrade();
 |  |                  let session = inner.session.upgrade();
 | 
											
												
													
														|  | -                let pgid = pgid.read()?;
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  if let Some(session) = session {
 |  |                  if let Some(session) = session {
 | 
											
												
													
														|  |                      session.set_foreground_pgid(pgid)
 |  |                      session.set_foreground_pgid(pgid)
 | 
											
										
											
												
													
														|  | @@ -617,18 +621,18 @@ impl Terminal {
 | 
											
												
													
														|  |                  ptr.write(window_size)
 |  |                  ptr.write(window_size)
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              TerminalIORequest::GetTermios(ptr) => {
 |  |              TerminalIORequest::GetTermios(ptr) => {
 | 
											
												
													
														|  | -                let inner = self.inner.lock();
 |  | 
 | 
											
												
													
														|  | -                ptr.write(inner.termio.get_user())
 |  | 
 | 
											
												
													
														|  | 
 |  | +                let termios = self.inner.lock().termio.get_user();
 | 
											
												
													
														|  | 
 |  | +                ptr.write(termios)
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              TerminalIORequest::SetTermios(ptr) => {
 |  |              TerminalIORequest::SetTermios(ptr) => {
 | 
											
												
													
														|  | -                let mut inner = self.inner.lock();
 |  | 
 | 
											
												
													
														|  |                  let user_termios = ptr.read()?;
 |  |                  let user_termios = ptr.read()?;
 | 
											
												
													
														|  | 
 |  | +                let mut inner = self.inner.lock();
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  // TODO: We ignore unknown bits for now.
 |  |                  // TODO: We ignore unknown bits for now.
 | 
											
												
													
														|  | -                inner.termio.iflag = TermioIFlags::from_bits_truncate(user_termios.iflag);
 |  | 
 | 
											
												
													
														|  | -                inner.termio.oflag = TermioOFlags::from_bits_truncate(user_termios.oflag);
 |  | 
 | 
											
												
													
														|  | -                inner.termio.lflag = TermioLFlags::from_bits_truncate(user_termios.lflag);
 |  | 
 | 
											
												
													
														|  | -                inner.termio.cflag = user_termios.cflag as u32;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                inner.termio.iflag = TermioIFlags::from_bits_truncate(user_termios.iflag as u16);
 | 
											
												
													
														|  | 
 |  | +                inner.termio.oflag = TermioOFlags::from_bits_truncate(user_termios.oflag as u16);
 | 
											
												
													
														|  | 
 |  | +                inner.termio.lflag = TermioLFlags::from_bits_truncate(user_termios.lflag as u16);
 | 
											
												
													
														|  | 
 |  | +                inner.termio.cflag = user_termios.cflag;
 | 
											
												
													
														|  |                  inner.termio.line = user_termios.line;
 |  |                  inner.termio.line = user_termios.line;
 | 
											
												
													
														|  |                  inner.termio.cc = user_termios.cc;
 |  |                  inner.termio.cc = user_termios.cc;
 | 
											
												
													
														|  |  
 |  |  
 |