diff options
Diffstat (limited to 'Userland/Shell')
-rw-r--r-- | Userland/Shell/AST.cpp | 20 | ||||
-rw-r--r-- | Userland/Shell/Builtin.cpp | 14 | ||||
-rw-r--r-- | Userland/Shell/ImmediateFunctions.cpp | 6 | ||||
-rw-r--r-- | Userland/Shell/Parser.cpp | 4 | ||||
-rw-r--r-- | Userland/Shell/Shell.cpp | 53 | ||||
-rw-r--r-- | Userland/Shell/Shell.h | 10 | ||||
-rw-r--r-- | Userland/Shell/main.cpp | 2 |
7 files changed, 59 insertions, 50 deletions
diff --git a/Userland/Shell/AST.cpp b/Userland/Shell/AST.cpp index 8f079d10ab..095de9adbc 100644 --- a/Userland/Shell/AST.cpp +++ b/Userland/Shell/AST.cpp @@ -1000,7 +1000,7 @@ ErrorOr<RefPtr<Value>> DoubleQuotedString::run(RefPtr<Shell> shell) builder.join(""sv, values); - return make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors()); + return make_ref_counted<StringValue>(TRY(builder.to_string())); } ErrorOr<void> DoubleQuotedString::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata) @@ -1711,7 +1711,7 @@ ErrorOr<void> Execute::for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<Iter if (!shell) return {}; - auto commands = shell->expand_aliases(move(unexpanded_commands)); + auto commands = TRY(shell->expand_aliases(move(unexpanded_commands))); if (m_capture_stdout) { // Make sure that we're going to be running _something_. @@ -1751,12 +1751,12 @@ ErrorOr<void> Execute::for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<Iter NothingLeft, }; auto check_and_call = [&]() -> ErrorOr<CheckResult> { - auto ifs = shell->local_variable_or("IFS"sv, "\n"sv); + auto ifs = TRY(shell->local_variable_or("IFS"sv, "\n"sv)); - if (auto offset = stream.offset_of(ifs.bytes()).release_value_but_fixme_should_propagate_errors(); offset.has_value()) { + if (auto offset = TRY(stream.offset_of(ifs.bytes())); offset.has_value()) { auto line_end = offset.value(); if (line_end == 0) { - stream.discard(ifs.length()).release_value_but_fixme_should_propagate_errors(); + TRY(stream.discard(ifs.length())); if (shell->options.inline_exec_keep_empty_segments) if (TRY(callback(make_ref_counted<StringValue>(String {}))) == IterationDecision::Break) { @@ -3741,7 +3741,7 @@ StringValue::~StringValue() ErrorOr<String> StringValue::resolve_as_string(RefPtr<Shell> shell) { if (m_split.is_empty()) - return m_string; + return TRY(resolve_slices(shell, String { m_string }, m_slices)); return Value::resolve_as_string(shell); } @@ -3799,7 +3799,7 @@ ErrorOr<String> SimpleVariableValue::resolve_as_string(RefPtr<Shell> shell) return resolve_slices(shell, String {}, m_slices); if (auto value = TRY(resolve_without_cast(shell)); value != this) - return value->resolve_as_string(shell); + return resolve_slices(shell, TRY(value->resolve_as_string(shell)), m_slices); auto name = m_name.to_deprecated_string(); char* env_value = getenv(name.characters()); @@ -3826,7 +3826,7 @@ ErrorOr<NonnullRefPtr<Value>> SimpleVariableValue::resolve_without_cast(RefPtr<S { VERIFY(shell); - if (auto value = shell->lookup_local_variable(m_name)) { + if (auto value = TRY(shell->lookup_local_variable(m_name))) { auto result = value.release_nonnull(); // If a slice is applied, add it. if (!m_slices.is_empty()) @@ -3868,11 +3868,11 @@ ErrorOr<Vector<String>> SpecialVariableValue::resolve_as_list(RefPtr<Shell> shel case '$': return { resolve_slices(shell, Vector { TRY(String::number(getpid())) }, m_slices) }; case '*': - if (auto argv = shell->lookup_local_variable("ARGV"sv)) + if (auto argv = TRY(shell->lookup_local_variable("ARGV"sv))) return resolve_slices(shell, TRY(const_cast<Value&>(*argv).resolve_as_list(shell)), m_slices); return resolve_slices(shell, Vector<String> {}, m_slices); case '#': - if (auto argv = shell->lookup_local_variable("ARGV"sv)) { + if (auto argv = TRY(shell->lookup_local_variable("ARGV"sv))) { if (argv->is_list()) { auto list_argv = static_cast<AST::ListValue const*>(argv.ptr()); return { resolve_slices(shell, Vector { TRY(String::number(list_argv->values().size())) }, m_slices) }; diff --git a/Userland/Shell/Builtin.cpp b/Userland/Shell/Builtin.cpp index 9741ab0447..e2bb86365c 100644 --- a/Userland/Shell/Builtin.cpp +++ b/Userland/Shell/Builtin.cpp @@ -544,7 +544,7 @@ ErrorOr<int> Shell::builtin_export(Main::Arguments arguments) auto parts = value.split_limit('=', 2); if (parts.size() == 1) { - auto value = lookup_local_variable(parts[0]); + auto value = TRY(lookup_local_variable(parts[0])); if (value) { auto values = TRY(const_cast<AST::Value&>(*value).resolve_as_list(*this)); StringBuilder builder; @@ -932,7 +932,7 @@ ErrorOr<int> Shell::builtin_shift(Main::Arguments arguments) if (count < 1) return 0; - auto argv_ = lookup_local_variable("ARGV"sv); + auto argv_ = TRY(lookup_local_variable("ARGV"sv)); if (!argv_) { warnln("shift: ARGV is unset"); return 1; @@ -965,7 +965,7 @@ ErrorOr<int> Shell::builtin_source(Main::Arguments arguments) if (!parser.parse(arguments)) return 1; - auto previous_argv = lookup_local_variable("ARGV"sv); + auto previous_argv = TRY(lookup_local_variable("ARGV"sv)); ScopeGuard guard { [&] { if (!args.is_empty()) set_local_variable("ARGV", const_cast<AST::Value&>(*previous_argv)); @@ -1008,7 +1008,7 @@ ErrorOr<int> Shell::builtin_time(Main::Arguments arguments) for (auto& arg : args) command.argv.append(TRY(String::from_utf8(arg))); - auto commands = expand_aliases({ move(command) }); + auto commands = TRY(expand_aliases({ move(command) })); AK::Statistics iteration_times; @@ -1146,7 +1146,7 @@ ErrorOr<int> Shell::builtin_unset(Main::Arguments arguments) if (!did_touch_path && value == "PATH"sv) did_touch_path = true; - if (lookup_local_variable(value)) { + if (TRY(lookup_local_variable(value)) != nullptr) { unset_local_variable(value); } else { unsetenv(value.characters()); @@ -1175,7 +1175,7 @@ ErrorOr<int> Shell::builtin_not(Main::Arguments arguments) for (auto& arg : args) command.argv.unchecked_append(TRY(String::from_utf8(arg))); - auto commands = expand_aliases({ move(command) }); + auto commands = TRY(expand_aliases({ move(command) })); int exit_code = 1; auto found_a_job = false; for (auto& job : run_commands(commands)) { @@ -1351,7 +1351,7 @@ ErrorOr<int> Shell::builtin_argsparser_parse(Main::Arguments arguments) }; auto enlist = [&](auto name, auto value) -> ErrorOr<NonnullRefPtr<AST::Value>> { - auto variable = lookup_local_variable(name); + auto variable = TRY(lookup_local_variable(name)); if (variable) { auto list = TRY(const_cast<AST::Value&>(*variable).resolve_as_list(*this)); auto new_value = TRY(value->resolve_as_string(*this)); diff --git a/Userland/Shell/ImmediateFunctions.cpp b/Userland/Shell/ImmediateFunctions.cpp index 8d1f03d6be..7b48fbfc0d 100644 --- a/Userland/Shell/ImmediateFunctions.cpp +++ b/Userland/Shell/ImmediateFunctions.cpp @@ -465,7 +465,7 @@ ErrorOr<RefPtr<AST::Node>> Shell::immediate_value_or_default(AST::ImmediateExpre } auto name = TRY(TRY(const_cast<AST::Node&>(arguments.first()).run(*this))->resolve_as_string(*this)); - if (!local_variable_or(name, ""sv).is_empty()) + if (!TRY(local_variable_or(name, ""sv)).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); return arguments.last(); @@ -479,7 +479,7 @@ ErrorOr<RefPtr<AST::Node>> Shell::immediate_assign_default(AST::ImmediateExpress } auto name = TRY(TRY(const_cast<AST::Node&>(arguments.first()).run(*this))->resolve_as_string(*this)); - if (!local_variable_or(name, ""sv).is_empty()) + if (!TRY(local_variable_or(name, ""sv)).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); auto value = TRY(TRY(const_cast<AST::Node&>(arguments.last()).run(*this))->resolve_without_cast(*this)); @@ -496,7 +496,7 @@ ErrorOr<RefPtr<AST::Node>> Shell::immediate_error_if_empty(AST::ImmediateExpress } auto name = TRY(TRY(const_cast<AST::Node&>(arguments.first()).run(*this))->resolve_as_string(*this)); - if (!local_variable_or(name, ""sv).is_empty()) + if (!TRY(local_variable_or(name, ""sv)).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); auto error_value = TRY(TRY(const_cast<AST::Node&>(arguments.last()).run(*this))->resolve_as_string(*this)); diff --git a/Userland/Shell/Parser.cpp b/Userland/Shell/Parser.cpp index ec9ec35f99..18f01a265c 100644 --- a/Userland/Shell/Parser.cpp +++ b/Userland/Shell/Parser.cpp @@ -1903,8 +1903,8 @@ RefPtr<AST::Node> Parser::parse_bareword() auto first_slash_index = string.find_byte_offset('/'); if (first_slash_index.has_value()) { - username = string.substring_from_byte_offset(1, *first_slash_index).release_value_but_fixme_should_propagate_errors(); - string = string.substring_from_byte_offset(*first_slash_index + 1).release_value_but_fixme_should_propagate_errors(); + username = string.substring_from_byte_offset(1, *first_slash_index - 1).release_value_but_fixme_should_propagate_errors(); + string = string.substring_from_byte_offset(*first_slash_index).release_value_but_fixme_should_propagate_errors(); } else { username = string.substring_from_byte_offset(1).release_value_but_fixme_should_propagate_errors(); string = {}; diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index 6d5384679e..eaa16ba24b 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -289,11 +289,11 @@ Vector<DeprecatedString> Shell::expand_globs(Vector<StringView> path_segments, S } } -Vector<AST::Command> Shell::expand_aliases(Vector<AST::Command> initial_commands) +ErrorOr<Vector<AST::Command>> Shell::expand_aliases(Vector<AST::Command> initial_commands) { Vector<AST::Command> commands; - Function<void(AST::Command&)> resolve_aliases_and_append = [&](auto& command) { + Function<ErrorOr<void>(AST::Command&)> resolve_aliases_and_append = [&](auto& command) -> ErrorOr<void> { if (!command.argv.is_empty()) { auto alias = resolve_alias(command.argv[0]); if (!alias.is_null()) { @@ -308,12 +308,12 @@ Vector<AST::Command> Shell::expand_aliases(Vector<AST::Command> initial_commands NonnullRefPtr<AST::Node> substitute = adopt_ref(*new AST::Join(subcommand_nonnull->position(), subcommand_nonnull, adopt_ref(*new AST::CommandLiteral(subcommand_nonnull->position(), command)))); - auto res = substitute->run(*this).release_value_but_fixme_should_propagate_errors(); - for (auto& subst_command : res->resolve_as_commands(*this).release_value_but_fixme_should_propagate_errors()) { + auto res = TRY(substitute->run(*this)); + for (auto& subst_command : TRY(res->resolve_as_commands(*this))) { if (!subst_command.argv.is_empty() && subst_command.argv.first() == argv0) // Disallow an alias resolving to itself. commands.append(subst_command); else - resolve_aliases_and_append(subst_command); + TRY(resolve_aliases_and_append(subst_command)); } } else { commands.append(command); @@ -324,10 +324,12 @@ Vector<AST::Command> Shell::expand_aliases(Vector<AST::Command> initial_commands } else { commands.append(command); } + + return {}; }; for (auto& command : initial_commands) - resolve_aliases_and_append(command); + TRY(resolve_aliases_and_append(command)); return commands; } @@ -350,7 +352,7 @@ Shell::LocalFrame* Shell::find_frame_containing_local_variable(StringView name) return nullptr; } -RefPtr<AST::Value const> Shell::lookup_local_variable(StringView name) const +ErrorOr<RefPtr<AST::Value const>> Shell::lookup_local_variable(StringView name) const { if (auto* frame = find_frame_containing_local_variable(name)) return frame->local_variables.get(name).value(); @@ -361,13 +363,13 @@ RefPtr<AST::Value const> Shell::lookup_local_variable(StringView name) const return nullptr; } -RefPtr<AST::Value const> Shell::get_argument(size_t index) const +ErrorOr<RefPtr<AST::Value const>> Shell::get_argument(size_t index) const { if (index == 0) - return adopt_ref(*new AST::StringValue(String::from_deprecated_string(current_script).release_value_but_fixme_should_propagate_errors())); + return adopt_ref(*new AST::StringValue(TRY(String::from_deprecated_string(current_script)))); --index; - if (auto argv = lookup_local_variable("ARGV"sv)) { + if (auto argv = TRY(lookup_local_variable("ARGV"sv))) { if (argv->is_list_without_resolution()) { AST::ListValue const* list = static_cast<AST::ListValue const*>(argv.ptr()); if (list->values().size() <= index) @@ -385,12 +387,12 @@ RefPtr<AST::Value const> Shell::get_argument(size_t index) const return nullptr; } -DeprecatedString Shell::local_variable_or(StringView name, DeprecatedString const& replacement) const +ErrorOr<DeprecatedString> Shell::local_variable_or(StringView name, DeprecatedString const& replacement) const { - auto value = lookup_local_variable(name); + auto value = TRY(lookup_local_variable(name)); if (value) { StringBuilder builder; - builder.join(' ', const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)).release_value_but_fixme_should_propagate_errors()); + builder.join(' ', TRY(const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)))); return builder.to_deprecated_string(); } return replacement; @@ -1085,10 +1087,17 @@ bool Shell::is_allowed_to_modify_termios(const AST::Command& command) const return false; auto value = lookup_local_variable("PROGRAMS_ALLOWED_TO_MODIFY_DEFAULT_TERMIOS"sv); - if (!value) + if (value.is_error()) + return false; + + if (!value.value()) return false; - return const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)).release_value_but_fixme_should_propagate_errors().contains_slow(command.argv[0]); + auto result = const_cast<AST::Value&>(*value.value()).resolve_as_list(const_cast<Shell&>(*this)); + if (result.is_error()) + return false; + + return result.value().contains_slow(command.argv[0]); } void Shell::restore_ios() @@ -1428,13 +1437,13 @@ void Shell::remove_entry_from_cache(StringView entry) cached_path.remove(index); } -void Shell::highlight(Line::Editor& editor) const +ErrorOr<void> Shell::highlight(Line::Editor& editor) const { auto line = editor.line(); auto ast = parse(line, m_is_interactive); if (!ast) - return; - ast->highlight_in_editor(editor, const_cast<Shell&>(*this)).release_value_but_fixme_should_propagate_errors(); + return {}; + return ast->highlight_in_editor(editor, const_cast<Shell&>(*this)); } Vector<Line::CompletionSuggestion> Shell::complete() @@ -1697,15 +1706,15 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s AST::Command completion_command; completion_command.argv.append(program_name_storage); - completion_command = expand_aliases({ completion_command }).last(); + completion_command = TRY(expand_aliases({ completion_command })).last(); - auto completion_utility_name = String::formatted("_complete_{}", completion_command.argv[0]).release_value_but_fixme_should_propagate_errors(); + auto completion_utility_name = TRY(String::formatted("_complete_{}", completion_command.argv[0])); if (binary_search(cached_path.span(), completion_utility_name, nullptr, RunnablePathComparator {}) != nullptr) completion_command.argv[0] = completion_utility_name; else if (!options.invoke_program_for_autocomplete) return Error::from_string_literal("Refusing to use the program itself as completion source"); - completion_command.argv.extend({ String::from_utf8("--complete"sv).release_value_but_fixme_should_propagate_errors(), String::from_utf8_short_string("--"sv) }); + completion_command.argv.extend({ TRY(String::from_utf8("--complete"sv)), String::from_utf8_short_string("--"sv) }); struct Visitor : public AST::NodeVisitor { Visitor(Shell& shell, AST::Position position) @@ -1874,7 +1883,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s completion_command.argv.extend(visitor.list()); - auto devnull = String::from_utf8("/dev/null"sv).release_value_but_fixme_should_propagate_errors(); + auto devnull = TRY(String::from_utf8("/dev/null"sv)); completion_command.should_wait = true; completion_command.redirections.append(AST::PathRedirection::create(devnull, STDERR_FILENO, AST::PathRedirection::Write)); completion_command.redirections.append(AST::PathRedirection::create(devnull, STDIN_FILENO, AST::PathRedirection::Read)); diff --git a/Userland/Shell/Shell.h b/Userland/Shell/Shell.h index dd6a22502c..9d01900823 100644 --- a/Userland/Shell/Shell.h +++ b/Userland/Shell/Shell.h @@ -165,15 +165,15 @@ public: static DeprecatedString expand_tilde(StringView expression); static Vector<DeprecatedString> expand_globs(StringView path, StringView base); static Vector<DeprecatedString> expand_globs(Vector<StringView> path_segments, StringView base); - Vector<AST::Command> expand_aliases(Vector<AST::Command>); + ErrorOr<Vector<AST::Command>> expand_aliases(Vector<AST::Command>); DeprecatedString resolve_path(DeprecatedString) const; DeprecatedString resolve_alias(StringView) const; static bool has_history_event(StringView); - RefPtr<AST::Value const> get_argument(size_t) const; - RefPtr<AST::Value const> lookup_local_variable(StringView) const; - DeprecatedString local_variable_or(StringView, DeprecatedString const&) const; + ErrorOr<RefPtr<AST::Value const>> get_argument(size_t) const; + ErrorOr<RefPtr<AST::Value const>> lookup_local_variable(StringView) const; + ErrorOr<DeprecatedString> local_variable_or(StringView, DeprecatedString const&) const; void set_local_variable(DeprecatedString const&, RefPtr<AST::Value>, bool only_in_current_frame = false); void unset_local_variable(StringView, bool only_in_current_frame = false); @@ -276,7 +276,7 @@ public: No }; - void highlight(Line::Editor&) const; + ErrorOr<void> highlight(Line::Editor&) const; Vector<Line::CompletionSuggestion> complete(); Vector<Line::CompletionSuggestion> complete(StringView); Vector<Line::CompletionSuggestion> complete_program_name(StringView, size_t offset, EscapeMode = EscapeMode::Bareword); diff --git a/Userland/Shell/main.cpp b/Userland/Shell/main.cpp index 1ed6c8803e..631178feed 100644 --- a/Userland/Shell/main.cpp +++ b/Userland/Shell/main.cpp @@ -83,7 +83,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) if (cursor >= 0) editor.set_cursor(cursor); } - shell->highlight(editor); + (void)shell->highlight(editor); }; editor->on_tab_complete = [&](const Line::Editor&) { return shell->complete(); |