[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Patch for terminal modes
[Thread Prev] | [Thread Next]
- Subject: Patch for terminal modes
- From: vicalloy <hu@xxxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Wed, 16 Aug 2017 09:52:15 +0800
- To: libssh@xxxxxxxxxx
|
Attachment:
v0-7-ttymodes.diff
Description: Binary data
|
|
From e46654b5bb852e2946550b9bc422d9de9232f5e4 Mon Sep 17 00:00:00 2001 From: Hu Xiaomao <hu@xxxxxxxxxx> Date: Wed, 16 Aug 2017 09:15:18 +0800 Subject: [PATCH] Add function to support tty modes on Signed-off-by: Hu Xiaomao <hu@xxxxxxxxxx> --- include/libssh/libssh.h | 3 + include/libssh/priv.h | 6 ++ src/CMakeLists.txt | 7 ++ src/channels.c | 96 +++++++++++++++++++++------- src/ttymodes.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 256 insertions(+), 22 deletions(-) create mode 100644 src/ttymodes.c diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 3721489..50b8b5b 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -124,6 +124,7 @@ typedef struct ssh_session_struct* ssh_session; typedef struct ssh_string_struct* ssh_string; typedef struct ssh_event_struct* ssh_event; typedef void* ssh_gssapi_creds; +typedef void* ssh_termios; /* Socket type */ #ifdef _WIN32 @@ -396,6 +397,8 @@ LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd); LIBSSH_API int ssh_channel_request_pty(ssh_channel channel); LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term, int cols, int rows); +LIBSSH_API int ssh_channel_request_pty_size_modes(ssh_channel channel, const char *term, + int cols, int rows, ssh_termios termios); LIBSSH_API int ssh_channel_request_shell(ssh_channel channel); LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum); LIBSSH_API int ssh_channel_request_sftp(ssh_channel channel); diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 5a74915..8c34d39 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -256,6 +256,12 @@ unsigned char *bin_to_base64(const unsigned char *source, int len); int compress_buffer(ssh_session session,ssh_buffer buf); int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen); +#ifdef HAVE_TERMIOS_H +/* ttymodes.c */ +#include <termios.h> +ssh_buffer tty_make_modes(struct termios *termios_p); +#endif + /* match.c */ int match_hostname(const char *host, const char *pattern, unsigned int len); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1012ddf..1613b73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -206,6 +206,13 @@ if (WITH_ZLIB) ) endif(WITH_ZLIB) +if (HAVE_TERMIOS_H) + set(libssh_SRCS + ${libssh_SRCS} + ttymodes.c + ) +endif(HAVE_TERMIOS_H) + if (WITH_GSSAPI AND GSSAPI_FOUND) set(libssh_SRCS ${libssh_SRCS} diff --git a/src/channels.c b/src/channels.c index 30c3146..11fd02b 100644 --- a/src/channels.c +++ b/src/channels.c @@ -34,6 +34,7 @@ #include <arpa/inet.h> #endif +#include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" @@ -776,7 +777,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request) { #else SSH_LOG(SSH_LOG_WARNING, "Unhandled channel request %s", request); #endif - + SAFE_FREE(request); return SSH_PACKET_USED; @@ -1602,23 +1603,26 @@ error: /** * @brief Request a pty with a specific type and size. * - * @param[in] channel The channel to sent the request. + * @param[in] channel The channel to sent the request. * - * @param[in] terminal The terminal type ("vt100, xterm,..."). + * @param[in] terminal The terminal type ("vt100, xterm,..."). * - * @param[in] col The number of columns. + * @param[in] col The number of columns. * - * @param[in] row The number of rows. + * @param[in] row The number of rows. * - * @return SSH_OK on success, - * SSH_ERROR if an error occurred, - * SSH_AGAIN if in nonblocking mode and call has - * to be done again. + * @param[in] termios_p The termios used to set modes for pty + * + * @return SSH_OK on success, + * SSH_ERROR if an error occurred, + * SSH_AGAIN if in nonblocking mode and call has + * to be done again. */ -int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal, - int col, int row) { +int ssh_channel_request_pty_size_modes(ssh_channel channel, const char *terminal, + int col, int row, ssh_termios termios) { ssh_session session; ssh_buffer buffer = NULL; + ssh_buffer tty_modes_buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { @@ -1636,7 +1640,7 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal, rc = channel_request_pty_size1(channel,terminal, col, row); return rc; - } + } #endif switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: @@ -1651,15 +1655,41 @@ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal, goto error; } - rc = ssh_buffer_pack(buffer, - "sdddddb", - terminal, - col, - row, - 0, /* pix */ - 0, /* pix */ - 1, /* add a 0byte string */ - 0); +#ifdef HAVE_TERMIOS_H + if (termios != NULL) { + tty_modes_buffer = tty_make_modes(termios); + if (tty_modes_buffer == NULL) { + ssh_set_error_oom(session); + goto error; + } + } +#endif + + if (tty_modes_buffer != NULL) { + size_t tty_modes_buffer_size = tty_modes_buffer->used; + rc = ssh_buffer_pack(buffer, + "sdddddPb", + terminal, + col, + row, + 0, /* pix */ + 0, /* pix */ + 1 + tty_modes_buffer_size, /* add tty modes and a 0byte string */ + tty_modes_buffer_size, + tty_modes_buffer->data, + 0); + + } else { + rc = ssh_buffer_pack(buffer, + "sdddddb", + terminal, + col, + row, + 0, /* pix */ + 0, /* pix */ + 1, /* add a 0byte string */ + 0); + } if (rc != SSH_OK) { ssh_set_error_oom(session); @@ -1669,11 +1699,33 @@ pending: rc = channel_request(channel, "pty-req", buffer, 1); error: ssh_buffer_free(buffer); + ssh_buffer_free(tty_modes_buffer); return rc; } /** + * @brief Request a pty with a specific type and size. + * + * @param[in] channel The channel to sent the request. + * + * @param[in] terminal The terminal type ("vt100, xterm,..."). + * + * @param[in] col The number of columns. + * + * @param[in] row The number of rows. + * + * @return SSH_OK on success, + * SSH_ERROR if an error occurred, + * SSH_AGAIN if in nonblocking mode and call has + * to be done again. + */ +int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal, + int col, int row) { + return ssh_channel_request_pty_size_modes(channel, terminal, col, row, NULL); +} + +/** * @brief Request a PTY. * * @param[in] channel The channel to send the request. @@ -3264,7 +3316,7 @@ error: * forward the content of a socket to the channel. You still have to * use channel_read and channel_write for this. */ -int ssh_channel_open_x11(ssh_channel channel, +int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port) { ssh_session session; ssh_buffer payload = NULL; diff --git a/src/ttymodes.c b/src/ttymodes.c new file mode 100644 index 0000000..7437fd6 --- /dev/null +++ b/src/ttymodes.c @@ -0,0 +1,166 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2017 by Hu Xiaomao <hu@xxxxxxxxxx> + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ +#include <termios.h> + +#include <libssh/priv.h> +#include <libssh/libssh.h> +#include <libssh/buffer.h> + +static int tty_mode_flags[36][2] = { + /* c_iflag */ + {IGNPAR, 30}, + {PARMRK, 31}, + {INPCK, 32}, + {ISTRIP, 33}, + {INLCR, 34}, + {IGNCR, 35}, + {ICRNL, 36}, +#if defined(IUCLC) + {IUCLC, 37}, +#endif + {IXON, 38}, + {IXANY, 39}, + {IXOFF, 40}, +#ifdef IMAXBEL + {IMAXBEL,41}, +#endif /* IMAXBEL */ + + /* c_lflag */ + {ISIG, 50}, + {ICANON, 51}, +#ifdef XCASE + {XCASE, 52}, +#endif + {ECHO, 53}, + {ECHOE, 54}, + {ECHOK, 55}, + {ECHONL, 56}, + {NOFLSH, 57}, + {TOSTOP, 58}, +#ifdef IEXTEN + {IEXTEN, 59}, +#endif /* IEXTEN */ +#if defined(ECHOCTL) + {ECHOCTL, 60}, +#endif /* ECHOCTL */ +#ifdef ECHOKE + {ECHOKE, 61}, +#endif /* ECHOKE */ +#if defined(PENDIN) + {PENDIN, 62}, +#endif /* PENDIN */ + + /* c_oflag */ + {OPOST, 70}, +#if defined(OLCUC) + {OLCUC, 71}, +#endif +#ifdef ONLCR + {ONLCR, 72}, +#endif +#ifdef OCRNL + {OCRNL, 73}, +#endif +#ifdef ONOCR + {ONOCR, 74}, +#endif +#ifdef ONLRET + {ONLRET, 75}, +#endif + + /* c_cflag */ + {CS7, 90}, + {CS8, 91}, + {PARENB, 92}, + {PARODD, 93}, + + /* end flag */ + {0, 0} +}; + +static int buffer_add_ttymode(ssh_buffer buffer, int tty_mode[2], tcflag_t termios_flag) { + int rc = SSH_ERROR; + uint32_t mode_mark = tty_mode[0]; + uint8_t opcode = tty_mode[1]; + rc = buffer_add_u8(buffer, opcode); + if (rc != SSH_OK) { + return rc; + } + + uint32_t flag = htonl((termios_flag & mode_mark) != 0); + rc = buffer_add_u32(buffer, flag);\ + return rc; +} + +static inline tcflag_t get_termios_flag(struct termios termios, uint8_t opcode) { + if (opcode >= 30 && opcode < 50) { + return termios.c_iflag; + } + if (opcode >= 50 && opcode < 70) { + return termios.c_lflag; + } + if (opcode >= 70 && opcode < 90) { + return termios.c_oflag; + } + if (opcode >= 90 && opcode < 100) { + return termios.c_oflag; + } + return 0; +} + +static int buffer_add_tty_modes(ssh_buffer buffer, int tty_modes[][2], struct termios termios) { + int rc = SSH_ERROR; + int i = 0; + do { + tcflag_t termios_flag = get_termios_flag(termios, tty_modes[i][1]); + rc = buffer_add_ttymode(buffer, tty_modes[i], termios_flag); + i++; + if (rc != SSH_OK) { + return rc; + } + } while ( tty_modes[i][0] ); + return rc; +} + +/** + * @brief Encodes terminal modes + * + * @param[in] termios_p The termios used to set modes for tty + * + * @return A SSH buffer of Encoded terminal modes, NULL on error. + */ +ssh_buffer tty_make_modes(struct termios *termios_p) { + int rc = SSH_ERROR; + + ssh_buffer buffer = ssh_buffer_new(); + if (buffer == NULL) { + return NULL; + } + + rc = buffer_add_tty_modes(buffer, tty_mode_flags, *termios_p); + + if (rc != SSH_OK) { + ssh_buffer_free(buffer); + return NULL; + } + + return buffer; +} -- 2.8.1 |
Archive administrator: postmaster@lists.cynapses.org