/* 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