From 8898ec1f9cc92d18eb3c5d6301cc100da919dac7 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 12 Jul 2017 05:47:28 -0600 Subject: [PATCH] Pass window size change events to the plugin. --- doc/sudo_plugin.cat | 14 ++++++++++++- doc/sudo_plugin.man.in | 26 +++++++++++++++++++++++- doc/sudo_plugin.mdoc.in | 20 ++++++++++++++++++- include/sudo_plugin.h | 5 +++-- src/exec_pty.c | 44 +++++++++++++++++++++++++++++++++++++---- 5 files changed, 100 insertions(+), 9 deletions(-) diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat index 0bb30f2ec..2187ecf21 100644 --- a/doc/sudo_plugin.cat +++ b/doc/sudo_plugin.cat @@ -867,6 +867,7 @@ DDEESSCCRRIIPPTTIIOONN int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); + int (*change_winsize)(unsigned int lines, unsigned int cols); }; When an I/O plugin is loaded, ssuuddoo runs the command in a pseudo-tty. @@ -1124,6 +1125,14 @@ DDEESSCCRRIIPPTTIIOONN See the _P_o_l_i_c_y _p_l_u_g_i_n _A_P_I section for a description of deregister_hooks. + change_winsize + int (*change_winsize)(unsigned int lines, unsigned int cols); + + The cchhaannggee__wwiinnssiizzee() function is called whenever the window size of + the terminal changes from the initial values specified in the + user_info list. It returns 1 on success, 0 on failure, -1 if an + error occurred (which will terminate the running command). + _I_/_O _P_l_u_g_i_n _V_e_r_s_i_o_n _M_a_c_r_o_s Same as for the _P_o_l_i_c_y _p_l_u_g_i_n _A_P_I. @@ -1563,6 +1572,9 @@ PPLLUUGGIINN AAPPII CCHHAANNGGEELLOOGG Version 1.11 (sudo 1.8.20) The _t_i_m_e_o_u_t entry was added to the settings list. + Version 1.12 (sudo 1.8.21) + The change_winsize field was added to the io_plugin struct. + SSEEEE AALLSSOO sudo.conf(4), sudoers(4), sudo(1m) @@ -1592,4 +1604,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or https://www.sudo.ws/license.html for complete details. -Sudo 1.8.21 June 2, 2017 Sudo 1.8.21 +Sudo 1.8.21 July 11, 2017 Sudo 1.8.21 diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in index 4e169fccc..c4f038103 100644 --- a/doc/sudo_plugin.man.in +++ b/doc/sudo_plugin.man.in @@ -16,7 +16,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.TH "SUDO_PLUGIN" "5" "June 2, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDO_PLUGIN" "5" "July 11, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -1470,6 +1470,7 @@ struct io_plugin { int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); + int (*change_winsize)(unsigned int lines, unsigned int cols); }; .RE .fi @@ -1976,6 +1977,24 @@ See the \fIPolicy plugin API\fR section for a description of \fRderegister_hooks.\fR +.TP 6n +change_winsize +.nf +.RS 6n +int (*change_winsize)(unsigned int lines, unsigned int cols); +.RE +.fi +.RS 6n +.sp +The +\fBchange_winsize\fR() +function is called whenever the window size of the terminal changes from +the initial values specified in the +\fRuser_info\fR +list. +It returns 1 on success, 0 on failure, \-1 if an error occurred (which +will terminate the running command). +.RE .PP \fII/O Plugin Version Macros\fR .PP @@ -2794,6 +2813,11 @@ The entry was added to the \fRsettings\fR list. +.TP 6n +Version 1.12 (sudo 1.8.21) +The +\fRchange_winsize\fR +field was added to the io_plugin struct. .SH "SEE ALSO" sudo.conf(@mansectform@), sudoers(@mansectform@), diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in index 285ca6e55..d8bc3b910 100644 --- a/doc/sudo_plugin.mdoc.in +++ b/doc/sudo_plugin.mdoc.in @@ -14,7 +14,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 2, 2017 +.Dd July 11, 2017 .Dt SUDO_PLUGIN @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -1298,6 +1298,7 @@ struct io_plugin { int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); + int (*change_winsize)(unsigned int lines, unsigned int cols); }; .Ed .Pp @@ -1730,6 +1731,19 @@ See the .Sx Policy plugin API section for a description of .Li deregister_hooks. +.It change_winsize +.Bd -literal -compact +int (*change_winsize)(unsigned int lines, unsigned int cols); +.Ed +.Pp +The +.Fn change_winsize +function is called whenever the window size of the terminal changes from +the initial values specified in the +.Li user_info +list. +It returns 1 on success, 0 on failure, \-1 if an error occurred (which +will terminate the running command). .El .Pp .Em I/O Plugin Version Macros @@ -2447,6 +2461,10 @@ The entry was added to the .Li settings list. +.It Version 1.12 (sudo 1.8.21) +The +.Li change_winsize +field was added to the io_plugin struct. .El .Sh SEE ALSO .Xr sudo.conf @mansectform@ , diff --git a/include/sudo_plugin.h b/include/sudo_plugin.h index 309e2963b..a15ce1882 100644 --- a/include/sudo_plugin.h +++ b/include/sudo_plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2016 Todd C. Miller + * Copyright (c) 2009-2017 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,7 @@ /* API version major/minor */ #define SUDO_API_VERSION_MAJOR 1 -#define SUDO_API_VERSION_MINOR 11 +#define SUDO_API_VERSION_MINOR 12 #define SUDO_API_MKVERSION(x, y) (((x) << 16) | (y)) #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR) @@ -168,6 +168,7 @@ struct io_plugin { int (*log_stderr)(const char *buf, unsigned int len); void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); + int (*change_winsize)(unsigned int rows, unsigned int cols); }; /* Sudoers group plugin version major/minor */ diff --git a/src/exec_pty.c b/src/exec_pty.c index d8efb2979..c7cb64303 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -362,6 +362,38 @@ log_stderr(const char *buf, unsigned int n, struct io_buffer *iob) debug_return_bool(ret); } +/* Call I/O plugin stderr log method. */ +static void +log_winchange(unsigned int rows, unsigned int cols) +{ + struct plugin_container *plugin; + sigset_t omask; + debug_decl(log_winchange, SUDO_DEBUG_EXEC); + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + TAILQ_FOREACH(plugin, &io_plugins, entries) { + if (plugin->u.io->version < SUDO_API_MKVERSION(1, 12)) + continue; + if (plugin->u.io->change_winsize) { + int rc; + + sudo_debug_set_active_instance(plugin->debug_instance); + rc = plugin->u.io->change_winsize(rows, cols); + if (rc <= 0) { + if (rc < 0) { + /* Error: disable plugin's I/O function. */ + plugin->u.io->change_winsize = NULL; + } + break; + } + } + } + sudo_debug_set_active_instance(sudo_debug_instance); + sigprocmask(SIG_SETMASK, &omask, NULL); + + debug_return; +} + /* * Check whether we are running in the foregroup. * Updates the foreground global and does lazy init of the @@ -376,8 +408,8 @@ check_foreground(pid_t ppgrp) foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp; if (foreground && !tty_initialized) { if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) { - tty_initialized = true; sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]); + tty_initialized = true; } } } @@ -1266,8 +1298,8 @@ exec_pty(struct command_details *details, struct command_status *cstat) if (foreground) { /* Copy terminal attrs from user tty -> pty slave. */ if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) { - tty_initialized = true; sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]); + tty_initialized = true; } /* Start out in raw mode unless part of a pipeline or backgrounded. */ @@ -1516,7 +1548,8 @@ del_io_events(bool nonblocking) } /* - * Propagates tty size change signals to pty being used by the command. + * Propagates tty size change signals to pty being used by the command + * and passes new window size to the I/O plugin. */ static void sync_ttysize(int src, int dst) @@ -1526,9 +1559,12 @@ sync_ttysize(int src, int dst) debug_decl(sync_ttysize, SUDO_DEBUG_EXEC); if (ioctl(src, TIOCGWINSZ, &wsize) == 0) { - ioctl(dst, TIOCSWINSZ, &wsize); + (void)ioctl(dst, TIOCSWINSZ, &wsize); if ((pgrp = tcgetpgrp(dst)) != -1) killpg(pgrp, SIGWINCH); + + if (tty_initialized) + log_winchange(wsize.ws_row, wsize.ws_col); } debug_return; -- 2.40.0