diff options
-rw-r--r-- | Shell/AST.cpp | 8 | ||||
-rw-r--r-- | Shell/AST.h | 8 | ||||
-rw-r--r-- | Shell/Forward.h | 1 | ||||
-rw-r--r-- | Shell/Job.cpp | 1 | ||||
-rw-r--r-- | Shell/Job.h | 9 | ||||
-rw-r--r-- | Shell/Shell.cpp | 28 |
6 files changed, 44 insertions, 11 deletions
diff --git a/Shell/AST.cpp b/Shell/AST.cpp index be8d600d69..07864b734e 100644 --- a/Shell/AST.cpp +++ b/Shell/AST.cpp @@ -1142,6 +1142,14 @@ RefPtr<Value> Pipe::run(RefPtr<Shell> shell) last_in_left.should_wait = false; last_in_left.is_pipe_source = true; + if (first_in_right.pipeline) { + last_in_left.pipeline = first_in_right.pipeline; + } else { + auto pipeline = adopt(*new Pipeline); + last_in_left.pipeline = pipeline; + first_in_right.pipeline = pipeline; + } + Vector<Command> commands; commands.append(left); commands.append(last_in_left); diff --git a/Shell/AST.h b/Shell/AST.h index e016375db8..34399bf9d4 100644 --- a/Shell/AST.h +++ b/Shell/AST.h @@ -150,9 +150,15 @@ private: virtual bool is_fd_redirection() const override { return true; } }; +class Pipeline : public RefCounted<Pipeline> { +public: + pid_t pgid { -1 }; +}; + struct Command { Vector<String> argv; NonnullRefPtrVector<Redirection> redirections; + mutable RefPtr<Pipeline> pipeline; bool should_wait { true }; bool is_pipe_source { false }; bool should_notify_if_in_background { true }; @@ -190,7 +196,7 @@ public: } CommandValue(Vector<String> argv) - : m_command({ move(argv), {}, true, false, true }) + : m_command({ move(argv), {}, {}, true, false, true }) { } diff --git a/Shell/Forward.h b/Shell/Forward.h index f54829b191..94d5cf7eda 100644 --- a/Shell/Forward.h +++ b/Shell/Forward.h @@ -32,5 +32,6 @@ namespace AST { class Node; class Value; class SyntaxError; +class Pipeline; } diff --git a/Shell/Job.cpp b/Shell/Job.cpp index 29408c5266..498fc850c1 100644 --- a/Shell/Job.cpp +++ b/Shell/Job.cpp @@ -25,6 +25,7 @@ */ #include "Job.h" +#include "AST.h" #include <inttypes.h> #include <stdio.h> #include <sys/wait.h> diff --git a/Shell/Job.h b/Shell/Job.h index 9de08bfebc..7b13042091 100644 --- a/Shell/Job.h +++ b/Shell/Job.h @@ -27,6 +27,7 @@ #pragma once #include "Execution.h" +#include "Forward.h" #include <AK/Function.h> #include <AK/JsonObject.h> #include <AK/JsonValue.h> @@ -42,7 +43,7 @@ class Job : public RefCounted<Job> { public: - static NonnullRefPtr<Job> create(pid_t pid, pid_t pgid, String command, u64 job_id) { return adopt(*new Job(pid, pgid, move(command), job_id)); } + static NonnullRefPtr<Job> create(pid_t pid, pid_t pgid, String command, u64 job_id, AST::Pipeline* pipeline = nullptr) { return adopt(*new Job(pid, pgid, move(command), job_id, pipeline)); } ~Job() { @@ -121,12 +122,15 @@ public: bool print_status(PrintStatusMode); private: - Job(pid_t pid, unsigned pgid, String cmd, u64 job_id) + Job(pid_t pid, unsigned pgid, String cmd, u64 job_id, AST::Pipeline* pipeline) : m_pgid(pgid) , m_pid(pid) , m_job_id(job_id) , m_cmd(move(cmd)) { + if (pipeline) + m_pipeline = *pipeline; + set_running_in_background(false); m_command_timer.start(); } @@ -143,4 +147,5 @@ private: mutable bool m_active { true }; mutable bool m_is_suspended { false }; bool m_should_be_disowned { false }; + RefPtr<AST::Pipeline> m_pipeline; }; diff --git a/Shell/Shell.cpp b/Shell/Shell.cpp index be5d61304e..58eeda947d 100644 --- a/Shell/Shell.cpp +++ b/Shell/Shell.cpp @@ -518,15 +518,10 @@ RefPtr<Job> Shell::run_command(const AST::Command& command) perror("fork"); return nullptr; } + if (child == 0) { - setpgid(0, 0); tcsetattr(0, TCSANOW, &default_termios); - if (command.should_wait) { - auto pid = getpid(); - auto pgid = getpgid(pid); - tcsetpgrp(STDOUT_FILENO, pgid); - tcsetpgrp(STDIN_FILENO, pgid); - } + for (auto& rewiring : rewirings) { #ifdef SH_DEBUG dbgprintf("in %s<%d>, dup2(%d, %d)\n", argv[0], getpid(), rewiring.dest_fd, rewiring.source_fd); @@ -572,10 +567,27 @@ RefPtr<Job> Shell::run_command(const AST::Command& command) ASSERT_NOT_REACHED(); } + bool is_first = !command.pipeline || (command.pipeline && command.pipeline->pgid == -1); + + if (command.pipeline) { + if (is_first) { + command.pipeline->pgid = child; + } + } + + pid_t pgid = is_first ? child : (command.pipeline ? command.pipeline->pgid : child); + if (setpgid(child, pgid) < 0) + perror("setpgid"); + + if (command.should_wait) { + tcsetpgrp(STDOUT_FILENO, pgid); + tcsetpgrp(STDIN_FILENO, pgid); + } + StringBuilder cmd; cmd.join(" ", command.argv); - auto job = Job::create(child, (unsigned)child, cmd.build(), find_last_job_id() + 1); + auto job = Job::create(child, pgid, cmd.build(), find_last_job_id() + 1, command.pipeline); jobs.set((u64)child, job); job->on_exit = [](auto job) { |