Skip to content

Commit

Permalink
Implement quick and dirty Ctrl-C and Ctrl-Z behaviors
Browse files Browse the repository at this point in the history
  • Loading branch information
guilload committed Jun 27, 2017
1 parent 4fcd86e commit b4ec8c0
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
16 changes: 11 additions & 5 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate libc;

extern crate nom;
extern crate nix;
extern crate nom;

use std::ffi::CString;
use std::ffi;
Expand Down Expand Up @@ -48,7 +48,7 @@ named!(pub parse_command<&str, Command>,
stdin: redirect_from.unwrap_or(StdX::StdIn),
stdout: redirect_to.unwrap_or(StdX::StdOut),
pid: 0,
status: Status::Suspended,
status: Status::Running,
})
)
);
Expand All @@ -66,8 +66,10 @@ pub struct Command {

#[derive(Debug, Clone, PartialEq)]
pub enum Status {
Suspended,
Completed,
Running,
Suspended,
Terminated,
}


Expand All @@ -80,7 +82,7 @@ impl Command {
stdin: StdX::StdIn,
stdout: StdX::StdOut,
pid: 0,
status: Status::Suspended,
status: Status::Running,
}
}

Expand Down Expand Up @@ -128,6 +130,10 @@ impl Command {
self.status == Status::Suspended
}

pub fn is_terminated(&self) -> bool {
self.status == Status::Terminated
}

fn cprogram(&self) -> Result<CString, ffi::NulError> {
CString::new(self.program.as_bytes())
}
Expand Down Expand Up @@ -233,6 +239,6 @@ fn test_command_new() {

#[test]
fn test_status() {
assert!(Command::new("ls").is_suspended());
assert!(!Command::new("ls").is_completed());
assert!(Command::new("ls").status(Status::Completed).is_completed());
}
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rotten_sh::signal::Signal;

struct Shell {
background_jobs: Vec<Pipeline>,
suspended_jobs: Vec<Pipeline>,
}

impl Shell {
Expand All @@ -26,7 +27,7 @@ impl Shell {
setpgid(0, 0).unwrap();
tcsetpgrp(libc::STDIN_FILENO, getpid()).unwrap();

Shell { background_jobs: vec![], }
Shell { background_jobs: vec![], suspended_jobs: vec![] }
}

fn run(&mut self) {
Expand Down Expand Up @@ -63,6 +64,9 @@ impl Shell {
}
else {
job.fg().unwrap();
if job.is_suspended() {
self.suspended_jobs.push(job);
}
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern crate nom;
use std::io;
use std::os::unix::io::RawFd;

use self::nix::sys::signal::Signal::{SIGINT, SIGTSTP};
use self::nix::sys::wait::{waitpid, WaitStatus, WUNTRACED};
use self::nix::unistd::{close, getpid, pipe, tcsetpgrp};
use self::nom::*;
Expand Down Expand Up @@ -64,16 +65,21 @@ impl Pipeline {
}

pub fn is_suspended(&self) -> bool {
self.commands.iter().all(|c| c.is_suspended())
self.commands.iter().any(|c| c.is_suspended())
}

pub fn is_terminated(&self) -> bool {
self.commands.iter().any(|c| c.is_terminated())
}

pub fn wait(&mut self) -> Result<(), nix::Error> {
while !self.is_completed() {
while !self.is_completed() && !self.is_suspended() && !self.is_terminated() {
let status = waitpid(-1 * self.pgid, Some(WUNTRACED))?;

match status {
WaitStatus::Exited(pid, _) => self.find_command(pid).unwrap().status(Status::Completed),
WaitStatus::Stopped(pid, _) => self.find_command(pid).unwrap().status(Status::Suspended),
WaitStatus::Signaled(pid, SIGINT, _) => self.find_command(pid).unwrap().status(Status::Terminated),
WaitStatus::Stopped(pid, SIGTSTP) => self.find_command(pid).unwrap().status(Status::Suspended),
_ => panic!("unimplemented!"),
};
}
Expand Down

0 comments on commit b4ec8c0

Please sign in to comment.