diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-04-23 19:09:13 +0430 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-04-23 20:27:58 +0200 |
commit | 0d2602c900757a49f228d6a4099f8dd7993a4982 (patch) | |
tree | dbbdb2eb70f193c8a57436e4be9acc8824e2a1b8 /Userland | |
parent | 95055d3a382a512dc3fe5ad8f2336aa6ba6b0390 (diff) | |
download | serenity-0d2602c900757a49f228d6a4099f8dd7993a4982.zip |
Shell: Add a 'kill' builtin that wraps the system's own
Fixes #6578.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Shell/Builtin.cpp | 37 | ||||
-rw-r--r-- | Userland/Shell/Shell.cpp | 21 | ||||
-rw-r--r-- | Userland/Shell/Shell.h | 5 |
3 files changed, 62 insertions, 1 deletions
diff --git a/Userland/Shell/Builtin.cpp b/Userland/Shell/Builtin.cpp index d5d72b21a5..aea7492449 100644 --- a/Userland/Shell/Builtin.cpp +++ b/Userland/Shell/Builtin.cpp @@ -1031,6 +1031,43 @@ int Shell::builtin_not(int argc, const char** argv) return exit_code == 0 ? 1 : 0; } +int Shell::builtin_kill(int argc, const char** argv) +{ + // Simply translate the arguments and pass them to `kill' + Vector<String> replaced_values; + auto kill_path = find_in_path("kill"); + if (kill_path.is_empty()) { + warnln("kill: `kill' not found in PATH"); + return 126; + } + replaced_values.append(kill_path); + for (auto i = 1; i < argc; ++i) { + if (auto job_id = resolve_job_spec(argv[i]); job_id.has_value()) { + auto job = find_job(job_id.value()); + if (job) { + replaced_values.append(String::number(job->pid())); + } else { + warnln("kill: Job with pid {} not found", job_id.value()); + return 1; + } + } else { + replaced_values.append(argv[i]); + } + } + + // Now just run `kill' + AST::Command command; + command.argv = move(replaced_values); + command.position = m_source_position.has_value() ? m_source_position->position : Optional<AST::Position> {}; + + auto exit_code = 1; + if (auto job = run_command(command)) { + block_on_job(job); + exit_code = job->exit_code(); + } + return exit_code; +} + bool Shell::run_builtin(const AST::Command& command, const NonnullRefPtrVector<AST::Rewiring>& rewirings, int& retval) { if (command.argv.is_empty()) diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index cdeb65031d..4d5bb1fded 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -1194,6 +1194,27 @@ String Shell::unescape_token(const String& token) return builder.build(); } +String Shell::find_in_path(const StringView& program_name) +{ + String path = getenv("PATH"); + if (!path.is_empty()) { + auto directories = path.split(':'); + for (const auto& directory : directories) { + Core::DirIterator programs(directory.characters(), Core::DirIterator::SkipDots); + while (programs.has_next()) { + auto program = programs.next_path(); + auto program_path = String::formatted("{}/{}", directory, program); + if (access(program_path.characters(), X_OK) != 0) + continue; + if (program == program_name) + return program_path; + } + } + } + + return {}; +} + void Shell::cache_path() { if (!m_is_interactive) diff --git a/Userland/Shell/Shell.h b/Userland/Shell/Shell.h index abd2a9608a..4559cefac9 100644 --- a/Userland/Shell/Shell.h +++ b/Userland/Shell/Shell.h @@ -46,7 +46,8 @@ __ENUMERATE_SHELL_BUILTIN(fg) \ __ENUMERATE_SHELL_BUILTIN(bg) \ __ENUMERATE_SHELL_BUILTIN(wait) \ - __ENUMERATE_SHELL_BUILTIN(dump) + __ENUMERATE_SHELL_BUILTIN(dump) \ + __ENUMERATE_SHELL_BUILTIN(kill) #define ENUMERATE_SHELL_OPTIONS() \ __ENUMERATE_SHELL_OPTION(inline_exec_keep_empty_segments, false, "Keep empty segments in inline execute $(...)") \ @@ -103,6 +104,8 @@ public: String resolve_path(String) const; String resolve_alias(const String&) const; + static String find_in_path(const StringView& program_name); + static bool has_history_event(StringView); RefPtr<AST::Value> get_argument(size_t); |