diff --git a/Userland/Applets/Keymap/KeymapStatusWindow.cpp b/Userland/Applets/Keymap/KeymapStatusWindow.cpp index e2b2d9e317..ae4c1bd068 100644 --- a/Userland/Applets/Keymap/KeymapStatusWindow.cpp +++ b/Userland/Applets/Keymap/KeymapStatusWindow.cpp @@ -16,7 +16,7 @@ void KeymapStatusWidget::mousedown_event(GUI::MouseEvent& event) if (event.button() != GUI::MouseButton::Primary) return; - Core::Process::spawn("/bin/KeyboardSettings"); + MUST(Core::Process::spawn("/bin/KeyboardSettings")); } KeymapStatusWindow::KeymapStatusWindow() diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index 71fbde74cc..fd81e4263c 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/Userland/Applications/Browser/BrowserWindow.cpp @@ -302,7 +302,7 @@ void BrowserWindow::build_menus() settings_menu.add_separator(); auto open_settings_action = GUI::Action::create("&Settings", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/settings.png").release_value_but_fixme_should_propagate_errors(), [](auto&) { - Core::Process::spawn("/bin/BrowserSettings"); + MUST(Core::Process::spawn("/bin/BrowserSettings")); }); settings_menu.add_action(move(open_settings_action)); diff --git a/Userland/Applications/Settings/main.cpp b/Userland/Applications/Settings/main.cpp index 83329e7512..9d62b24a92 100644 --- a/Userland/Applications/Settings/main.cpp +++ b/Userland/Applications/Settings/main.cpp @@ -104,7 +104,7 @@ ErrorOr serenity_main(Main::Arguments arguments) auto launch_origin_rect = icon_view->to_widget_rect(icon_view->content_rect(index)).translated(icon_view->screen_relative_rect().location()); setenv("__libgui_launch_origin_rect", String::formatted("{},{},{},{}", launch_origin_rect.x(), launch_origin_rect.y(), launch_origin_rect.width(), launch_origin_rect.height()).characters(), 1); - Core::Process::spawn(executable); + MUST(Core::Process::spawn(executable)); }; auto statusbar = TRY(main_widget->try_add()); diff --git a/Userland/Applications/Terminal/main.cpp b/Userland/Applications/Terminal/main.cpp index e133f3c00c..3ebdae7b11 100644 --- a/Userland/Applications/Terminal/main.cpp +++ b/Userland/Applications/Terminal/main.cpp @@ -328,7 +328,7 @@ ErrorOr serenity_main(Main::Arguments arguments) auto open_settings_action = GUI::Action::create("&Settings", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/settings.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) { - Core::Process::spawn("/bin/TerminalSettings"); + MUST(Core::Process::spawn("/bin/TerminalSettings")); }); TRY(terminal->context_menu().try_add_separator()); @@ -336,7 +336,7 @@ ErrorOr serenity_main(Main::Arguments arguments) auto file_menu = TRY(window->try_add_menu("&File")); TRY(file_menu->try_add_action(GUI::Action::create("Open New &Terminal", { Mod_Ctrl | Mod_Shift, Key_N }, Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-terminal.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) { - Core::Process::spawn("/bin/Terminal"); + MUST(Core::Process::spawn("/bin/Terminal")); }))); TRY(file_menu->try_add_action(open_settings_action)); diff --git a/Userland/Applications/Welcome/WelcomeWidget.cpp b/Userland/Applications/Welcome/WelcomeWidget.cpp index e4583e417c..3ce0cacf6f 100644 --- a/Userland/Applications/Welcome/WelcomeWidget.cpp +++ b/Userland/Applications/Welcome/WelcomeWidget.cpp @@ -54,7 +54,7 @@ WelcomeWidget::WelcomeWidget() m_help_button = *find_descendant_of_type_named("help_button"); m_help_button->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/book-open.png").release_value_but_fixme_should_propagate_errors()); m_help_button->on_click = [](auto) { - Core::Process::spawn("/bin/Help"sv); + MUST(Core::Process::spawn("/bin/Help"sv)); }; m_new_button = *find_descendant_of_type_named("new_button"); diff --git a/Userland/Libraries/LibCore/Process.cpp b/Userland/Libraries/LibCore/Process.cpp index efdf3909e7..afa5fb1a3a 100644 --- a/Userland/Libraries/LibCore/Process.cpp +++ b/Userland/Libraries/LibCore/Process.cpp @@ -1,11 +1,14 @@ /* * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2022, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #include +#include #include +#include #include #include @@ -17,21 +20,65 @@ extern char** environ; namespace Core { -pid_t Process::spawn(StringView path) -{ - String path_string = path; +struct ArgvList { + String m_path; + Vector m_argv; - pid_t pid; - char const* argv[] = { path_string.characters(), nullptr }; - if ((errno = posix_spawn(&pid, path_string.characters(), nullptr, nullptr, const_cast(argv), environ))) { - perror("Process::spawn posix_spawn"); - } else { -#ifdef __serenity__ - if (disown(pid) < 0) - perror("Process::spawn disown"); -#endif + ArgvList(String path, size_t size) + : m_path { path } + { + m_argv.ensure_capacity(size + 2); + m_argv.append(m_path.characters()); } - return pid; + + void append(char const* arg) + { + m_argv.append(arg); + } + + Span get() + { + if (m_argv.is_empty() || m_argv.last() != nullptr) + m_argv.append(nullptr); + return m_argv; + } + + ErrorOr spawn() + { + auto pid = TRY(System::posix_spawn(m_path.characters(), nullptr, nullptr, const_cast(get().data()), environ)); +#ifdef __serenity__ + TRY(System::disown(pid)); +#endif + return pid; + } +}; + +ErrorOr Process::spawn(StringView path, Span arguments) +{ + ArgvList argv { path, arguments.size() }; + for (auto const& arg : arguments) + argv.append(arg.characters()); + return argv.spawn(); +} + +ErrorOr Process::spawn(StringView path, Span arguments) +{ + Vector backing_strings; + backing_strings.ensure_capacity(arguments.size()); + ArgvList argv { path, arguments.size() }; + for (auto const& arg : arguments) { + backing_strings.append(arg); + argv.append(backing_strings.last().characters()); + } + return argv.spawn(); +} + +ErrorOr Process::spawn(StringView path, Span arguments) +{ + ArgvList argv { path, arguments.size() }; + for (auto arg : arguments) + argv.append(arg); + return argv.spawn(); } } diff --git a/Userland/Libraries/LibCore/Process.h b/Userland/Libraries/LibCore/Process.h index 79820451e2..89f349d922 100644 --- a/Userland/Libraries/LibCore/Process.h +++ b/Userland/Libraries/LibCore/Process.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2022, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,12 +8,15 @@ #pragma once #include +#include namespace Core { class Process { public: - static pid_t spawn(StringView path); + static ErrorOr spawn(StringView path, Span arguments); + static ErrorOr spawn(StringView path, Span arguments); + static ErrorOr spawn(StringView path, Span arguments = {}); }; } diff --git a/Userland/Libraries/LibDesktop/AppFile.cpp b/Userland/Libraries/LibDesktop/AppFile.cpp index f46d765958..6d9ae97c46 100644 --- a/Userland/Libraries/LibDesktop/AppFile.cpp +++ b/Userland/Libraries/LibDesktop/AppFile.cpp @@ -130,7 +130,7 @@ bool AppFile::spawn() const return false; auto pid = Core::Process::spawn(executable()); - if (pid < 0) + if (pid.is_error()) return false; return true; diff --git a/Userland/Services/Taskbar/ClockWidget.cpp b/Userland/Services/Taskbar/ClockWidget.cpp index 4ccc1e7361..0c5a0649f6 100644 --- a/Userland/Services/Taskbar/ClockWidget.cpp +++ b/Userland/Services/Taskbar/ClockWidget.cpp @@ -154,7 +154,7 @@ ClockWidget::ClockWidget() m_calendar_launcher->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-calendar.png").release_value_but_fixme_should_propagate_errors()); m_calendar_launcher->set_tooltip("Calendar"); m_calendar_launcher->on_click = [](auto) { - Core::Process::spawn("/bin/Calendar"sv); + MUST(Core::Process::spawn("/bin/Calendar")); }; } diff --git a/Userland/Services/Taskbar/QuickLaunchWidget.cpp b/Userland/Services/Taskbar/QuickLaunchWidget.cpp index 6c253c2492..8687c713a9 100644 --- a/Userland/Services/Taskbar/QuickLaunchWidget.cpp +++ b/Userland/Services/Taskbar/QuickLaunchWidget.cpp @@ -48,9 +48,7 @@ ErrorOr QuickLaunchEntryAppFile::launch() const ErrorOr QuickLaunchEntryExecutable::launch() const { - auto pid = Core::Process::spawn(m_path); - if (pid < 0) - return Error::from_syscall("Core::Process::spawn", -errno); + TRY(Core::Process::spawn(m_path)); return {}; } diff --git a/Userland/Services/Taskbar/main.cpp b/Userland/Services/Taskbar/main.cpp index 4150145aa0..852663946e 100644 --- a/Userland/Services/Taskbar/main.cpp +++ b/Userland/Services/Taskbar/main.cpp @@ -109,7 +109,7 @@ ErrorOr> build_system_menu() auto system_menu = TRY(GUI::Menu::try_create("\xE2\x9A\xA1")); // HIGH VOLTAGE SIGN system_menu->add_action(GUI::Action::create("&About SerenityOS", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/ladyball.png").release_value_but_fixme_should_propagate_errors(), [](auto&) { - Core::Process::spawn("/bin/About"sv); + MUST(Core::Process::spawn("/bin/About"sv)); })); system_menu->add_separator(); @@ -229,12 +229,12 @@ ErrorOr> build_system_menu() } system_menu->add_action(GUI::Action::create("&Settings", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-settings.png").release_value_but_fixme_should_propagate_errors(), [](auto&) { - Core::Process::spawn("/bin/Settings"sv); + MUST(Core::Process::spawn("/bin/Settings"sv)); })); system_menu->add_separator(); system_menu->add_action(GUI::Action::create("&Help", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-help.png").release_value_but_fixme_should_propagate_errors(), [](auto&) { - Core::Process::spawn("/bin/Help"sv); + MUST(Core::Process::spawn("/bin/Help"sv)); })); system_menu->add_action(GUI::Action::create("&Run...", Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-run.png").release_value_but_fixme_should_propagate_errors(), [](auto&) { posix_spawn_file_actions_t spawn_actions;