Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add kill-session command #745

Merged
merged 10 commits into from
Oct 11, 2021
61 changes: 59 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ mod tests;

use crate::install::populate_data_dir;
use sessions::{
assert_session, assert_session_ne, get_active_session, get_sessions, list_sessions,
print_sessions, session_exists, ActiveSession,
assert_session, assert_session_ne, get_active_session, get_sessions, kill_session,
list_sessions, print_sessions, session_exists, ActiveSession,
};
use std::process;
use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo};
Expand All @@ -27,6 +27,63 @@ pub fn main() {
list_sessions();
}

if let Some(Command::Sessions(Sessions::KillAllSessions { yes })) = opts.command {
match get_sessions() {
Ok(sessions) => {
if sessions.is_empty() {
println!("No active zellij sessions found.");
process::exit(1);
} else {
let kill_all_sessions = |sessions: Vec<std::string::String>| {
for session in sessions.iter() {
jaeheonji marked this conversation as resolved.
Show resolved Hide resolved
kill_session(session);
}
process::exit(0)
};

if yes {
kill_all_sessions(sessions);
} else {
use std::io::{stdin, stdout, Write};

let mut answer = String::new();
println!("WARNING: this action will kill all sessions.");
print!("Do you want to continue? [y/N] ");
let _ = stdout().flush();
stdin().read_line(&mut answer).unwrap();

match answer.as_str().trim() {
"y" | "Y" | "yes" | "Yes" => kill_all_sessions(sessions),
_ => {
println!("Abort.");
process::exit(1);
}
}
}
}
}
Err(e) => {
eprintln!("Error occured: {:?}", e);
process::exit(1);
}
}
}

if let Some(Command::Sessions(Sessions::KillSession { target_session })) = opts.command.clone()
{
match target_session.as_ref() {
Some(target_session) => {
assert_session(target_session);
kill_session(target_session);
process::exit(0);
}
None => {
println!("Please specify the session name to kill.");
process::exit(1);
}
}
}

atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap();
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
if let Some(path) = opts.server {
Expand Down
13 changes: 13 additions & 0 deletions src/sessions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ pub(crate) fn get_active_session() -> ActiveSession {
}
}

pub(crate) fn kill_session(name: &str) {
let path = &*ZELLIJ_SOCK_DIR.join(name);
match LocalSocketStream::connect(path) {
Ok(stream) => {
IpcSenderWithContext::new(stream).send(ClientToServerMsg::KillSession);
}
Err(e) => {
eprintln!("Error occured: {:?}", e);
process::exit(1);
}
};
}

pub(crate) fn list_sessions() {
let exit_code = match get_sessions() {
Ok(sessions) => {
Expand Down
10 changes: 10 additions & 0 deletions zellij-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub(crate) enum ServerInstruction {
ClientExit(ClientId),
RemoveClient(ClientId),
Error(String),
KillSession,
DetachSession(ClientId),
AttachClient(ClientAttributes, Options, ClientId),
}
Expand All @@ -78,6 +79,7 @@ impl From<&ServerInstruction> for ServerContext {
ServerInstruction::ClientExit(..) => ServerContext::ClientExit,
ServerInstruction::RemoveClient(..) => ServerContext::RemoveClient,
ServerInstruction::Error(_) => ServerContext::Error,
ServerInstruction::KillSession => ServerContext::KillSession,
ServerInstruction::DetachSession(..) => ServerContext::DetachSession,
ServerInstruction::AttachClient(..) => ServerContext::AttachClient,
}
Expand Down Expand Up @@ -400,6 +402,14 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
.unwrap();
}
}
ServerInstruction::KillSession => {
let client_ids = session_state.read().unwrap().client_ids();
for client_id in client_ids {
os_input.send_to_client(client_id, ServerToClientMsg::Exit(ExitReason::Normal));
remove_client!(client_id, os_input, session_state);
}
break;
}
ServerInstruction::DetachSession(client_id) => {
os_input.send_to_client(client_id, ServerToClientMsg::Exit(ExitReason::Normal));
remove_client!(client_id, os_input, session_state);
Expand Down
3 changes: 3 additions & 0 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ pub(crate) fn route_thread_main(
let _ = to_server.send(ServerInstruction::RemoveClient(client_id));
break;
}
ClientToServerMsg::KillSession => {
to_server.send(ServerInstruction::KillSession).unwrap();
}
}
}
}
15 changes: 15 additions & 0 deletions zellij-utils/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,19 @@ pub enum Sessions {
#[structopt(subcommand, name = "options")]
options: Option<SessionCommand>,
},

/// Kill the specific session
#[structopt(alias = "k")]
KillSession {
/// Name of target session
target_session: Option<String>,
},

/// Kill all sessions
#[structopt(alias = "ka")]
KillAllSessions {
/// Automatic yes to prompts
#[structopt(short, long)]
yes: bool,
},
}
1 change: 1 addition & 0 deletions zellij-utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ pub enum ServerContext {
ClientExit,
RemoveClient,
Error,
KillSession,
DetachSession,
AttachClient,
}
1 change: 1 addition & 0 deletions zellij-utils/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub enum ClientToServerMsg {
AttachClient(ClientAttributes, Options),
Action(Action),
ClientExited,
KillSession,
}

// Types of messages sent from the server to the client
Expand Down