From f7397dc65858f1105d78930fa530c9d829a03336 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 29 Sep 2007 12:27:45 +0000 Subject: [PATCH] Add support for resetting the terminal modes on stderr to something sensible before printing error messages to it. This should fix the stair-stepping in Plink's progress messages. git-svn-id: svn://svn.tartarus.org/sgt/putty@7745 cda61777-01e9-0310-a592-d414129be87e --- unix/unix.h | 18 ++++++++++++++++++ unix/uxcons.c | 42 ++++++++++++++++++++++++++++++++++++++++++ unix/uxplink.c | 19 +++++++++++++++++-- 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/unix/unix.h b/unix/unix.h index 90faf5a6..44749b8d 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -60,6 +60,18 @@ extern long tickcount_offset; #define WCHAR wchar_t #define BYTE unsigned char +/* + * Unix-specific global flag + * + * FLAG_STDERR_TTY indicates that standard error might be a terminal and + * might get its configuration munged, so anything trying to output plain + * text (i.e. with newlines in it) will need to put it back into cooked + * mode first. Applications setting this flag should also call + * stderr_tty_init() before messing with any terminal modes, and can call + * premsg() before outputting text to stderr and postmsg() afterwards. + */ +#define FLAG_STDERR_TTY 0x1000 + /* Things pty.c needs from pterm.c */ char *get_x_display(void *frontend); int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */ @@ -91,6 +103,12 @@ char *x_get_default(const char *key); /* Things uxstore.c provides to pterm.c */ void provide_xrm_string(char *string); +/* Things provided by uxcons.c */ +struct termios; +void stderr_tty_init(void); +void premsg(struct termios *); +void postmsg(struct termios *); + /* The interface used by uxsel.c */ void uxsel_init(void); typedef int (*uxsel_callback_fn)(int fd, int event); diff --git a/unix/uxcons.c b/unix/uxcons.c index d4848a6a..16e69fbb 100644 --- a/unix/uxcons.c +++ b/unix/uxcons.c @@ -18,6 +18,31 @@ int console_batch_mode = FALSE; static void *console_logctx = NULL; +static struct termios orig_termios_stderr; +static int stderr_is_a_tty; + +void stderr_tty_init() +{ + /* Ensure that if stderr is a tty, we can get it back to a sane state. */ + if ((flags & FLAG_STDERR_TTY) && isatty(STDERR_FILENO)) { + stderr_is_a_tty = TRUE; + tcgetattr(STDERR_FILENO, &orig_termios_stderr); + } +} + +void premsg(struct termios *cf) +{ + if (stderr_is_a_tty) { + tcgetattr(STDERR_FILENO, cf); + tcsetattr(STDERR_FILENO, TCSADRAIN, &orig_termios_stderr); + } +} +void postmsg(struct termios *cf) +{ + if (stderr_is_a_tty) + tcsetattr(STDERR_FILENO, TCSADRAIN, cf); +} + /* * Clean up and exit. */ @@ -101,6 +126,7 @@ int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, static const char abandoned[] = "Connection abandoned.\n"; char line[32]; + struct termios cf; /* * Verify the key. @@ -110,6 +136,7 @@ int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, if (ret == 0) /* success - key matched OK */ return 1; + premsg(&cf); if (ret == 2) { /* key was different */ if (console_batch_mode) { fprintf(stderr, wrongmsg_batch, keytype, fingerprint); @@ -141,9 +168,11 @@ int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') { if (line[0] == 'y' || line[0] == 'Y') store_host_key(host, port, keytype, keystr); + postmsg(&cf); return 1; } else { fprintf(stderr, abandoned); + postmsg(&cf); return 0; } } @@ -166,7 +195,9 @@ int askalg(void *frontend, const char *algtype, const char *algname, static const char abandoned[] = "Connection abandoned.\n"; char line[32]; + struct termios cf; + premsg(&cf); if (console_batch_mode) { fprintf(stderr, msg_batch, algtype, algname); return 0; @@ -187,9 +218,11 @@ int askalg(void *frontend, const char *algtype, const char *algname, } if (line[0] == 'y' || line[0] == 'Y') { + postmsg(&cf); return 1; } else { fprintf(stderr, abandoned); + postmsg(&cf); return 0; } } @@ -215,7 +248,9 @@ int askappend(void *frontend, Filename filename, "Logging will not be enabled.\n"; char line[32]; + struct termios cf; + premsg(&cf); if (console_batch_mode) { fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename.path); fflush(stderr); @@ -235,6 +270,7 @@ int askappend(void *frontend, Filename filename, tcsetattr(0, TCSANOW, &oldmode); } + postmsg(&cf); if (line[0] == 'y' || line[0] == 'Y') return 2; else if (line[0] == 'n' || line[0] == 'N') @@ -266,7 +302,10 @@ void old_keyfile_warning(void) "Once the key is loaded into PuTTYgen, you can perform\n" "this conversion simply by saving it again.\n"; + struct termios cf; + premsg(&cf); fputs(message, stderr); + postmsg(&cf); } void console_provide_logctx(void *logctx) @@ -276,8 +315,11 @@ void console_provide_logctx(void *logctx) void logevent(void *frontend, const char *string) { + struct termios cf; + premsg(&cf); if (console_logctx) log_eventlog(console_logctx, string); + postmsg(&cf); } static void console_data_untrusted(const char *data, int len) diff --git a/unix/uxplink.c b/unix/uxplink.c index 13369b10..a1dac9ad 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -27,14 +27,19 @@ void *logctx; +static struct termios orig_termios; + void fatalbox(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -43,12 +48,15 @@ void fatalbox(char *p, ...) } void modalfatalbox(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -57,12 +65,15 @@ void modalfatalbox(char *p, ...) } void connection_fatal(void *frontend, char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "FATAL ERROR: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); if (logctx) { log_free(logctx); logctx = NULL; @@ -71,17 +82,19 @@ void connection_fatal(void *frontend, char *p, ...) } void cmdline_error(char *p, ...) { + struct termios cf; va_list ap; + premsg(&cf); fprintf(stderr, "plink: "); va_start(ap, p); vfprintf(stderr, p, ap); va_end(ap); fputc('\n', stderr); + postmsg(&cf); exit(1); } static int local_tty = FALSE; /* do we have a local tty? */ -static struct termios orig_termios; static Backend *back; static void *backhandle; @@ -582,7 +595,9 @@ int main(int argc, char **argv) default_protocol = PROT_SSH; default_port = 22; - flags = FLAG_STDERR; + flags = FLAG_STDERR | FLAG_STDERR_TTY; + + stderr_tty_init(); /* * Process the command line. */ -- 2.11.0