1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

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.

[originally from svn r7745]
This commit is contained in:
Ben Harris 2007-09-29 12:27:45 +00:00
parent 38ee5fc58d
commit faa6e26d38
3 changed files with 77 additions and 2 deletions

View File

@ -60,6 +60,18 @@ extern long tickcount_offset;
#define WCHAR wchar_t #define WCHAR wchar_t
#define BYTE unsigned char #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 */ /* Things pty.c needs from pterm.c */
char *get_x_display(void *frontend); char *get_x_display(void *frontend);
int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */ 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 */ /* Things uxstore.c provides to pterm.c */
void provide_xrm_string(char *string); 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 */ /* The interface used by uxsel.c */
void uxsel_init(void); void uxsel_init(void);
typedef int (*uxsel_callback_fn)(int fd, int event); typedef int (*uxsel_callback_fn)(int fd, int event);

View File

@ -18,6 +18,31 @@ int console_batch_mode = FALSE;
static void *console_logctx = NULL; 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. * 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"; static const char abandoned[] = "Connection abandoned.\n";
char line[32]; char line[32];
struct termios cf;
/* /*
* Verify the key. * 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 */ if (ret == 0) /* success - key matched OK */
return 1; return 1;
premsg(&cf);
if (ret == 2) { /* key was different */ if (ret == 2) { /* key was different */
if (console_batch_mode) { if (console_batch_mode) {
fprintf(stderr, wrongmsg_batch, keytype, fingerprint); 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] != '\0' && line[0] != '\r' && line[0] != '\n') {
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
postmsg(&cf);
return 1; return 1;
} else { } else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
postmsg(&cf);
return 0; return 0;
} }
} }
@ -166,7 +195,9 @@ int askalg(void *frontend, const char *algtype, const char *algname,
static const char abandoned[] = "Connection abandoned.\n"; static const char abandoned[] = "Connection abandoned.\n";
char line[32]; char line[32];
struct termios cf;
premsg(&cf);
if (console_batch_mode) { if (console_batch_mode) {
fprintf(stderr, msg_batch, algtype, algname); fprintf(stderr, msg_batch, algtype, algname);
return 0; return 0;
@ -187,9 +218,11 @@ int askalg(void *frontend, const char *algtype, const char *algname,
} }
if (line[0] == 'y' || line[0] == 'Y') { if (line[0] == 'y' || line[0] == 'Y') {
postmsg(&cf);
return 1; return 1;
} else { } else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
postmsg(&cf);
return 0; return 0;
} }
} }
@ -215,7 +248,9 @@ int askappend(void *frontend, Filename filename,
"Logging will not be enabled.\n"; "Logging will not be enabled.\n";
char line[32]; char line[32];
struct termios cf;
premsg(&cf);
if (console_batch_mode) { if (console_batch_mode) {
fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename.path); fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename.path);
fflush(stderr); fflush(stderr);
@ -235,6 +270,7 @@ int askappend(void *frontend, Filename filename,
tcsetattr(0, TCSANOW, &oldmode); tcsetattr(0, TCSANOW, &oldmode);
} }
postmsg(&cf);
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
return 2; return 2;
else if (line[0] == 'n' || line[0] == 'N') 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" "Once the key is loaded into PuTTYgen, you can perform\n"
"this conversion simply by saving it again.\n"; "this conversion simply by saving it again.\n";
struct termios cf;
premsg(&cf);
fputs(message, stderr); fputs(message, stderr);
postmsg(&cf);
} }
void console_provide_logctx(void *logctx) void console_provide_logctx(void *logctx)
@ -276,8 +315,11 @@ void console_provide_logctx(void *logctx)
void logevent(void *frontend, const char *string) void logevent(void *frontend, const char *string)
{ {
struct termios cf;
premsg(&cf);
if (console_logctx) if (console_logctx)
log_eventlog(console_logctx, string); log_eventlog(console_logctx, string);
postmsg(&cf);
} }
static void console_data_untrusted(const char *data, int len) static void console_data_untrusted(const char *data, int len)

View File

@ -27,14 +27,19 @@
void *logctx; void *logctx;
static struct termios orig_termios;
void fatalbox(char *p, ...) void fatalbox(char *p, ...)
{ {
struct termios cf;
va_list ap; va_list ap;
premsg(&cf);
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p); va_start(ap, p);
vfprintf(stderr, p, ap); vfprintf(stderr, p, ap);
va_end(ap); va_end(ap);
fputc('\n', stderr); fputc('\n', stderr);
postmsg(&cf);
if (logctx) { if (logctx) {
log_free(logctx); log_free(logctx);
logctx = NULL; logctx = NULL;
@ -43,12 +48,15 @@ void fatalbox(char *p, ...)
} }
void modalfatalbox(char *p, ...) void modalfatalbox(char *p, ...)
{ {
struct termios cf;
va_list ap; va_list ap;
premsg(&cf);
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p); va_start(ap, p);
vfprintf(stderr, p, ap); vfprintf(stderr, p, ap);
va_end(ap); va_end(ap);
fputc('\n', stderr); fputc('\n', stderr);
postmsg(&cf);
if (logctx) { if (logctx) {
log_free(logctx); log_free(logctx);
logctx = NULL; logctx = NULL;
@ -57,12 +65,15 @@ void modalfatalbox(char *p, ...)
} }
void connection_fatal(void *frontend, char *p, ...) void connection_fatal(void *frontend, char *p, ...)
{ {
struct termios cf;
va_list ap; va_list ap;
premsg(&cf);
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p); va_start(ap, p);
vfprintf(stderr, p, ap); vfprintf(stderr, p, ap);
va_end(ap); va_end(ap);
fputc('\n', stderr); fputc('\n', stderr);
postmsg(&cf);
if (logctx) { if (logctx) {
log_free(logctx); log_free(logctx);
logctx = NULL; logctx = NULL;
@ -71,17 +82,19 @@ void connection_fatal(void *frontend, char *p, ...)
} }
void cmdline_error(char *p, ...) void cmdline_error(char *p, ...)
{ {
struct termios cf;
va_list ap; va_list ap;
premsg(&cf);
fprintf(stderr, "plink: "); fprintf(stderr, "plink: ");
va_start(ap, p); va_start(ap, p);
vfprintf(stderr, p, ap); vfprintf(stderr, p, ap);
va_end(ap); va_end(ap);
fputc('\n', stderr); fputc('\n', stderr);
postmsg(&cf);
exit(1); exit(1);
} }
static int local_tty = FALSE; /* do we have a local tty? */ static int local_tty = FALSE; /* do we have a local tty? */
static struct termios orig_termios;
static Backend *back; static Backend *back;
static void *backhandle; static void *backhandle;
@ -582,7 +595,9 @@ int main(int argc, char **argv)
default_protocol = PROT_SSH; default_protocol = PROT_SSH;
default_port = 22; default_port = 22;
flags = FLAG_STDERR; flags = FLAG_STDERR | FLAG_STDERR_TTY;
stderr_tty_init();
/* /*
* Process the command line. * Process the command line.
*/ */