summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Shell/AST.cpp8
-rw-r--r--Shell/AST.h8
-rw-r--r--Shell/Forward.h1
-rw-r--r--Shell/Job.cpp1
-rw-r--r--Shell/Job.h9
-rw-r--r--Shell/Shell.cpp28
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) {