// -*- c++ -*- /* $Id: spawn.ccg,v 1.8 2006/05/12 08:08:44 murrayc Exp $ */ /* 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 Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #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) { #ifdef GLIBMM_EXCEPTIONS_ENABLED try { #endif //GLIBMM_EXCEPTIONS_ENABLED (*reinterpret_cast*>(user_data))(); #ifdef GLIBMM_EXCEPTIONS_ENABLED } catch(...) { Glib::exception_handlers_invoke(); } #endif //GLIBMM_EXCEPTIONS_ENABLED } 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 Glib::ArrayHandle& argv, const Glib::ArrayHandle& envp, SpawnFlags flags, const sigc::slot& child_setup, Pid* child_pid, int* standard_input, int* standard_output, int* standard_error) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; GError* error = 0; g_spawn_async_with_pipes( working_directory.c_str(), const_cast(argv.data()), const_cast(envp.data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, child_pid, standard_input, standard_output, standard_error, &error); if(error) Glib::Error::throw_exception(error); } void spawn_async_with_pipes(const std::string& working_directory, const Glib::ArrayHandle& argv, SpawnFlags flags, const sigc::slot& child_setup, Pid* child_pid, int* standard_input, int* standard_output, int* standard_error) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; GError* error = 0; g_spawn_async_with_pipes( working_directory.c_str(), const_cast(argv.data()), 0, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, child_pid, standard_input, standard_output, standard_error, &error); if(error) Glib::Error::throw_exception(error); } void spawn_async(const std::string& working_directory, const Glib::ArrayHandle& argv, const Glib::ArrayHandle& envp, SpawnFlags flags, const sigc::slot& child_setup, Pid* child_pid) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; GError* error = 0; g_spawn_async( working_directory.c_str(), const_cast(argv.data()), const_cast(envp.data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, child_pid, &error); if(error) Glib::Error::throw_exception(error); } void spawn_async(const std::string& working_directory, const Glib::ArrayHandle& argv, SpawnFlags flags, const sigc::slot& child_setup, Pid* child_pid) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; GError* error = 0; g_spawn_async( working_directory.c_str(), const_cast(argv.data()), 0, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, child_pid, &error); if(error) Glib::Error::throw_exception(error); } void spawn_sync(const std::string& working_directory, const Glib::ArrayHandle& argv, const Glib::ArrayHandle& envp, SpawnFlags flags, const sigc::slot& child_setup, std::string* standard_output, std::string* standard_error, int* exit_status) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; Glib::ScopedPtr buf_standard_output; Glib::ScopedPtr buf_standard_error; GError* error = 0; g_spawn_sync( working_directory.c_str(), const_cast(argv.data()), const_cast(envp.data()), static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, (standard_output) ? buf_standard_output.addr() : 0, (standard_error) ? buf_standard_error.addr() : 0, exit_status, &error); if(error) Glib::Error::throw_exception(error); 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 Glib::ArrayHandle& argv, SpawnFlags flags, const sigc::slot& child_setup, std::string* standard_output, std::string* standard_error, int* exit_status) { const bool setup_slot = !child_setup.empty(); sigc::slot child_setup_ = child_setup; Glib::ScopedPtr buf_standard_output; Glib::ScopedPtr buf_standard_error; GError* error = 0; g_spawn_sync( working_directory.c_str(), const_cast(argv.data()), 0, static_cast(unsigned(flags)), (setup_slot) ? &child_setup_callback : 0, (setup_slot) ? &child_setup_ : 0, (standard_output) ? buf_standard_output.addr() : 0, (standard_error) ? buf_standard_error.addr() : 0, exit_status, &error); if(error) Glib::Error::throw_exception(error); 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* error = 0; g_spawn_command_line_async(command_line.c_str(), &error); if(error) Glib::Error::throw_exception(error); } void spawn_command_line_sync(const std::string& command_line, std::string* standard_output, std::string* standard_error, int* exit_status) { Glib::ScopedPtr buf_standard_output; Glib::ScopedPtr buf_standard_error; GError* error = 0; g_spawn_command_line_sync( command_line.c_str(), (standard_output) ? buf_standard_output.addr() : 0, (standard_error) ? buf_standard_error.addr() : 0, exit_status, &error); if(error) Glib::Error::throw_exception(error); 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