diff options
author | Matt Johnston <matt@ucc.asn.au> | 2004-08-01 08:54:01 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2004-08-01 08:54:01 +0000 |
commit | 051b7454f80a52d2b0bea2e34562949a3bc70fe4 (patch) | |
tree | 4414c89d8e9ffc08d15721d3d02756b6f0dcdd83 /svr-chansession.c | |
parent | cb071834dab43b2edf6112a9918714691f27f3de (diff) |
- Added terminal mode handling etc for the client, and window change
- Refactored the terminal-mode handling for the server
- Improved session closing for the client
--HG--
extra : convert_revision : 9d19b4f22c39798af5f3f24c2022f8caec4919e8
Diffstat (limited to 'svr-chansession.c')
-rw-r--r-- | svr-chansession.c | 196 |
1 files changed, 100 insertions, 96 deletions
diff --git a/svr-chansession.c b/svr-chansession.c index 50e0a5e..9639961 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -56,6 +56,7 @@ static void chansessionrequest(struct Channel *channel); static void send_exitsignalstatus(struct Channel *channel); static int sesscheckclose(struct Channel *channel); +static void get_termmodes(struct ChanSess *chansess); /* required to clear environment */ @@ -192,10 +193,6 @@ static int newchansess(struct Channel *channel) { chansess->slave = -1; chansess->tty = NULL; chansess->term = NULL; - chansess->termw = 0; - chansess->termh = 0; - chansess->termc = 0; - chansess->termr = 0; chansess->exited = 0; @@ -376,22 +373,111 @@ static int sessionsignal(struct ChanSess *chansess) { * client. Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ static int sessionwinchange(struct ChanSess *chansess) { + int termc, termr, termw, termh; + if (chansess->master < 0) { /* haven't got a pty yet */ return DROPBEAR_FAILURE; } - chansess->termc = buf_getint(ses.payload); - chansess->termr = buf_getint(ses.payload); - chansess->termw = buf_getint(ses.payload); - chansess->termh = buf_getint(ses.payload); + termc = buf_getint(ses.payload); + termr = buf_getint(ses.payload); + termw = buf_getint(ses.payload); + termh = buf_getint(ses.payload); - pty_change_window_size(chansess->master, chansess->termr, chansess->termc, - chansess->termw, chansess->termh); + pty_change_window_size(chansess->master, termr, termc, termw, termh); return DROPBEAR_FAILURE; } +static void get_termmodes(struct ChanSess *chansess) { + + struct termios termio; + unsigned char opcode; + unsigned int value; + const struct TermCode * termcode; + unsigned int len; + + TRACE(("enter get_termmodes")); + + /* Term modes */ + /* We'll ignore errors and continue if we can't set modes. + * We're ignoring baud rates since they seem evil */ + if (tcgetattr(chansess->master, &termio) == -1) { + return; + } + + len = buf_getint(ses.payload); + if (len != ses.payload->len - ses.payload->pos) { + dropbear_exit("bad term mode string"); + } + + if (len == 0) { + TRACE(("leave get_termmodes: empty terminal modes string")); + } + + while (((opcode = buf_getbyte(ses.payload)) != 0x00) && opcode <= 159) { + + /* must be before checking type, so that value is consumed even if + * we don't use it */ + value = buf_getint(ses.payload); + + /* handle types of code */ + if (opcode > MAX_TERMCODE) { + continue; + } + termcode = &termcodes[(unsigned int)opcode]; + + + switch (termcode->type) { + + case TERMCODE_NONE: + break; + + case TERMCODE_CONTROLCHAR: + termio.c_cc[termcode->mapcode] = value; + break; + + case TERMCODE_INPUT: + if (value) { + termio.c_iflag |= termcode->mapcode; + } else { + termio.c_iflag &= ~(termcode->mapcode); + } + break; + + case TERMCODE_OUTPUT: + if (value) { + termio.c_oflag |= termcode->mapcode; + } else { + termio.c_oflag &= ~(termcode->mapcode); + } + break; + + case TERMCODE_LOCAL: + if (value) { + termio.c_lflag |= termcode->mapcode; + } else { + termio.c_lflag &= ~(termcode->mapcode); + } + break; + + case TERMCODE_CONTROL: + if (value) { + termio.c_cflag |= termcode->mapcode; + } else { + termio.c_cflag &= ~(termcode->mapcode); + } + break; + + } + } + if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) { + dropbear_log(LOG_INFO, "error setting terminal attributes"); + } + TRACE(("leave get_termmodes")); +} + /* Set up a session pty which will be used to execute the shell or program. * The pty is allocated now, and kept for when the shell/program executes. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ @@ -399,7 +485,6 @@ static int sessionpty(struct ChanSess * chansess) { unsigned int termlen; unsigned char namebuf[65]; - struct termios termio; TRACE(("enter sessionpty")); chansess->term = buf_getstring(ses.payload, &termlen); @@ -408,10 +493,6 @@ static int sessionpty(struct ChanSess * chansess) { TRACE(("leave sessionpty: term len too long")); return DROPBEAR_FAILURE; } - chansess->termc = buf_getint(ses.payload); - chansess->termr = buf_getint(ses.payload); - chansess->termw = buf_getint(ses.payload); - chansess->termh = buf_getint(ses.payload); /* allocate the pty */ assert(chansess->master == -1); /* haven't already got one */ @@ -426,89 +507,12 @@ static int sessionpty(struct ChanSess * chansess) { } pty_setowner(ses.authstate.pw, chansess->tty); - pty_change_window_size(chansess->master, chansess->termr, chansess->termc, - chansess->termw, chansess->termh); - /* Term modes */ - /* We'll ignore errors and continue if we can't set modes. - * We're ignoring baud rates since they seem evil */ - if (tcgetattr(chansess->master, &termio) == 0) { - unsigned char opcode; - unsigned int value; - const struct TermCode * termcode; - unsigned int len; - - len = buf_getint(ses.payload); - if (len != ses.payload->len - ses.payload->pos) { - dropbear_exit("bad term mode string"); - } - - if (len == 0) { - TRACE(("empty terminal modes string")); - return DROPBEAR_SUCCESS; - } - - while (((opcode = buf_getbyte(ses.payload)) != 0x00) && - opcode <= 159) { + /* Set up the rows/col counts */ + sessionwinchange(chansess); - /* must be before checking type, so that value is consumed even if - * we don't use it */ - value = buf_getint(ses.payload); - - /* handle types of code */ - if (opcode > MAX_TERMCODE) { - continue; - } - termcode = &termcodes[(unsigned int)opcode]; - - - switch (termcode->type) { - - case TERMCODE_NONE: - break; - - case TERMCODE_CONTROLCHAR: - termio.c_cc[termcode->mapcode] = value; - break; - - case TERMCODE_INPUT: - if (value) { - termio.c_iflag |= termcode->mapcode; - } else { - termio.c_iflag &= ~(termcode->mapcode); - } - break; - - case TERMCODE_OUTPUT: - if (value) { - termio.c_oflag |= termcode->mapcode; - } else { - termio.c_oflag &= ~(termcode->mapcode); - } - break; - - case TERMCODE_LOCAL: - if (value) { - termio.c_lflag |= termcode->mapcode; - } else { - termio.c_lflag &= ~(termcode->mapcode); - } - break; - - case TERMCODE_CONTROL: - if (value) { - termio.c_cflag |= termcode->mapcode; - } else { - termio.c_cflag &= ~(termcode->mapcode); - } - break; - - } - } - if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) { - dropbear_log(LOG_INFO, "error setting terminal attributes"); - } - } + /* Read the terminal modes */ + get_termmodes(chansess); TRACE(("leave sessionpty")); return DROPBEAR_SUCCESS; |