mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 12:58:13 +00:00
Shell: Rename {source,dest}_fd to {old,new}_fd
This makes `Rewiring' much more understandable, and un-confuses the uses of `dup2()'. Also fixes `dup2()' bugs.
This commit is contained in:
parent
0bc758d34a
commit
f4b7a688b1
4 changed files with 74 additions and 54 deletions
|
@ -852,13 +852,13 @@ DynamicEvaluate::~DynamicEvaluate()
|
||||||
void Fd2FdRedirection::dump(int level) const
|
void Fd2FdRedirection::dump(int level) const
|
||||||
{
|
{
|
||||||
Node::dump(level);
|
Node::dump(level);
|
||||||
print_indented(String::format("%d -> %d", m_source_fd, m_dest_fd), level);
|
print_indented(String::format("%d -> %d", m_old_fd, m_new_fd), level);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Value> Fd2FdRedirection::run(RefPtr<Shell>)
|
RefPtr<Value> Fd2FdRedirection::run(RefPtr<Shell>)
|
||||||
{
|
{
|
||||||
Command command;
|
Command command;
|
||||||
command.redirections.append(FdRedirection::create(m_source_fd, m_dest_fd, Rewiring::Close::None));
|
command.redirections.append(FdRedirection::create(m_new_fd, m_old_fd, Rewiring::Close::None));
|
||||||
return create<CommandValue>(move(command));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,8 +869,8 @@ void Fd2FdRedirection::highlight_in_editor(Line::Editor& editor, Shell&, Highlig
|
||||||
|
|
||||||
Fd2FdRedirection::Fd2FdRedirection(Position position, int src, int dst)
|
Fd2FdRedirection::Fd2FdRedirection(Position position, int src, int dst)
|
||||||
: Node(move(position))
|
: Node(move(position))
|
||||||
, m_source_fd(src)
|
, m_old_fd(src)
|
||||||
, m_dest_fd(dst)
|
, m_new_fd(dst)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,7 +1120,7 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non
|
||||||
}
|
}
|
||||||
auto& last_in_commands = commands.last();
|
auto& last_in_commands = commands.last();
|
||||||
|
|
||||||
last_in_commands.redirections.prepend(FdRedirection::create(STDOUT_FILENO, pipefd[1], Rewiring::Close::Destination));
|
last_in_commands.redirections.prepend(FdRedirection::create(pipefd[1], STDOUT_FILENO, Rewiring::Close::Old));
|
||||||
last_in_commands.should_wait = false;
|
last_in_commands.should_wait = false;
|
||||||
last_in_commands.should_notify_if_in_background = false;
|
last_in_commands.should_notify_if_in_background = false;
|
||||||
last_in_commands.is_pipe_source = false;
|
last_in_commands.is_pipe_source = false;
|
||||||
|
@ -1685,8 +1685,8 @@ RefPtr<Value> Pipe::run(RefPtr<Shell> shell)
|
||||||
auto last_in_left = left.take_last();
|
auto last_in_left = left.take_last();
|
||||||
auto first_in_right = right.take_first();
|
auto first_in_right = right.take_first();
|
||||||
|
|
||||||
auto pipe_read_end = FdRedirection::create(STDIN_FILENO, -1, Rewiring::Close::Destination);
|
auto pipe_read_end = FdRedirection::create(-1, STDIN_FILENO, Rewiring::Close::Old);
|
||||||
auto pipe_write_end = FdRedirection::create(STDOUT_FILENO, -1, pipe_read_end, Rewiring::Close::RefreshDestination);
|
auto pipe_write_end = FdRedirection::create(-1, STDOUT_FILENO, pipe_read_end, Rewiring::Close::RefreshOld);
|
||||||
first_in_right.redirections.append(pipe_read_end);
|
first_in_right.redirections.append(pipe_read_end);
|
||||||
last_in_left.redirections.append(pipe_write_end);
|
last_in_left.redirections.append(pipe_write_end);
|
||||||
last_in_left.should_wait = false;
|
last_in_left.should_wait = false;
|
||||||
|
@ -2810,7 +2810,7 @@ Vector<String> TildeValue::resolve_as_list(RefPtr<Shell> shell)
|
||||||
|
|
||||||
Result<NonnullRefPtr<Rewiring>, String> CloseRedirection::apply() const
|
Result<NonnullRefPtr<Rewiring>, String> CloseRedirection::apply() const
|
||||||
{
|
{
|
||||||
return adopt(*new Rewiring(fd, fd, Rewiring::Close::ImmediatelyCloseDestination));
|
return adopt(*new Rewiring(fd, fd, Rewiring::Close::ImmediatelyCloseNew));
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseRedirection::~CloseRedirection()
|
CloseRedirection::~CloseRedirection()
|
||||||
|
@ -2825,7 +2825,7 @@ Result<NonnullRefPtr<Rewiring>, String> PathRedirection::apply() const
|
||||||
dbg() << "open() failed for '" << path << "' with " << error;
|
dbg() << "open() failed for '" << path << "' with " << error;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
return adopt(*new Rewiring(my_fd, fd, Rewiring::Close::Destination));
|
return adopt(*new Rewiring(fd, my_fd, Rewiring::Close::Old));
|
||||||
};
|
};
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case AST::PathRedirection::WriteAppend:
|
case AST::PathRedirection::WriteAppend:
|
||||||
|
|
49
Shell/AST.h
49
Shell/AST.h
|
@ -63,27 +63,28 @@ struct Position {
|
||||||
|
|
||||||
struct FdRedirection;
|
struct FdRedirection;
|
||||||
struct Rewiring : public RefCounted<Rewiring> {
|
struct Rewiring : public RefCounted<Rewiring> {
|
||||||
int source_fd { -1 };
|
int old_fd { -1 };
|
||||||
int dest_fd { -1 };
|
int new_fd { -1 };
|
||||||
FdRedirection* other_pipe_end { nullptr };
|
FdRedirection* other_pipe_end { nullptr };
|
||||||
enum class Close {
|
enum class Close {
|
||||||
None,
|
None,
|
||||||
Source,
|
Old,
|
||||||
Destination,
|
New,
|
||||||
RefreshDestination,
|
RefreshNew,
|
||||||
ImmediatelyCloseDestination,
|
RefreshOld,
|
||||||
|
ImmediatelyCloseNew,
|
||||||
} fd_action { Close::None };
|
} fd_action { Close::None };
|
||||||
|
|
||||||
Rewiring(int source, int dest, Close close = Close::None)
|
Rewiring(int source, int dest, Close close = Close::None)
|
||||||
: source_fd(source)
|
: old_fd(source)
|
||||||
, dest_fd(dest)
|
, new_fd(dest)
|
||||||
, fd_action(close)
|
, fd_action(close)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Rewiring(int source, int dest, FdRedirection* other_end, Close close)
|
Rewiring(int source, int dest, FdRedirection* other_end, Close close)
|
||||||
: source_fd(source)
|
: old_fd(source)
|
||||||
, dest_fd(dest)
|
, new_fd(dest)
|
||||||
, other_pipe_end(other_end)
|
, other_pipe_end(other_end)
|
||||||
, fd_action(close)
|
, fd_action(close)
|
||||||
{
|
{
|
||||||
|
@ -143,25 +144,25 @@ private:
|
||||||
|
|
||||||
struct FdRedirection : public Redirection {
|
struct FdRedirection : public Redirection {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<FdRedirection> create(int source, int dest, Rewiring::Close close)
|
static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, Rewiring::Close close)
|
||||||
{
|
{
|
||||||
return adopt(*new FdRedirection(source, dest, close));
|
return adopt(*new FdRedirection(old_fd, new_fd, close));
|
||||||
}
|
}
|
||||||
|
|
||||||
static NonnullRefPtr<FdRedirection> create(int source, int dest, FdRedirection* pipe_end, Rewiring::Close close)
|
static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
|
||||||
{
|
{
|
||||||
return adopt(*new FdRedirection(source, dest, pipe_end, close));
|
return adopt(*new FdRedirection(old_fd, new_fd, pipe_end, close));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FdRedirection();
|
virtual ~FdRedirection();
|
||||||
|
|
||||||
virtual Result<NonnullRefPtr<Rewiring>, String> apply() const override
|
virtual Result<NonnullRefPtr<Rewiring>, String> apply() const override
|
||||||
{
|
{
|
||||||
return adopt(*new Rewiring(source_fd, dest_fd, other_pipe_end, action));
|
return adopt(*new Rewiring(old_fd, new_fd, other_pipe_end, action));
|
||||||
}
|
}
|
||||||
|
|
||||||
int source_fd { -1 };
|
int old_fd { -1 };
|
||||||
int dest_fd { -1 };
|
int new_fd { -1 };
|
||||||
FdRedirection* other_pipe_end { nullptr };
|
FdRedirection* other_pipe_end { nullptr };
|
||||||
Rewiring::Close action { Rewiring::Close::None };
|
Rewiring::Close action { Rewiring::Close::None };
|
||||||
|
|
||||||
|
@ -171,9 +172,9 @@ private:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FdRedirection(int source, int dest, FdRedirection* pipe_end, Rewiring::Close close)
|
FdRedirection(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
|
||||||
: source_fd(source)
|
: old_fd(old_fd)
|
||||||
, dest_fd(dest)
|
, new_fd(new_fd)
|
||||||
, other_pipe_end(pipe_end)
|
, other_pipe_end(pipe_end)
|
||||||
, action(close)
|
, action(close)
|
||||||
{
|
{
|
||||||
|
@ -748,8 +749,8 @@ public:
|
||||||
virtual ~Fd2FdRedirection();
|
virtual ~Fd2FdRedirection();
|
||||||
virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
|
virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
|
||||||
|
|
||||||
int source_fd() const { return m_source_fd; }
|
int source_fd() const { return m_old_fd; }
|
||||||
int dest_fd() const { return m_dest_fd; }
|
int dest_fd() const { return m_new_fd; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NODE(Fd2FdRedirection);
|
NODE(Fd2FdRedirection);
|
||||||
|
@ -758,8 +759,8 @@ private:
|
||||||
virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
|
virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
|
||||||
virtual bool is_command() const override { return true; }
|
virtual bool is_command() const override { return true; }
|
||||||
|
|
||||||
int m_source_fd { -1 };
|
int m_old_fd { -1 };
|
||||||
int m_dest_fd { -1 };
|
int m_new_fd { -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionDeclaration final : public Node {
|
class FunctionDeclaration final : public Node {
|
||||||
|
|
|
@ -823,7 +823,7 @@ bool Shell::run_builtin(const AST::Command& command, const NonnullRefPtrVector<A
|
||||||
SavedFileDescriptors fds { rewirings };
|
SavedFileDescriptors fds { rewirings };
|
||||||
|
|
||||||
for (auto& rewiring : rewirings) {
|
for (auto& rewiring : rewirings) {
|
||||||
int rc = dup2(rewiring.dest_fd, rewiring.source_fd);
|
int rc = dup2(rewiring.old_fd, rewiring.new_fd);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("dup2(run)");
|
perror("dup2(run)");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -582,17 +582,17 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
}
|
}
|
||||||
auto& rewiring = rewiring_result.value();
|
auto& rewiring = rewiring_result.value();
|
||||||
|
|
||||||
if (rewiring->fd_action != AST::Rewiring::Close::ImmediatelyCloseDestination)
|
if (rewiring->fd_action != AST::Rewiring::Close::ImmediatelyCloseNew)
|
||||||
rewirings.append(*rewiring);
|
rewirings.append(*rewiring);
|
||||||
|
|
||||||
if (rewiring->fd_action == AST::Rewiring::Close::Source) {
|
if (rewiring->fd_action == AST::Rewiring::Close::Old) {
|
||||||
fds.add(rewiring->source_fd);
|
fds.add(rewiring->old_fd);
|
||||||
} else if (rewiring->fd_action == AST::Rewiring::Close::Destination) {
|
} else if (rewiring->fd_action == AST::Rewiring::Close::New) {
|
||||||
if (rewiring->dest_fd != -1)
|
if (rewiring->new_fd != -1)
|
||||||
fds.add(rewiring->dest_fd);
|
fds.add(rewiring->new_fd);
|
||||||
} else if (rewiring->fd_action == AST::Rewiring::Close::ImmediatelyCloseDestination) {
|
} else if (rewiring->fd_action == AST::Rewiring::Close::ImmediatelyCloseNew) {
|
||||||
fds.add(rewiring->dest_fd);
|
fds.add(rewiring->new_fd);
|
||||||
} else if (rewiring->fd_action == AST::Rewiring::Close::RefreshDestination) {
|
} else if (rewiring->fd_action == AST::Rewiring::Close::RefreshNew) {
|
||||||
ASSERT(rewiring->other_pipe_end);
|
ASSERT(rewiring->other_pipe_end);
|
||||||
|
|
||||||
int pipe_fd[2];
|
int pipe_fd[2];
|
||||||
|
@ -601,8 +601,20 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
perror("pipe(RedirRefresh)");
|
perror("pipe(RedirRefresh)");
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
rewiring->dest_fd = pipe_fd[1];
|
rewiring->new_fd = pipe_fd[1];
|
||||||
rewiring->other_pipe_end->dest_fd = pipe_fd[0]; // This fd will be added to the collection on one of the next iterations.
|
rewiring->other_pipe_end->new_fd = pipe_fd[0]; // This fd will be added to the collection on one of the next iterations.
|
||||||
|
fds.add(pipe_fd[1]);
|
||||||
|
} else if (rewiring->fd_action == AST::Rewiring::Close::RefreshOld) {
|
||||||
|
ASSERT(rewiring->other_pipe_end);
|
||||||
|
|
||||||
|
int pipe_fd[2];
|
||||||
|
int rc = pipe(pipe_fd);
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("pipe(RedirRefresh)");
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
rewiring->old_fd = pipe_fd[1];
|
||||||
|
rewiring->other_pipe_end->old_fd = pipe_fd[0]; // This fd will be added to the collection on one of the next iterations.
|
||||||
fds.add(pipe_fd[1]);
|
fds.add(pipe_fd[1]);
|
||||||
}
|
}
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
@ -611,17 +623,24 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
auto apply_rewirings = [&] {
|
auto apply_rewirings = [&] {
|
||||||
for (auto& rewiring : rewirings) {
|
for (auto& rewiring : rewirings) {
|
||||||
#ifdef SH_DEBUG
|
#ifdef SH_DEBUG
|
||||||
dbgprintf("in %s<%d>, dup2(%d, %d)\n", command.argv.is_empty() ? "(<Empty>)" : command.argv[0].characters(), getpid(), rewiring.dest_fd, rewiring.source_fd);
|
dbgprintf("in %s<%d>, dup2(%d, %d)\n", command.argv.is_empty() ? "(<Empty>)" : command.argv[0].characters(), getpid(), rewiring.old_fd, rewiring.new_fd);
|
||||||
#endif
|
#endif
|
||||||
int rc = dup2(rewiring.dest_fd, rewiring.source_fd);
|
int rc = dup2(rewiring.old_fd, rewiring.new_fd);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("dup2(run)");
|
perror("dup2(run)");
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
// dest_fd is closed via the `fds` collector, but rewiring.other_pipe_end->dest_fd
|
// {new,old}_fd is closed via the `fds` collector, but rewiring.other_pipe_end->{new,old}_fd
|
||||||
// isn't yet in that collector when the first child spawns.
|
// isn't yet in that collector when the first child spawns.
|
||||||
if (rewiring.other_pipe_end && close(rewiring.other_pipe_end->dest_fd) < 0)
|
if (rewiring.other_pipe_end) {
|
||||||
perror("close other pipe end");
|
if (rewiring.fd_action == AST::Rewiring::Close::RefreshNew) {
|
||||||
|
if (rewiring.other_pipe_end && close(rewiring.other_pipe_end->new_fd) < 0)
|
||||||
|
perror("close other pipe end");
|
||||||
|
} else if (rewiring.fd_action == AST::Rewiring::Close::RefreshOld) {
|
||||||
|
if (rewiring.other_pipe_end && close(rewiring.other_pipe_end->old_fd) < 0)
|
||||||
|
perror("close other pipe end");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
@ -648,7 +667,7 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
SavedFileDescriptors fds { rewirings };
|
SavedFileDescriptors fds { rewirings };
|
||||||
|
|
||||||
for (auto& rewiring : rewirings) {
|
for (auto& rewiring : rewirings) {
|
||||||
int rc = dup2(rewiring.dest_fd, rewiring.source_fd);
|
int rc = dup2(rewiring.old_fd, rewiring.new_fd);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("dup2(run)");
|
perror("dup2(run)");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -878,7 +897,7 @@ NonnullRefPtrVector<Job> Shell::run_commands(Vector<AST::Command>& commands)
|
||||||
dbg() << "redir path " << (int)path_redir->direction << " " << path_redir->path << " <-> " << path_redir->fd;
|
dbg() << "redir path " << (int)path_redir->direction << " " << path_redir->path << " <-> " << path_redir->fd;
|
||||||
} else if (redir.is_fd_redirection()) {
|
} else if (redir.is_fd_redirection()) {
|
||||||
auto* fdredir = (const AST::FdRedirection*)&redir;
|
auto* fdredir = (const AST::FdRedirection*)&redir;
|
||||||
dbg() << "redir fd " << fdredir->source_fd << " -> " << fdredir->dest_fd;
|
dbg() << "redir fd " << fdredir->old_fd << " -> " << fdredir->new_fd;
|
||||||
} else if (redir.is_close_redirection()) {
|
} else if (redir.is_close_redirection()) {
|
||||||
auto close_redir = (const AST::CloseRedirection*)&redir;
|
auto close_redir = (const AST::CloseRedirection*)&redir;
|
||||||
dbg() << "close fd " << close_redir->fd;
|
dbg() << "close fd " << close_redir->fd;
|
||||||
|
@ -1662,7 +1681,7 @@ void FileDescriptionCollector::add(int fd)
|
||||||
SavedFileDescriptors::SavedFileDescriptors(const NonnullRefPtrVector<AST::Rewiring>& intended_rewirings)
|
SavedFileDescriptors::SavedFileDescriptors(const NonnullRefPtrVector<AST::Rewiring>& intended_rewirings)
|
||||||
{
|
{
|
||||||
for (auto& rewiring : intended_rewirings) {
|
for (auto& rewiring : intended_rewirings) {
|
||||||
int new_fd = dup(rewiring.source_fd);
|
int new_fd = dup(rewiring.new_fd);
|
||||||
if (new_fd < 0) {
|
if (new_fd < 0) {
|
||||||
if (errno != EBADF)
|
if (errno != EBADF)
|
||||||
perror("dup");
|
perror("dup");
|
||||||
|
@ -1676,7 +1695,7 @@ SavedFileDescriptors::SavedFileDescriptors(const NonnullRefPtrVector<AST::Rewiri
|
||||||
auto rc = fcntl(new_fd, F_SETFL, flags | FD_CLOEXEC);
|
auto rc = fcntl(new_fd, F_SETFL, flags | FD_CLOEXEC);
|
||||||
ASSERT(rc == 0);
|
ASSERT(rc == 0);
|
||||||
|
|
||||||
m_saves.append({ rewiring.source_fd, new_fd });
|
m_saves.append({ rewiring.new_fd, new_fd });
|
||||||
m_collector.add(new_fd);
|
m_collector.add(new_fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue