diff options
author | 2014-01-16 23:57:37 +0000 | |
---|---|---|
committer | 2014-01-16 23:57:37 +0000 | |
commit | 58560c88da8dad162ac2766f1f39c5eb9e09a4ae (patch) | |
tree | d097b1d3f2a54b1bafb5cbcd810b769f82b5de2f | |
parent | 614631e0c5b2c56dc0069683040a2e88f9b04687 (diff) | |
download | paludis-58560c88da8dad162ac2766f1f39c5eb9e09a4ae.tar.gz paludis-58560c88da8dad162ac2766f1f39c5eb9e09a4ae.tar.xz |
Give PTYs a sensible size
Fixes: ticket:1298, Gentoo#484298
-rw-r--r-- | paludis/util/process.cc | 42 | ||||
-rw-r--r-- | paludis/util/pty.cc | 23 | ||||
-rw-r--r-- | paludis/util/pty.hh | 3 |
3 files changed, 61 insertions, 7 deletions
diff --git a/paludis/util/process.cc b/paludis/util/process.cc index 7b4356f97..ef00b003a 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 d2cbd4179..68c2c2e8c 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 94406fe3f..58d74859f 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(); |