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:
parent
38ee5fc58d
commit
faa6e26d38
18
unix/unix.h
18
unix/unix.h
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user