From 7bc70b7f00efe9e5dc2a48dce157dfaa4455fcb1 Mon Sep 17 00:00:00 2001 From: Dan Robertson <dan.robertson@anidata.org> Date: Tue, 28 Nov 2017 21:50:58 +0000 Subject: [PATCH] Update the disown command - disown panics if - No arguments are provided to the command - No jobspec's are provided to the -r or -h options - disown does not have a help option --- src/builtins/job_control.rs | 46 +++++++++++++++++++++++++++++++------ src/builtins/mod.rs | 10 +++++++- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/builtins/job_control.rs b/src/builtins/job_control.rs index d81c7980..0b5b087b 100644 --- a/src/builtins/job_control.rs +++ b/src/builtins/job_control.rs @@ -1,17 +1,41 @@ //! Contains the `jobs`, `disown`, `bg`, and `fg` commands that manage job control in the shell. +use std::error::Error; use shell::Shell; use shell::job_control::{JobControl, ProcessState}; use shell::signals; use shell::status::*; -use std::io::{stderr, Write}; +use std::io::{stderr, stdout, Write}; + +const DISOWN_MAN_PAGE: &'static str = r#"NAME + disown - Disown processes + +SYNOPSIS + disown [ --help | -r | -h | -a ][PID...] + +DESCRIPTION + Disowning a process removes that process from the shell's background process table. + +OPTIONS + -r Remove all running jobs from the background process list. + -h Specifies that each job supplied will not receive the SIGHUP signal when the shell receives a SIGHUP. + -a If no job IDs were supplied, remove all jobs from the background process list. +"#; /// Disowns given process job IDs, and optionally marks jobs to not receive SIGHUP signals. /// The `-a` flag selects all jobs, `-r` selects all running jobs, and `-h` specifies to mark /// SIGHUP ignoral. -pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> i32 { - let stderr = stderr(); - let mut stderr = stderr.lock(); +pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> Result<(), String> { + fn print_help(ret: Result<(), String>) -> Result<(), String> { + let stdout = stdout(); + let mut stdout = stdout.lock(); + + return match stdout.write_all(DISOWN_MAN_PAGE.as_bytes()).and_then(|_| stdout.flush()) { + Ok(_) => ret, + Err(err) => Err(err.description().to_owned()), + } + } + const NO_SIGHUP: u8 = 1; const ALL_JOBS: u8 = 2; const RUN_JOBS: u8 = 4; @@ -23,16 +47,24 @@ pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> i32 { "-a" => flags |= ALL_JOBS, "-h" => flags |= NO_SIGHUP, "-r" => flags |= RUN_JOBS, + "--help" => { + return print_help(Ok(())); + }, _ => match arg.parse::<u32>() { Ok(jobspec) => jobspecs.push(jobspec), Err(_) => { - let _ = writeln!(stderr, "ion: disown: invalid jobspec: '{}'", arg); - return FAILURE; + return Err(format!("invalid jobspec: '{}'", arg)); } }, } } + if flags == 0 { + return print_help(Err("must provide arguments".to_owned())); + } else if (flags & ALL_JOBS) == 0 && jobspecs.is_empty() { + return Err("must provide a jobspec with -h or -r".to_owned()); + } + let mut processes = shell.background.lock().unwrap(); if jobspecs.is_empty() && flags & ALL_JOBS != 0 { if flags & NO_SIGHUP != 0 { @@ -71,7 +103,7 @@ pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> i32 { } } - SUCCESS + Ok(()) } /// Display a list of all jobs running in the background. diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index b43a1f9d..6c2a20b3 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -357,7 +357,15 @@ fn builtin_suspend(_: &[&str], _: &mut Shell) -> i32 { } fn builtin_disown(args: &[&str], shell: &mut Shell) -> i32 { - job_control::disown(shell, &args[1..]) + match job_control::disown(shell, &args[1..]) { + Ok(()) => SUCCESS, + Err(err) => { + let stderr = io::stderr(); + let mut stderr = stderr.lock(); + let _ = writeln!(stderr, "ion: disown: {}", err); + FAILURE + } + } } fn builtin_help(args: &[&str], shell: &mut Shell) -> i32 { -- GitLab