mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 22:18:11 +00:00
parent
0dac7af6c5
commit
c589625418
6 changed files with 81 additions and 13 deletions
|
@ -757,23 +757,41 @@ int Shell::builtin_unset(int argc, const char** argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Shell::run_builtin(int argc, const char** argv, int& retval)
|
||||
bool Shell::run_builtin(const AST::Command& command, const NonnullRefPtrVector<AST::Rewiring>& rewirings, int& retval)
|
||||
{
|
||||
if (argc == 0)
|
||||
if (command.argv.is_empty())
|
||||
return false;
|
||||
|
||||
StringView name { argv[0] };
|
||||
if (!has_builtin(command.argv.first()))
|
||||
return false;
|
||||
|
||||
Vector<const char*> argv;
|
||||
for (auto& arg : command.argv)
|
||||
argv.append(arg.characters());
|
||||
|
||||
argv.append(nullptr);
|
||||
|
||||
StringView name = command.argv.first();
|
||||
|
||||
SavedFileDescriptors fds { rewirings };
|
||||
|
||||
for (auto& rewiring : rewirings) {
|
||||
int rc = dup2(rewiring.dest_fd, rewiring.source_fd);
|
||||
if (rc < 0) {
|
||||
perror("dup2(run)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define __ENUMERATE_SHELL_BUILTIN(builtin) \
|
||||
if (name == #builtin) { \
|
||||
retval = builtin_##builtin(argc, argv); \
|
||||
retval = builtin_##builtin(argv.size() - 1, argv.data()); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
ENUMERATE_SHELL_BUILTINS();
|
||||
|
||||
#undef __ENUMERATE_SHELL_BUILTIN
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Forward.h"
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibCore/ElapsedTimer.h>
|
||||
|
@ -42,3 +44,18 @@ public:
|
|||
private:
|
||||
Vector<int, 32> m_fds;
|
||||
};
|
||||
|
||||
class SavedFileDescriptors {
|
||||
public:
|
||||
SavedFileDescriptors(const NonnullRefPtrVector<AST::Rewiring>&);
|
||||
~SavedFileDescriptors();
|
||||
|
||||
private:
|
||||
struct SavedFileDescriptor {
|
||||
int original { -1 };
|
||||
int saved { -1 };
|
||||
};
|
||||
|
||||
Vector<SavedFileDescriptor> m_saves;
|
||||
FileDescriptionCollector m_collector;
|
||||
};
|
||||
|
|
|
@ -33,5 +33,6 @@ class Node;
|
|||
class Value;
|
||||
class SyntaxError;
|
||||
class Pipeline;
|
||||
class Rewiring;
|
||||
|
||||
}
|
||||
|
|
|
@ -500,6 +500,10 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int retval = 0;
|
||||
if (run_builtin(command, rewirings, retval))
|
||||
return nullptr;
|
||||
|
||||
Vector<const char*> argv;
|
||||
Vector<String> copy_argv = command.argv;
|
||||
argv.ensure_capacity(command.argv.size() + 1);
|
||||
|
@ -509,10 +513,6 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
|||
|
||||
argv.append(nullptr);
|
||||
|
||||
int retval = 0;
|
||||
if (run_builtin(argv.size() - 1, argv.data(), retval))
|
||||
return nullptr;
|
||||
|
||||
int sync_pipe[2];
|
||||
if (pipe(sync_pipe) < 0) {
|
||||
perror("pipe");
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
RefPtr<Job> run_command(const AST::Command&);
|
||||
NonnullRefPtrVector<Job> run_commands(Vector<AST::Command>&);
|
||||
bool run_file(const String&, bool explicitly_invoked = true);
|
||||
bool run_builtin(int argc, const char** argv, int& retval);
|
||||
bool run_builtin(const AST::Command&, const NonnullRefPtrVector<AST::Rewiring>&, int& retval);
|
||||
bool has_builtin(const StringView&) const;
|
||||
void block_on_job(RefPtr<Job>);
|
||||
String prompt() const;
|
||||
|
|
|
@ -56,6 +56,38 @@ void FileDescriptionCollector::add(int fd)
|
|||
m_fds.append(fd);
|
||||
}
|
||||
|
||||
SavedFileDescriptors::SavedFileDescriptors(const NonnullRefPtrVector<AST::Rewiring>& intended_rewirings)
|
||||
{
|
||||
for (auto& rewiring : intended_rewirings) {
|
||||
int new_fd = dup(rewiring.source_fd);
|
||||
if (new_fd < 0) {
|
||||
if (errno != EBADF)
|
||||
perror("dup");
|
||||
// The fd that will be overwritten isn't open right now,
|
||||
// it will be cleaned up by the exec()-side collector
|
||||
// and we have nothing to do here, so just ignore this error.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto flags = fcntl(new_fd, F_GETFL);
|
||||
auto rc = fcntl(new_fd, F_SETFL, flags | FD_CLOEXEC);
|
||||
ASSERT(rc == 0);
|
||||
|
||||
m_saves.append({ rewiring.source_fd, new_fd });
|
||||
m_collector.add(new_fd);
|
||||
}
|
||||
}
|
||||
|
||||
SavedFileDescriptors::~SavedFileDescriptors()
|
||||
{
|
||||
for (auto& save : m_saves) {
|
||||
if (dup2(save.saved, save.original) < 0) {
|
||||
perror("dup2(~SavedFileDescriptors)");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Core::EventLoop loop;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue