Mercurial > dropbear
comparison cli-chansession.c @ 722:4a274f47eabd
Add ~. and ~^Z handling to exit/suspend dbclient
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 23 Mar 2013 23:16:06 +0800 |
parents | a98a2138364a |
children | ac2158e3e403 b2d4205b0897 |
comparison
equal
deleted
inserted
replaced
721:62fb0b5ff683 | 722:4a274f47eabd |
---|---|
36 #include "agentfwd.h" | 36 #include "agentfwd.h" |
37 | 37 |
38 static void cli_closechansess(struct Channel *channel); | 38 static void cli_closechansess(struct Channel *channel); |
39 static int cli_initchansess(struct Channel *channel); | 39 static int cli_initchansess(struct Channel *channel); |
40 static void cli_chansessreq(struct Channel *channel); | 40 static void cli_chansessreq(struct Channel *channel); |
41 | |
42 static void send_chansess_pty_req(struct Channel *channel); | 41 static void send_chansess_pty_req(struct Channel *channel); |
43 static void send_chansess_shell_req(struct Channel *channel); | 42 static void send_chansess_shell_req(struct Channel *channel); |
43 static void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len); | |
44 | |
44 | 45 |
45 static void cli_tty_setup(); | 46 static void cli_tty_setup(); |
46 | 47 |
47 const struct ChanType clichansess = { | 48 const struct ChanType clichansess = { |
48 0, /* sepfds */ | 49 0, /* sepfds */ |
372 | 373 |
373 send_chansess_shell_req(channel); | 374 send_chansess_shell_req(channel); |
374 | 375 |
375 if (cli_opts.wantpty) { | 376 if (cli_opts.wantpty) { |
376 cli_tty_setup(); | 377 cli_tty_setup(); |
377 } | 378 channel->read_mangler = cli_escape_handler; |
379 cli_ses.last_char = '\r'; | |
380 } | |
378 | 381 |
379 return 0; /* Success */ | 382 return 0; /* Success */ |
380 } | 383 } |
381 | 384 |
382 #ifdef ENABLE_CLI_NETCAT | 385 #ifdef ENABLE_CLI_NETCAT |
427 /* No special channel request data */ | 430 /* No special channel request data */ |
428 encrypt_packet(); | 431 encrypt_packet(); |
429 TRACE(("leave cli_send_chansess_request")) | 432 TRACE(("leave cli_send_chansess_request")) |
430 | 433 |
431 } | 434 } |
435 | |
436 // returns 1 if the character should be consumed, 0 to pass through | |
437 static int | |
438 do_escape(unsigned char c) { | |
439 switch (c) { | |
440 case '.': | |
441 dropbear_exit("Terminated"); | |
442 return 1; | |
443 break; | |
444 case 0x1a: | |
445 // ctrl-z | |
446 cli_tty_cleanup(); | |
447 kill(getpid(), SIGTSTP); | |
448 // after continuation | |
449 cli_tty_setup(); | |
450 cli_ses.winchange = 1; | |
451 return 1; | |
452 break; | |
453 } | |
454 return 0; | |
455 } | |
456 | |
457 static | |
458 void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len) { | |
459 char c; | |
460 int skip_char = 0; | |
461 | |
462 // only handle escape characters if they are read one at a time. simplifies | |
463 // the code and avoids nasty people putting ~. at the start of a line to paste | |
464 if (*len != 1) { | |
465 cli_ses.last_char = 0x0; | |
466 return; | |
467 } | |
468 | |
469 c = buf[0]; | |
470 | |
471 if (cli_ses.last_char == DROPBEAR_ESCAPE_CHAR) { | |
472 skip_char = do_escape(c); | |
473 cli_ses.last_char = 0x0; | |
474 } else { | |
475 if (c == DROPBEAR_ESCAPE_CHAR) { | |
476 if (cli_ses.last_char == '\r') { | |
477 cli_ses.last_char = DROPBEAR_ESCAPE_CHAR; | |
478 skip_char = 1; | |
479 } else { | |
480 cli_ses.last_char = 0x0; | |
481 } | |
482 } else { | |
483 cli_ses.last_char = c; | |
484 } | |
485 } | |
486 | |
487 if (skip_char) { | |
488 *len = 0; | |
489 } | |
490 } |