diff --git a/Shell/Job.h b/Shell/Job.h index 341084931a..d374a9c8d5 100644 --- a/Shell/Job.h +++ b/Shell/Job.h @@ -42,8 +42,10 @@ public: ~Job() { - auto elapsed = m_command_timer.elapsed(); - dbg() << "Command \"" << m_cmd << "\" finished in " << elapsed << " ms"; + if (m_active) { + auto elapsed = m_command_timer.elapsed(); + dbg() << "Command \"" << m_cmd << "\" finished in " << elapsed << " ms"; + } } Job(pid_t pid, unsigned pgid, String cmd, u64 job_id) @@ -79,6 +81,8 @@ public: m_running_in_background = running_in_background; } + void deactivate() const { m_active = false; } + private: unsigned m_pgid { 0 }; pid_t m_pid { 0 }; @@ -88,4 +92,5 @@ private: bool m_running_in_background { false }; int m_exit_code { -1 }; Core::ElapsedTimer m_command_timer; + mutable bool m_active { true }; }; diff --git a/Shell/Shell.cpp b/Shell/Shell.cpp index f2fb1d5986..75f494e489 100644 --- a/Shell/Shell.cpp +++ b/Shell/Shell.cpp @@ -442,6 +442,65 @@ int Shell::builtin_fg(int argc, const char** argv) return return_value; } +int Shell::builtin_disown(int argc, const char** argv) +{ + Vector str_job_ids; + + Core::ArgsParser parser; + parser.add_positional_argument(str_job_ids, "Id of the jobs to disown (omit for current job)", "job_ids", Core::ArgsParser::Required::No); + + if (!parser.parse(argc, const_cast(argv), false)) + return 1; + + Vector job_ids; + for (auto& job_id : str_job_ids) { + bool ok; + auto id = StringView { job_id }.to_uint(ok); + if (ok) + job_ids.append(id); + else + printf("Invalid job id: %s\n", job_id); + } + + if (job_ids.is_empty()) + job_ids.append(jobs.size() - 1); + + Vector keys_of_jobs_to_disown; + + for (auto id : job_ids) { + bool found = false; + for (auto& entry : jobs) { + if (entry.value->job_id() == id) { + keys_of_jobs_to_disown.append(entry.key); + found = true; + break; + } + } + if (!found) { + printf("job with id %zu not found\n", id); + } + } + if (keys_of_jobs_to_disown.is_empty()) { + if (str_job_ids.is_empty()) { + printf("disown: no current job\n"); + } + // An error message has already been printed about the nonexistence of each listed job. + return 1; + } + for (auto job_index : keys_of_jobs_to_disown) { + auto job = jobs.get(job_index).value(); + + job->deactivate(); + + if (!job->is_running_in_background()) + printf("disown warning: job %llu is currently not running, 'kill -%d %d' to make it continue\n", job->job_id(), SIGCONT, job->pid()); + + jobs.remove(job_index); + } + + return 0; +} + int Shell::builtin_history(int, const char**) { for (size_t i = 0; i < editor.history().size(); ++i) { diff --git a/Shell/Shell.h b/Shell/Shell.h index 3b436b54c6..042e5e365b 100644 --- a/Shell/Shell.h +++ b/Shell/Shell.h @@ -84,6 +84,7 @@ using ContinuationRequest = ExitCodeOrContinuationRequest::ContinuationRequest; __ENUMERATE_SHELL_BUILTIN(popd) \ __ENUMERATE_SHELL_BUILTIN(time) \ __ENUMERATE_SHELL_BUILTIN(jobs) \ + __ENUMERATE_SHELL_BUILTIN(disown) \ __ENUMERATE_SHELL_BUILTIN(fg) \ __ENUMERATE_SHELL_BUILTIN(bg)