* be_misc.c: helper functions shared between main network backends.
*/
+#include <assert.h>
+#include <string.h>
+
#define DEFINE_PLUG_METHOD_MACROS
#include "putty.h"
#include "network.h"
void backend_socket_log(void *frontend, int type, SockAddr addr, int port,
- const char *error_msg, int error_code)
+ const char *error_msg, int error_code, Conf *conf,
+ int session_started)
{
char addrbuf[256], *msg;
case 2:
/* Proxy-related log messages have their own identifying
* prefix already, put on by our caller. */
- msg = dupstr(error_msg);
+ {
+ int len, log_to_term;
+
+ /* Suffix \r\n temporarily, so we can log to the terminal. */
+ msg = dupprintf("%s\r\n", error_msg);
+ len = strlen(msg);
+ assert(len >= 2);
+
+ log_to_term = conf_get_int(conf, CONF_proxy_log_to_term);
+ if (log_to_term == AUTO)
+ log_to_term = session_started ? FORCE_OFF : FORCE_ON;
+ if (log_to_term == FORCE_ON)
+ from_backend(frontend, TRUE, msg, len);
+
+ msg[len-2] = '\0'; /* remove the \r\n again */
+ }
break;
default:
msg = NULL; /* shouldn't happen, but placate optimiser */
HELPCTX(proxy_command),
conf_editbox_handler,
I(CONF_proxy_telnet_command), I(1));
+
+ ctrl_radiobuttons(s, "Print proxy diagnostics "
+ "in the terminal window", 'r', 5,
+ HELPCTX(proxy_main),
+ conf_radiobutton_handler,
+ I(CONF_proxy_log_to_term),
+ "No", I(FORCE_OFF),
+ "Yes", I(FORCE_ON),
+ "Only until session starts", I(AUTO), NULL);
}
/*
* Exports from be_misc.c.
*/
void backend_socket_log(void *frontend, int type, SockAddr addr, int port,
- const char *error_msg, int error_code);
+ const char *error_msg, int error_code, Conf *conf,
+ int session_started);
typedef struct bufchain_tag bufchain; /* rest of declaration in misc.c */
void log_proxy_stderr(Plug plug, bufchain *buf, const void *vdata, int len);
* three-way settings whose values are `always yes', `always
* no', and `decide by some more complex automated means'. This
* is true of line discipline options (local echo and line
- * editing), proxy DNS, Close On Exit, and SSH server bug
- * workarounds. Accordingly I supply a single enum here to deal
- * with them all.
+ * editing), proxy DNS, proxy terminal logging, Close On Exit, and
+ * SSH server bug workarounds. Accordingly I supply a single enum
+ * here to deal with them all.
*/
FORCE_ON, FORCE_OFF, AUTO
};
X(STR, NONE, proxy_username) \
X(STR, NONE, proxy_password) \
X(STR, NONE, proxy_telnet_command) \
+ X(INT, NONE, proxy_log_to_term) \
/* SSH options */ \
X(STR, NONE, remote_cmd) \
X(STR, NONE, remote_cmd2) /* fallback if remote_cmd fails; never loaded or saved */ \
int closed_on_socket_error;
int bufsize;
void *frontend;
- int sent_console_eof, sent_socket_eof;
+ int sent_console_eof, sent_socket_eof, session_started;
+
+ Conf *conf;
} *Raw;
static void raw_size(void *handle, int width, int height);
{
Raw raw = (Raw) plug;
backend_socket_log(raw->frontend, type, addr, port,
- error_msg, error_code);
+ error_msg, error_code, raw->conf, raw->session_started);
}
static void raw_check_close(Raw raw)
{
Raw raw = (Raw) plug;
c_write(raw, data, len);
+ /* We count 'session start', for proxy logging purposes, as being
+ * when data is received from the network and printed. */
+ raw->session_started = TRUE;
return 1;
}
*backend_handle = raw;
raw->sent_console_eof = raw->sent_socket_eof = FALSE;
raw->bufsize = 0;
+ raw->session_started = FALSE;
+ raw->conf = conf_copy(conf);
raw->frontend = frontend_handle;
if (raw->s)
sk_close(raw->s);
+ conf_free(raw->conf);
sfree(raw);
}
{
Rlogin rlogin = (Rlogin) plug;
backend_socket_log(rlogin->frontend, type, addr, port,
- error_msg, error_code);
+ error_msg, error_code,
+ rlogin->conf, !rlogin->firstbyte);
}
static int rlogin_closing(Plug plug, const char *error_msg, int error_code,
write_setting_s(sesskey, "ProxyUsername", conf_get_str(conf, CONF_proxy_username));
write_setting_s(sesskey, "ProxyPassword", conf_get_str(conf, CONF_proxy_password));
write_setting_s(sesskey, "ProxyTelnetCommand", conf_get_str(conf, CONF_proxy_telnet_command));
+ write_setting_i(sesskey, "ProxyLogToTerm", conf_get_int(conf, CONF_proxy_log_to_term));
wmap(sesskey, "Environment", conf, CONF_environmt, TRUE);
write_setting_s(sesskey, "UserName", conf_get_str(conf, CONF_username));
write_setting_i(sesskey, "UserNameFromEnvironment", conf_get_int(conf, CONF_username_from_env));
gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);
gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
conf, CONF_proxy_telnet_command);
+ gppi(sesskey, "ProxyLogToTerm", FORCE_OFF, conf, CONF_proxy_log_to_term);
gppmap(sesskey, "Environment", conf, CONF_environmt);
gpps(sesskey, "UserName", "", conf, CONF_username);
gppi(sesskey, "UserNameFromEnvironment", 0, conf, CONF_username_from_env);
int send_ok;
int echoing, editing;
+ int session_started;
void *frontend;
int ospeed, ispeed; /* temporaries */
crReturn(1);
}
+ ssh->session_started = TRUE;
+
s->vstrsize = sizeof(protoname) + 16;
s->vstring = snewn(s->vstrsize, char);
strcpy(s->vstring, protoname);
if (!ssh->attempting_connshare)
backend_socket_log(ssh->frontend, type, addr, port,
- error_msg, error_code);
+ error_msg, error_code, ssh->conf,
+ ssh->session_started);
}
void ssh_connshare_log(Ssh ssh, int event, const char *logtext,
ssh->X11_fwd_enabled = FALSE;
ssh->connshare = NULL;
ssh->attempting_connshare = FALSE;
+ ssh->session_started = FALSE;
*backend_handle = ssh;
int sb_opt, sb_len;
unsigned char *sb_buf;
int sb_size;
+ int session_started;
enum {
TOP_LEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
{
Telnet telnet = (Telnet) plug;
backend_socket_log(telnet->frontend, type, addr, port,
- error_msg, error_code);
+ error_msg, error_code, telnet->conf,
+ telnet->session_started);
}
static int telnet_closing(Plug plug, const char *error_msg, int error_code,
Telnet telnet = (Telnet) plug;
if (urgent)
telnet->in_synch = TRUE;
+ telnet->session_started = TRUE;
do_telnet_read(telnet, data, len);
return 1;
}
telnet->state = TOP_LEVEL;
telnet->ldisc = NULL;
telnet->pinger = NULL;
+ telnet->session_started = TRUE;
*backend_handle = telnet;
/*
Filename *platform_default_filename(const char *name) { return filename_from_str(""); }
char *x_get_default(const char *key) { return NULL; }
void log_eventlog(void *handle, const char *event) {}
+int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
+{ assert(!"only here to satisfy notional call from backend_socket_log"); }
/*
* Short description of parameters.