aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2014-01-16 23:57:37 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2014-01-16 23:57:37 +0000
commit58560c88da8dad162ac2766f1f39c5eb9e09a4ae (patch)
treed097b1d3f2a54b1bafb5cbcd810b769f82b5de2f
parent614631e0c5b2c56dc0069683040a2e88f9b04687 (diff)
downloadpaludis-58560c88da8dad162ac2766f1f39c5eb9e09a4ae.tar.gz
paludis-58560c88da8dad162ac2766f1f39c5eb9e09a4ae.tar.xz
Give PTYs a sensible size
Fixes: ticket:1298, Gentoo#484298
-rw-r--r--paludis/util/process.cc42
-rw-r--r--paludis/util/pty.cc23
-rw-r--r--paludis/util/pty.hh3
3 files changed, 61 insertions, 7 deletions
diff --git a/paludis/util/process.cc b/paludis/util/process.cc
index 7b4356f..ef00b00 100644
--- a/paludis/util/process.cc
+++ b/paludis/util/process.cc
@@ -46,6 +46,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>
+#include <sys/ioctl.h>
using namespace paludis;
@@ -561,6 +562,9 @@ Process::run()
if (_imp->echo_command_to)
_imp->command.echo_command_to(*_imp->echo_command_to);
+ bool set_tty_size_envvars(false);
+ unsigned short columns(80), lines(24);
+
std::unique_ptr<RunningProcessThread> thread;
if (_imp->need_thread)
{
@@ -589,11 +593,39 @@ Process::run()
thread->extra_newlines_if_any_output_exists = _imp->extra_newlines_if_any_output_exists;
+ if ((_imp->capture_stdout || _imp->capture_stderr) && _imp->use_ptys)
+ {
+ int tty(::open("/dev/tty", O_RDONLY | O_CLOEXEC));
+ if (-1 == tty)
+ Log::get_instance()->message("util.system.gwinsz.open_failed", ll_debug, lc_context)
+ << "open(/dev/tty) failed: " + std::string(std::strerror(errno));
+ else
+ {
+ struct winsize ws;
+ if (-1 == ::ioctl(tty, TIOCGWINSZ, &ws))
+ Log::get_instance()->message("util.system.gwinsz.ioctl_failed", ll_warning, lc_context)
+ << "ioctl(TIOCGWINSZ) failed: " + std::string(std::strerror(errno));
+ else if (0 == ws.ws_col || 0 == ws.ws_row)
+ Log::get_instance()->message("util.system.gwinsz.dodgy", ll_warning, lc_context)
+ << "Got zero for terminal columns and/or lines (" << ws.ws_col << "x" << ws.ws_row << "), ignoring";
+ else
+ {
+ columns = ws.ws_col;
+ lines = ws.ws_row;
+ }
+ if (-1 == ::close(tty))
+ throw InternalError(PALUDIS_HERE, "close(/dev/tty) failed: " + std::string(std::strerror(errno)));
+ }
+ Log::get_instance()->message("util.system.gwinsz", ll_debug, lc_context)
+ << "Terminal size is " << columns << "x" << lines;
+ set_tty_size_envvars = true;
+ }
+
if (_imp->capture_stdout)
{
thread->capture_stdout = _imp->capture_stdout;
if (_imp->use_ptys)
- thread->capture_stdout_pipe.reset(new Pty(true));
+ thread->capture_stdout_pipe.reset(new Pty(true, columns, lines));
else
thread->capture_stdout_pipe.reset(new Pipe(true));
}
@@ -602,7 +634,7 @@ Process::run()
{
thread->capture_stderr = _imp->capture_stderr;
if (_imp->use_ptys)
- thread->capture_stderr_pipe.reset(new Pty(true));
+ thread->capture_stderr_pipe.reset(new Pty(true, columns, lines));
else
thread->capture_stderr_pipe.reset(new Pipe(true));
}
@@ -749,6 +781,12 @@ Process::run()
throw ProcessError("dup2() failed");
}
+ if (set_tty_size_envvars)
+ {
+ ::setenv("COLUMNS", stringify(columns).c_str(), 1);
+ ::setenv("LINES", stringify(lines).c_str(), 1);
+ }
+
for (auto m(_imp->setenvs.begin()), m_end(_imp->setenvs.end()) ;
m != m_end ; ++m)
::setenv(m->first.c_str(), m->second.c_str(), 1);
diff --git a/paludis/util/pty.cc b/paludis/util/pty.cc
index d2cbd41..68c2c2e 100644
--- a/paludis/util/pty.cc
+++ b/paludis/util/pty.cc
@@ -26,6 +26,7 @@
#include <errno.h>
#include <cstring>
#include <unistd.h>
+#include <sys/ioctl.h>
#include "config.h"
#ifdef HAVE_PTSNAME_R
@@ -41,16 +42,16 @@ PtyError::PtyError(const std::string & our_message) throw () :
Pty::Pty()
{
- _init(false);
+ _init(false, 0, 0);
}
-Pty::Pty(const bool close_exec)
+Pty::Pty(const bool close_exec, const unsigned short columns, const unsigned short lines)
{
- _init(close_exec);
+ _init(close_exec, columns, lines);
}
void
-Pty::_init(const bool close_exec)
+Pty::_init(const bool close_exec, const unsigned short columns, const unsigned short lines)
{
Context context("When creating pty FDs:");
@@ -100,6 +101,20 @@ Pty::_init(const bool close_exec)
Log::get_instance()->message("util.pty.fds", ll_debug, lc_context) << "Pty FDs are '" << read_fd() << "', '"
<< write_fd() << "'";
+
+ if (0 != columns && 0 != lines)
+ {
+ struct winsize ws;
+ ws.ws_row = lines;
+ ws.ws_col = columns;
+ ws.ws_xpixel = ws.ws_ypixel = 0;
+ if (-1 == ioctl(_fds[1], TIOCSWINSZ, &ws))
+ Log::get_instance()->message("util.pty.swinsz.failed", ll_warning, lc_context)
+ << "ioctl(TIOCSWINSZ, { .ws_row = " << lines << ", .ws_col = " << columns << " }) failed: " + std::string(std::strerror(errno));
+ else
+ Log::get_instance()->message("util.pty.swinsz", ll_debug, lc_context)
+ << "Set Pty size to " << columns << "x" << lines;
+ }
}
Pty::~Pty()
diff --git a/paludis/util/pty.hh b/paludis/util/pty.hh
index 94406fe..58d7485 100644
--- a/paludis/util/pty.hh
+++ b/paludis/util/pty.hh
@@ -65,7 +65,7 @@ namespace paludis
public Channel
{
private:
- void _init(const bool);
+ void _init(const bool, const unsigned short columns, const unsigned short lines);
public:
///\name Basic operations
@@ -73,6 +73,7 @@ namespace paludis
Pty();
explicit Pty(const bool close_exec);
+ explicit Pty(const bool close_exec, const unsigned short columns, const unsigned short lines);
virtual ~Pty();