瀏覽代碼

Shell: Add the `disown' shell builtin

AnotherTest 5 年之前
父節點
當前提交
0d39418b0b
共有 3 個文件被更改,包括 67 次插入2 次删除
  1. 7 2
      Shell/Job.h
  2. 59 0
      Shell/Shell.cpp
  3. 1 0
      Shell/Shell.h

+ 7 - 2
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 };
 };

+ 59 - 0
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<const char*> 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<char**>(argv), false))
+        return 1;
+
+    Vector<size_t> 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<size_t> 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) {

+ 1 - 0
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)