/* Copyright (C) 2002 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include #include namespace { extern "C" { /* Helper callback to invoke the actual sigc++ slot. * We don't need to worry about (un)referencing, since the * child process gets its own copy of the parent's memory anyway. */ static void child_setup_callback(void* user_data) { try { (*reinterpret_cast(user_data))(); } catch (...) { Glib::exception_handlers_invoke(); } } static void copy_output_buf(std::string* dest, const char* buf) { if (dest) { if (buf) *dest = buf; else dest->erase(); } } } // extern "C" } // anonymous namespace namespace Glib { /**** process spawning functions *******************************************/ void spawn_async_with_pipes(const std::string& working_directory, const std::vector& argv, const std::vector& envp, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, Pid* child_pid, int* standard_input, int* standard_output, int* standard_error) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; GError* gerror = nullptr; g_spawn_async_with_pipes(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), const_cast(Glib::ArrayHandler::vector_to_array(envp).data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, child_pid, standard_input, standard_output, standard_error, &gerror); if (gerror) Glib::Error::throw_exception(gerror); } void spawn_async_with_pipes(const std::string& working_directory, const std::vector& argv, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, Pid* child_pid, int* standard_input, int* standard_output, int* standard_error) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; GError* gerror = nullptr; g_spawn_async_with_pipes(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), nullptr, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, child_pid, standard_input, standard_output, standard_error, &gerror); if (gerror) Glib::Error::throw_exception(gerror); } void spawn_async(const std::string& working_directory, const std::vector& argv, const std::vector& envp, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, Pid* child_pid) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; GError* gerror = nullptr; g_spawn_async(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), const_cast(Glib::ArrayHandler::vector_to_array(envp).data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, child_pid, &gerror); if (gerror) Glib::Error::throw_exception(gerror); } void spawn_async(const std::string& working_directory, const std::vector& argv, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, Pid* child_pid) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; GError* gerror = nullptr; g_spawn_async(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), nullptr, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, child_pid, &gerror); if (gerror) Glib::Error::throw_exception(gerror); } void spawn_sync(const std::string& working_directory, const std::vector& argv, const std::vector& envp, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, std::string* standard_output, std::string* standard_error, int* wait_status) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; GError* gerror = nullptr; char* pch_buf_standard_output = nullptr; char* pch_buf_standard_error = nullptr; g_spawn_sync(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), const_cast(Glib::ArrayHandler::vector_to_array(envp).data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, (standard_output) ? &pch_buf_standard_output : nullptr, (standard_error) ? &pch_buf_standard_error : nullptr, wait_status, &gerror); auto buf_standard_output = make_unique_ptr_gfree(pch_buf_standard_output); auto buf_standard_error = make_unique_ptr_gfree(pch_buf_standard_error); if (gerror) Glib::Error::throw_exception(gerror); copy_output_buf(standard_output, buf_standard_output.get()); copy_output_buf(standard_error, buf_standard_error.get()); } void spawn_sync(const std::string& working_directory, const std::vector& argv, SpawnFlags flags, const SlotSpawnChildSetup& child_setup, std::string* standard_output, std::string* standard_error, int* wait_status) { const bool setup_slot = !child_setup.empty(); auto child_setup_ = child_setup; char* pch_buf_standard_output = nullptr; char* pch_buf_standard_error = nullptr; GError* gerror = nullptr; g_spawn_sync(Glib::c_str_or_nullptr(working_directory), const_cast(Glib::ArrayHandler::vector_to_array(argv).data()), nullptr, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : nullptr, (setup_slot) ? &child_setup_ : nullptr, (standard_output) ? &pch_buf_standard_output : nullptr, (standard_error) ? &pch_buf_standard_error : nullptr, wait_status, &gerror); auto buf_standard_output = make_unique_ptr_gfree(pch_buf_standard_output); auto buf_standard_error = make_unique_ptr_gfree(pch_buf_standard_error); if (gerror) Glib::Error::throw_exception(gerror); copy_output_buf(standard_output, buf_standard_output.get()); copy_output_buf(standard_error, buf_standard_error.get()); } void spawn_command_line_async(const std::string& command_line) { GError* gerror = nullptr; g_spawn_command_line_async(command_line.c_str(), &gerror); if (gerror) Glib::Error::throw_exception(gerror); } void spawn_command_line_sync(const std::string& command_line, std::string* standard_output, std::string* standard_error, int* wait_status) { char* pch_buf_standard_output = nullptr; char* pch_buf_standard_error = nullptr; GError* gerror = nullptr; g_spawn_command_line_sync(command_line.c_str(), (standard_output) ? &pch_buf_standard_output : nullptr, (standard_error) ? &pch_buf_standard_error : nullptr, wait_status, &gerror); auto buf_standard_output = make_unique_ptr_gfree(pch_buf_standard_output); auto buf_standard_error = make_unique_ptr_gfree(pch_buf_standard_error); if (gerror) Glib::Error::throw_exception(gerror); copy_output_buf(standard_output, buf_standard_output.get()); copy_output_buf(standard_error, buf_standard_error.get()); } void spawn_close_pid(Pid pid) { g_spawn_close_pid(pid); } } // namespace Glib