Process.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/DeprecatedString.h>
  8. #include <AK/Vector.h>
  9. #include <LibCore/Process.h>
  10. #include <LibCore/System.h>
  11. #include <errno.h>
  12. #include <spawn.h>
  13. #ifdef AK_OS_SERENITY
  14. # include <serenity.h>
  15. #endif
  16. extern char** environ;
  17. namespace Core {
  18. struct ArgvList {
  19. DeprecatedString m_path;
  20. DeprecatedString m_working_directory;
  21. Vector<char const*, 10> m_argv;
  22. ArgvList(DeprecatedString path, size_t size)
  23. : m_path { path }
  24. {
  25. m_argv.ensure_capacity(size + 2);
  26. m_argv.append(m_path.characters());
  27. }
  28. void append(char const* arg)
  29. {
  30. m_argv.append(arg);
  31. }
  32. Span<char const*> get()
  33. {
  34. if (m_argv.is_empty() || m_argv.last() != nullptr)
  35. m_argv.append(nullptr);
  36. return m_argv;
  37. }
  38. void set_working_directory(DeprecatedString const& working_directory)
  39. {
  40. m_working_directory = working_directory;
  41. }
  42. ErrorOr<pid_t> spawn()
  43. {
  44. #ifdef AK_OS_SERENITY
  45. posix_spawn_file_actions_t spawn_actions;
  46. posix_spawn_file_actions_init(&spawn_actions);
  47. if (!m_working_directory.is_empty())
  48. posix_spawn_file_actions_addchdir(&spawn_actions, m_working_directory.characters());
  49. auto pid = TRY(System::posix_spawn(m_path.view(), &spawn_actions, nullptr, const_cast<char**>(get().data()), environ));
  50. TRY(System::disown(pid));
  51. #else
  52. auto pid = TRY(System::posix_spawn(m_path.view(), nullptr, nullptr, const_cast<char**>(get().data()), environ));
  53. #endif
  54. return pid;
  55. }
  56. };
  57. ErrorOr<pid_t> Process::spawn(StringView path, Span<DeprecatedString const> arguments, DeprecatedString working_directory)
  58. {
  59. ArgvList argv { path, arguments.size() };
  60. for (auto const& arg : arguments)
  61. argv.append(arg.characters());
  62. argv.set_working_directory(working_directory);
  63. return argv.spawn();
  64. }
  65. ErrorOr<pid_t> Process::spawn(StringView path, Span<StringView const> arguments, DeprecatedString working_directory)
  66. {
  67. Vector<DeprecatedString> backing_strings;
  68. backing_strings.ensure_capacity(arguments.size());
  69. ArgvList argv { path, arguments.size() };
  70. for (auto const& arg : arguments) {
  71. backing_strings.append(arg);
  72. argv.append(backing_strings.last().characters());
  73. }
  74. argv.set_working_directory(working_directory);
  75. return argv.spawn();
  76. }
  77. ErrorOr<pid_t> Process::spawn(StringView path, Span<char const* const> arguments, DeprecatedString working_directory)
  78. {
  79. ArgvList argv { path, arguments.size() };
  80. for (auto arg : arguments)
  81. argv.append(arg);
  82. argv.set_working_directory(working_directory);
  83. return argv.spawn();
  84. }
  85. }