aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-25 18:06:59 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-25 18:06:59 +0000
commitc320ebb2fdea399de080f4f4be1d93288ed8872c (patch)
treec30258f0b333cf138a5b124cb489cbde6b7284f2
parent64ae2fa8ece3b69fd0bd5865b28344f8dd89af5f (diff)
downloadpaludis-c320ebb2fdea399de080f4f4be1d93288ed8872c.tar.gz
paludis-c320ebb2fdea399de080f4f4be1d93288ed8872c.tar.xz
Allow stderr for system commands to be redirected. Make the message window auto scroll and display PStream stderr output.
-rw-r--r--paludis/util/system.cc44
-rw-r--r--paludis/util/system.hh16
-rw-r--r--src/gtkpaludis/message_window.cc38
-rw-r--r--src/gtkpaludis/message_window.hh3
4 files changed, 92 insertions, 9 deletions
diff --git a/paludis/util/system.cc b/paludis/util/system.cc
index 6cc12b4..22f0c13 100644
--- a/paludis/util/system.cc
+++ b/paludis/util/system.cc
@@ -39,6 +39,12 @@ using namespace paludis;
namespace
{
+ static int stdout_write_fd = -1;
+ static int stdout_close_fd = -1;
+
+ static int stderr_write_fd = -1;
+ static int stderr_close_fd = -1;
+
/**
* Runs a command in a directory if needed, wait for it to terminate
* and return its exit status.
@@ -55,6 +61,30 @@ namespace
if (-1 == chdir(stringify(*fsentry).c_str()))
throw RunCommandError("chdir failed: " + stringify(strerror(errno)));
+ if (-1 != stdout_write_fd)
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "dup2 " +
+ stringify(stdout_write_fd) + " 2");
+
+ if (-1 == dup2(stdout_write_fd, 1))
+ throw RunCommandError("dup2 failed");
+
+ if (-1 != stdout_close_fd)
+ close(stdout_close_fd);
+ }
+
+ if (-1 != stderr_write_fd)
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "dup2 " +
+ stringify(stderr_write_fd) + " 2");
+
+ if (-1 == dup2(stderr_write_fd, 2))
+ throw RunCommandError("dup2 failed");
+
+ if (-1 != stderr_close_fd)
+ close(stderr_close_fd);
+ }
+
Log::get_instance()->message(ll_debug, lc_no_context, "execl /bin/sh -c " + cmd);
execl("/bin/sh", "sh", "-c", cmd.c_str(), static_cast<char *>(0));
throw RunCommandError("execl /bin/sh -c '" + cmd + "' failed:"
@@ -74,6 +104,20 @@ namespace
}
}
+void
+paludis::set_run_command_stdout_fds(const int w, const int c)
+{
+ stdout_write_fd = w;
+ stdout_close_fd = c;
+}
+
+void
+paludis::set_run_command_stderr_fds(const int w, const int c)
+{
+ stderr_write_fd = w;
+ stderr_close_fd = c;
+}
+
GetenvError::GetenvError(const std::string & key) throw () :
Exception("Environment variable '" + key + "' not set")
{
diff --git a/paludis/util/system.hh b/paludis/util/system.hh
index a5c1482..f2bb984 100644
--- a/paludis/util/system.hh
+++ b/paludis/util/system.hh
@@ -106,6 +106,22 @@ namespace paludis
int run_command_in_directory(const std::string & cmd, const FSEntry & fsentry);
/**
+ * Set the stderr and close for stdout fds used by run_command and
+ * run_command_in_directory.
+ *
+ * \ingroup grpsystem
+ */
+ void set_run_command_stdout_fds(const int, const int);
+
+ /**
+ * Set the stderr and close for stderr fds used by run_command and
+ * run_command_in_directory.
+ *
+ * \ingroup grpsystem
+ */
+ void set_run_command_stderr_fds(const int, const int);
+
+ /**
* Make a command that's run in a particular environment.
*/
class MakeEnvCommand
diff --git a/src/gtkpaludis/message_window.cc b/src/gtkpaludis/message_window.cc
index 61ab344..5971a83 100644
--- a/src/gtkpaludis/message_window.cc
+++ b/src/gtkpaludis/message_window.cc
@@ -41,11 +41,13 @@ namespace paludis
InternalCounted<Implementation<MessageWindow> >
{
Pipe log_pipe;
- Pipe cmd_stderr_pipe;
+ Pipe command_stdout_pipe;
+ Pipe command_stderr_pipe;
MessageWindow * const owner;
Glib::RefPtr<Glib::IOChannel> log_connection;
- Glib::RefPtr<Glib::IOChannel> cmd_stderr_connection;
+ Glib::RefPtr<Glib::IOChannel> command_stdout_connection;
+ Glib::RefPtr<Glib::IOChannel> command_stderr_connection;
FDOutputStream stream;
Implementation(MessageWindow * const o);
@@ -54,16 +56,21 @@ namespace paludis
Implementation<MessageWindow>::Implementation(MessageWindow * const o) :
owner(o),
log_connection(Glib::IOChannel::create_from_fd(log_pipe.read_fd())),
- cmd_stderr_connection(Glib::IOChannel::create_from_fd(cmd_stderr_pipe.read_fd())),
+ command_stdout_connection(Glib::IOChannel::create_from_fd(command_stdout_pipe.read_fd())),
+ command_stderr_connection(Glib::IOChannel::create_from_fd(command_stderr_pipe.read_fd())),
stream(log_pipe.write_fd())
{
Glib::signal_io().connect(sigc::mem_fun(*owner, &MessageWindow::on_log_read),
log_pipe.read_fd(), Glib::IO_IN);
- Glib::signal_io().connect(sigc::mem_fun(*owner, &MessageWindow::on_cmd_stderr_read),
- cmd_stderr_pipe.read_fd(), Glib::IO_IN);
+ Glib::signal_io().connect(sigc::mem_fun(*owner, &MessageWindow::on_command_stdout_read),
+ command_stdout_pipe.read_fd(), Glib::IO_IN);
+ Glib::signal_io().connect(sigc::mem_fun(*owner, &MessageWindow::on_command_stderr_read),
+ command_stderr_pipe.read_fd(), Glib::IO_IN);
- PStream::set_stderr_fd(cmd_stderr_pipe.write_fd(), cmd_stderr_pipe.read_fd());
+ PStream::set_stderr_fd(command_stderr_pipe.write_fd(), command_stderr_pipe.read_fd());
+ set_run_command_stdout_fds(command_stdout_pipe.write_fd(), command_stdout_pipe.read_fd());
+ set_run_command_stderr_fds(command_stderr_pipe.write_fd(), command_stderr_pipe.read_fd());
Log::get_instance()->set_log_stream(&stream);
Log::get_instance()->message(ll_debug, lc_no_context, "Message window initialised");
@@ -96,13 +103,28 @@ MessageWindow::on_log_read(Glib::IOCondition io_condition)
}
bool
-MessageWindow::on_cmd_stderr_read(Glib::IOCondition io_condition)
+MessageWindow::on_command_stdout_read(Glib::IOCondition io_condition)
{
if (0 == io_condition & Glib::IO_IN)
return false;
Glib::ustring buf;
- _imp->cmd_stderr_connection->read_line(buf);
+ _imp->command_stdout_connection->read_line(buf);
+
+ get_buffer()->insert(get_buffer()->end(), buf);
+ scroll_to(get_buffer()->create_mark(get_buffer()->end()), 0.0, 0.0, 1.0);
+
+ return true;
+}
+
+bool
+MessageWindow::on_command_stderr_read(Glib::IOCondition io_condition)
+{
+ if (0 == io_condition & Glib::IO_IN)
+ return false;
+
+ Glib::ustring buf;
+ _imp->command_stderr_connection->read_line(buf);
get_buffer()->insert(get_buffer()->end(), buf);
scroll_to(get_buffer()->create_mark(get_buffer()->end()), 0.0, 0.0, 1.0);
diff --git a/src/gtkpaludis/message_window.hh b/src/gtkpaludis/message_window.hh
index 551146f..7a5e5c7 100644
--- a/src/gtkpaludis/message_window.hh
+++ b/src/gtkpaludis/message_window.hh
@@ -35,7 +35,8 @@ namespace paludis
virtual ~MessageWindow();
bool on_log_read(Glib::IOCondition);
- bool on_cmd_stderr_read(Glib::IOCondition);
+ bool on_command_stdout_read(Glib::IOCondition);
+ bool on_command_stderr_read(Glib::IOCondition);
};
}