mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
This commit is contained in:
parent
109df9f46b
commit
b4c8fd9d86
@ -8,7 +8,7 @@
|
||||
#include "putty.h"
|
||||
#include "network.h"
|
||||
|
||||
void backend_socket_log(Frontend *frontend, LogContext *logctx,
|
||||
void backend_socket_log(Seat *seat, LogContext *logctx,
|
||||
int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code, Conf *conf,
|
||||
int session_started)
|
||||
@ -43,7 +43,7 @@ void backend_socket_log(Frontend *frontend, LogContext *logctx,
|
||||
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);
|
||||
seat_stderr(seat, msg, len);
|
||||
|
||||
msg[len-2] = '\0'; /* remove the \r\n again */
|
||||
}
|
||||
|
23
cmdgen.c
23
cmdgen.c
@ -92,27 +92,6 @@ static void no_progress(void *param, int action, int phase, int iprogress)
|
||||
{
|
||||
}
|
||||
|
||||
void modalfatalbox(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void nonfatal(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stubs to let everything else link sensibly.
|
||||
*/
|
||||
@ -775,7 +754,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
if (encrypted && load_encrypted) {
|
||||
if (!old_passphrase) {
|
||||
prompts_t *p = new_prompts(NULL);
|
||||
prompts_t *p = new_prompts();
|
||||
int ret;
|
||||
p->to_server = FALSE;
|
||||
p->name = dupstr("SSH key passphrase");
|
||||
|
@ -81,8 +81,8 @@ void cmdline_cleanup(void)
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Similar interface to get_userpass_input(), except that here a -1
|
||||
* return means that we aren't capable of processing the prompt and
|
||||
* Similar interface to seat_get_userpass_input(), except that here a
|
||||
* -1 return means that we aren't capable of processing the prompt and
|
||||
* someone else should do it.
|
||||
*/
|
||||
int cmdline_get_passwd_input(prompts_t *p)
|
||||
|
3
defs.h
3
defs.h
@ -53,6 +53,9 @@ typedef struct LogContext LogContext;
|
||||
typedef struct LogPolicy LogPolicy;
|
||||
typedef struct LogPolicyVtable LogPolicyVtable;
|
||||
|
||||
typedef struct Seat Seat;
|
||||
typedef struct SeatVtable SeatVtable;
|
||||
|
||||
typedef struct Frontend Frontend;
|
||||
|
||||
typedef struct Ssh Ssh;
|
||||
|
@ -38,9 +38,6 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int from_backend(Frontend *frontend, int is_stderr, const void *data, int len)
|
||||
{ return 0; }
|
||||
|
||||
/* functions required by terminal.c */
|
||||
|
||||
void request_resize(Frontend *frontend, int x, int y) { }
|
||||
|
9
ldisc.c
9
ldisc.c
@ -24,7 +24,7 @@
|
||||
|
||||
static void c_write(Ldisc *ldisc, const void *buf, int len)
|
||||
{
|
||||
from_backend(ldisc->frontend, 0, buf, len);
|
||||
seat_stdout(ldisc->seat, buf, len);
|
||||
}
|
||||
|
||||
static int plen(Ldisc *ldisc, unsigned char c)
|
||||
@ -77,8 +77,7 @@ static void bsb(Ldisc *ldisc, int n)
|
||||
#define CTRL(x) (x^'@')
|
||||
#define KCTRL(x) ((x^'@') | 0x100)
|
||||
|
||||
Ldisc *ldisc_create(Conf *conf, Terminal *term,
|
||||
Backend *backend, Frontend *frontend)
|
||||
Ldisc *ldisc_create(Conf *conf, Terminal *term, Backend *backend, Seat *seat)
|
||||
{
|
||||
Ldisc *ldisc = snew(Ldisc);
|
||||
|
||||
@ -89,7 +88,7 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term,
|
||||
|
||||
ldisc->backend = backend;
|
||||
ldisc->term = term;
|
||||
ldisc->frontend = frontend;
|
||||
ldisc->seat = seat;
|
||||
|
||||
ldisc_configure(ldisc, conf);
|
||||
|
||||
@ -124,7 +123,7 @@ void ldisc_free(Ldisc *ldisc)
|
||||
|
||||
void ldisc_echoedit_update(Ldisc *ldisc)
|
||||
{
|
||||
frontend_echoedit_update(ldisc->frontend, ECHOING, EDITING);
|
||||
seat_echoedit_update(ldisc->seat, ECHOING, EDITING);
|
||||
}
|
||||
|
||||
void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
|
||||
|
2
ldisc.h
2
ldisc.h
@ -11,7 +11,7 @@
|
||||
struct Ldisc_tag {
|
||||
Terminal *term;
|
||||
Backend *backend;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
|
||||
/*
|
||||
* Values cached out of conf.
|
||||
|
44
misc.c
44
misc.c
@ -216,12 +216,24 @@ char *host_strduptrim(const char *s)
|
||||
return dupstr(s);
|
||||
}
|
||||
|
||||
prompts_t *new_prompts(Frontend *frontend)
|
||||
void seat_connection_fatal(Seat *seat, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *msg;
|
||||
|
||||
va_start(ap, fmt);
|
||||
msg = dupvprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
seat->vt->connection_fatal(seat, msg);
|
||||
sfree(msg); /* if we return */
|
||||
}
|
||||
|
||||
prompts_t *new_prompts(void)
|
||||
{
|
||||
prompts_t *p = snew(prompts_t);
|
||||
p->prompts = NULL;
|
||||
p->n_prompts = 0;
|
||||
p->frontend = frontend;
|
||||
p->data = NULL;
|
||||
p->to_server = TRUE; /* to be on the safe side */
|
||||
p->name = p->instruction = NULL;
|
||||
@ -1348,3 +1360,31 @@ char *buildinfo(const char *newline)
|
||||
|
||||
return strbuf_to_str(buf);
|
||||
}
|
||||
|
||||
int nullseat_output(
|
||||
Seat *seat, int is_stderr, const void *data, int len) { return 0; }
|
||||
int nullseat_eof(Seat *seat) { return TRUE; }
|
||||
int nullseat_get_userpass_input(
|
||||
Seat *seat, prompts_t *p, bufchain *input) { return 0; }
|
||||
void nullseat_notify_remote_exit(Seat *seat) {}
|
||||
void nullseat_connection_fatal(Seat *seat, const char *message) {}
|
||||
void nullseat_update_specials_menu(Seat *seat) {}
|
||||
char *nullseat_get_ttymode(Seat *seat, const char *mode) { return NULL; }
|
||||
void nullseat_set_busy_status(Seat *seat, BusyStatus status) {}
|
||||
int nullseat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *key_fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx) { return 0; }
|
||||
int nullseat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx) { return 0; }
|
||||
int nullseat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx) { return 0; }
|
||||
int nullseat_is_never_utf8(Seat *seat) { return FALSE; }
|
||||
int nullseat_is_always_utf8(Seat *seat) { return TRUE; }
|
||||
void nullseat_echoedit_update(Seat *seat, int echoing, int editing) {}
|
||||
const char *nullseat_get_x_display(Seat *seat) { return NULL; }
|
||||
int nullseat_get_windowid(Seat *seat, long *id_out) { return FALSE; }
|
||||
int nullseat_get_char_cell_size(
|
||||
Seat *seat, int *width, int *height) { return FALSE; }
|
||||
|
@ -235,7 +235,7 @@ extern Plug *const nullplug;
|
||||
/*
|
||||
* Exports from be_misc.c.
|
||||
*/
|
||||
void backend_socket_log(Frontend *frontend, LogContext *logctx,
|
||||
void backend_socket_log(Seat *seat, LogContext *logctx,
|
||||
int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code, Conf *conf,
|
||||
int session_started);
|
||||
|
107
pscp.c
107
pscp.c
@ -61,6 +61,29 @@ const char *const appname = "PSCP";
|
||||
|
||||
void ldisc_echoedit_update(Ldisc *ldisc) { }
|
||||
|
||||
static int pscp_output(Seat *, int is_stderr, const void *, int);
|
||||
static int pscp_eof(Seat *);
|
||||
|
||||
static const SeatVtable pscp_seat_vt = {
|
||||
pscp_output,
|
||||
pscp_eof,
|
||||
filexfer_get_userpass_input,
|
||||
nullseat_notify_remote_exit,
|
||||
console_connection_fatal,
|
||||
nullseat_update_specials_menu,
|
||||
nullseat_get_ttymode,
|
||||
nullseat_set_busy_status,
|
||||
console_verify_ssh_host_key,
|
||||
console_confirm_weak_crypto_primitive,
|
||||
console_confirm_weak_cached_hostkey,
|
||||
nullseat_is_never_utf8,
|
||||
nullseat_echoedit_update,
|
||||
nullseat_get_x_display,
|
||||
nullseat_get_windowid,
|
||||
nullseat_get_char_cell_size,
|
||||
};
|
||||
static Seat pscp_seat[1] = {{ &pscp_seat_vt }};
|
||||
|
||||
static void tell_char(FILE *stream, char c)
|
||||
{
|
||||
fputc(c, stream);
|
||||
@ -103,56 +126,6 @@ static void tell_user(FILE *stream, const char *fmt, ...)
|
||||
sfree(str2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message and perform a fatal exit.
|
||||
*/
|
||||
void modalfatalbox(const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Fatal: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
abandon_stats();
|
||||
tell_str(stderr, str2);
|
||||
sfree(str2);
|
||||
errs++;
|
||||
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void nonfatal(const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Error: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
abandon_stats();
|
||||
tell_str(stderr, str2);
|
||||
sfree(str2);
|
||||
errs++;
|
||||
}
|
||||
void connection_fatal(Frontend *frontend, const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Fatal: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
abandon_stats();
|
||||
tell_str(stderr, str2);
|
||||
sfree(str2);
|
||||
errs++;
|
||||
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* In pscp, all agent requests should be synchronous, so this is a
|
||||
* never-called stub.
|
||||
@ -168,16 +141,16 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
|
||||
* is available.
|
||||
*
|
||||
* To do this, we repeatedly call the SSH protocol module, with our
|
||||
* own trap in from_backend() to catch the data that comes back. We
|
||||
* do this until we have enough data.
|
||||
* own pscp_output() function to catch the data that comes back. We do
|
||||
* this until we have enough data.
|
||||
*/
|
||||
|
||||
static unsigned char *outptr; /* where to put the data */
|
||||
static unsigned outlen; /* how much data required */
|
||||
static unsigned char *pending = NULL; /* any spare data */
|
||||
static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
|
||||
int from_backend(Frontend *frontend, int is_stderr,
|
||||
const void *data, int datalen)
|
||||
static int pscp_output(Seat *seat, int is_stderr,
|
||||
const void *data, int datalen)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) data;
|
||||
unsigned len = (unsigned) datalen;
|
||||
@ -215,7 +188,7 @@ int from_backend(Frontend *frontend, int is_stderr,
|
||||
|
||||
return 0;
|
||||
}
|
||||
int from_backend_eof(Frontend *frontend)
|
||||
static int pscp_eof(Seat *seat)
|
||||
{
|
||||
/*
|
||||
* We usually expect to be the party deciding when to close the
|
||||
@ -224,8 +197,8 @@ int from_backend_eof(Frontend *frontend)
|
||||
* downloading rather than uploading.
|
||||
*/
|
||||
if ((using_sftp || uploading) && !sent_eof) {
|
||||
connection_fatal(frontend,
|
||||
"Received unexpected end-of-file from server");
|
||||
seat_connection_fatal(
|
||||
pscp_seat, "Received unexpected end-of-file from server");
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -325,7 +298,7 @@ static void bump(const char *fmt, ...)
|
||||
* Wait for the reply to a single SFTP request. Parallels the same
|
||||
* function in psftp.c (but isn't centralised into sftp.c because the
|
||||
* latter module handles SFTP only and shouldn't assume that SFTP is
|
||||
* the only thing going on by calling connection_fatal).
|
||||
* the only thing going on by calling seat_connection_fatal).
|
||||
*/
|
||||
struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
|
||||
{
|
||||
@ -334,13 +307,17 @@ struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
|
||||
|
||||
sftp_register(req);
|
||||
pktin = sftp_recv();
|
||||
if (pktin == NULL)
|
||||
connection_fatal(NULL, "did not receive SFTP response packet "
|
||||
"from server");
|
||||
if (pktin == NULL) {
|
||||
seat_connection_fatal(
|
||||
pscp_seat, "did not receive SFTP response packet from server");
|
||||
}
|
||||
rreq = sftp_find_request(pktin);
|
||||
if (rreq != req)
|
||||
connection_fatal(NULL, "unable to understand SFTP response packet "
|
||||
"from server: %s", fxp_error());
|
||||
if (rreq != req) {
|
||||
seat_connection_fatal(
|
||||
pscp_seat,
|
||||
"unable to understand SFTP response packet from server: %s",
|
||||
fxp_error());
|
||||
}
|
||||
return pktin;
|
||||
}
|
||||
|
||||
@ -513,7 +490,7 @@ static void do_cmd(char *host, char *user, char *cmd)
|
||||
|
||||
platform_psftp_pre_conn_setup();
|
||||
|
||||
err = backend_init(&ssh_backend, NULL, &backend, logctx, conf,
|
||||
err = backend_init(&ssh_backend, pscp_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost, 0,
|
||||
|
103
psftp.c
103
psftp.c
@ -38,6 +38,33 @@ static Backend *backend;
|
||||
static Conf *conf;
|
||||
int sent_eof = FALSE;
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* Seat vtable.
|
||||
*/
|
||||
|
||||
static int psftp_output(Seat *, int is_stderr, const void *, int);
|
||||
static int psftp_eof(Seat *);
|
||||
|
||||
static const SeatVtable psftp_seat_vt = {
|
||||
psftp_output,
|
||||
psftp_eof,
|
||||
filexfer_get_userpass_input,
|
||||
nullseat_notify_remote_exit,
|
||||
console_connection_fatal,
|
||||
nullseat_update_specials_menu,
|
||||
nullseat_get_ttymode,
|
||||
nullseat_set_busy_status,
|
||||
console_verify_ssh_host_key,
|
||||
console_confirm_weak_crypto_primitive,
|
||||
console_confirm_weak_cached_hostkey,
|
||||
nullseat_is_never_utf8,
|
||||
nullseat_echoedit_update,
|
||||
nullseat_get_x_display,
|
||||
nullseat_get_windowid,
|
||||
nullseat_get_char_cell_size,
|
||||
};
|
||||
static Seat psftp_seat[1] = {{ &psftp_seat_vt }};
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Manage sending requests and waiting for replies.
|
||||
*/
|
||||
@ -48,13 +75,17 @@ struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
|
||||
|
||||
sftp_register(req);
|
||||
pktin = sftp_recv();
|
||||
if (pktin == NULL)
|
||||
connection_fatal(NULL, "did not receive SFTP response packet "
|
||||
"from server");
|
||||
if (pktin == NULL) {
|
||||
seat_connection_fatal(
|
||||
psftp_seat, "did not receive SFTP response packet from server");
|
||||
}
|
||||
rreq = sftp_find_request(pktin);
|
||||
if (rreq != req)
|
||||
connection_fatal(NULL, "unable to understand SFTP response packet "
|
||||
"from server: %s", fxp_error());
|
||||
if (rreq != req) {
|
||||
seat_connection_fatal(
|
||||
psftp_seat,
|
||||
"unable to understand SFTP response packet from server: %s",
|
||||
fxp_error());
|
||||
}
|
||||
return pktin;
|
||||
}
|
||||
|
||||
@ -2437,50 +2468,6 @@ int do_sftp(int mode, int modeflags, char *batchfile)
|
||||
|
||||
static int verbose = 0;
|
||||
|
||||
/*
|
||||
* Print an error message and perform a fatal exit.
|
||||
*/
|
||||
void modalfatalbox(const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Fatal: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
fputs(str2, stderr);
|
||||
sfree(str2);
|
||||
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void nonfatal(const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Error: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
fputs(str2, stderr);
|
||||
sfree(str2);
|
||||
}
|
||||
void connection_fatal(Frontend *frontend, const char *fmt, ...)
|
||||
{
|
||||
char *str, *str2;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str = dupvprintf(fmt, ap);
|
||||
str2 = dupcat("Fatal: ", str, "\n", NULL);
|
||||
sfree(str);
|
||||
va_end(ap);
|
||||
fputs(str2, stderr);
|
||||
sfree(str2);
|
||||
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void ldisc_echoedit_update(Ldisc *ldisc) { }
|
||||
|
||||
/*
|
||||
@ -2498,7 +2485,7 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
|
||||
* is available.
|
||||
*
|
||||
* To do this, we repeatedly call the SSH protocol module, with our
|
||||
* own trap in from_backend() to catch the data that comes back. We
|
||||
* own psftp_output() function to catch the data that comes back. We
|
||||
* do this until we have enough data.
|
||||
*/
|
||||
|
||||
@ -2506,8 +2493,8 @@ static unsigned char *outptr; /* where to put the data */
|
||||
static unsigned outlen; /* how much data required */
|
||||
static unsigned char *pending = NULL; /* any spare data */
|
||||
static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
|
||||
int from_backend(Frontend *frontend, int is_stderr,
|
||||
const void *data, int datalen)
|
||||
static int psftp_output(Seat *seat, int is_stderr,
|
||||
const void *data, int datalen)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) data;
|
||||
unsigned len = (unsigned) datalen;
|
||||
@ -2551,7 +2538,8 @@ int from_backend(Frontend *frontend, int is_stderr,
|
||||
|
||||
return 0;
|
||||
}
|
||||
int from_backend_eof(Frontend *frontend)
|
||||
|
||||
static int psftp_eof(Seat *seat)
|
||||
{
|
||||
/*
|
||||
* We expect to be the party deciding when to close the
|
||||
@ -2559,11 +2547,12 @@ int from_backend_eof(Frontend *frontend)
|
||||
* should panic.
|
||||
*/
|
||||
if (!sent_eof) {
|
||||
connection_fatal(frontend,
|
||||
"Received unexpected end-of-file from SFTP server");
|
||||
seat_connection_fatal(
|
||||
psftp_seat, "Received unexpected end-of-file from SFTP server");
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int sftp_recvdata(char *buf, int len)
|
||||
{
|
||||
outptr = (unsigned char *) buf;
|
||||
@ -2820,7 +2809,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
|
||||
|
||||
platform_psftp_pre_conn_setup();
|
||||
|
||||
err = backend_init(&ssh_backend, NULL, &backend, logctx, conf,
|
||||
err = backend_init(&ssh_backend, psftp_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost, 0,
|
||||
|
377
putty.h
377
putty.h
@ -479,7 +479,7 @@ struct Backend {
|
||||
const BackendVtable *vt;
|
||||
};
|
||||
struct BackendVtable {
|
||||
const char *(*init) (Frontend *frontend, Backend **backend_out,
|
||||
const char *(*init) (Seat *seat, Backend **backend_out,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive);
|
||||
@ -515,8 +515,8 @@ struct BackendVtable {
|
||||
int default_port;
|
||||
};
|
||||
|
||||
#define backend_init(vt, fe, out, logctx, conf, host, port, rhost, nd, ka) \
|
||||
((vt)->init(fe, out, logctx, conf, host, port, rhost, nd, ka))
|
||||
#define backend_init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka) \
|
||||
((vt)->init(seat, out, logctx, conf, host, port, rhost, nd, ka))
|
||||
#define backend_free(be) ((be)->vt->free(be))
|
||||
#define backend_reconfig(be, conf) ((be)->vt->reconfig(be, conf))
|
||||
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len))
|
||||
@ -635,11 +635,10 @@ typedef struct {
|
||||
size_t n_prompts; /* May be zero (in which case display the foregoing,
|
||||
* if any, and return success) */
|
||||
prompt_t **prompts;
|
||||
Frontend *frontend;
|
||||
void *data; /* slot for housekeeping data, managed by
|
||||
* get_userpass_input(); initially NULL */
|
||||
* seat_get_userpass_input(); initially NULL */
|
||||
} prompts_t;
|
||||
prompts_t *new_prompts(Frontend *frontend);
|
||||
prompts_t *new_prompts();
|
||||
void add_prompt(prompts_t *p, char *promptstr, int echo);
|
||||
void prompt_set_result(prompt_t *pr, const char *newstr);
|
||||
void prompt_ensure_result_size(prompt_t *pr, int len);
|
||||
@ -697,6 +696,306 @@ typedef struct truecolour {
|
||||
enum { ALL_CLIPBOARDS(CLIP_ID) N_CLIPBOARDS };
|
||||
#undef CLIP_ID
|
||||
|
||||
/* Hint from backend to frontend about time-consuming operations, used
|
||||
* by seat_set_busy_status. Initial state is assumed to be
|
||||
* BUSY_NOT. */
|
||||
typedef enum BusyStatus {
|
||||
BUSY_NOT, /* Not busy, all user interaction OK */
|
||||
BUSY_WAITING, /* Waiting for something; local event loops still
|
||||
running so some local interaction (e.g. menus)
|
||||
OK, but network stuff is suspended */
|
||||
BUSY_CPU /* Locally busy (e.g. crypto); user interaction
|
||||
* suspended */
|
||||
} BusyStatus;
|
||||
|
||||
/*
|
||||
* Data type 'Seat', which is an API intended to contain essentially
|
||||
* everything that a back end might need to talk to its client for:
|
||||
* session output, password prompts, SSH warnings about host keys and
|
||||
* weak cryptography, notifications of events like the remote process
|
||||
* exiting or the GUI specials menu needing an update.
|
||||
*/
|
||||
struct Seat {
|
||||
const struct SeatVtable *vt;
|
||||
};
|
||||
struct SeatVtable {
|
||||
/*
|
||||
* Provide output from the remote session. 'is_stderr' indicates
|
||||
* that the output should be sent to a separate error message
|
||||
* channel, if the seat has one. But combining both channels into
|
||||
* one is OK too; that's what terminal-window based seats do.
|
||||
*
|
||||
* The return value is the current size of the output backlog.
|
||||
*/
|
||||
int (*output)(Seat *seat, int is_stderr, const void *data, int len);
|
||||
|
||||
/*
|
||||
* Called when the back end wants to indicate that EOF has arrived
|
||||
* on the server-to-client stream. Returns FALSE to indicate that
|
||||
* we intend to keep the session open in the other direction, or
|
||||
* TRUE to indicate that if they're closing so are we.
|
||||
*/
|
||||
int (*eof)(Seat *seat);
|
||||
|
||||
/*
|
||||
* Try to get answers from a set of interactive login prompts. The
|
||||
* prompts are provided in 'p'; the bufchain 'input' holds the
|
||||
* data currently outstanding in the session's normal standard-
|
||||
* input channel. Seats may implement this function by consuming
|
||||
* data from 'input' (e.g. password prompts in GUI PuTTY,
|
||||
* displayed in the same terminal as the subsequent session), or
|
||||
* by doing something entirely different (e.g. directly
|
||||
* interacting with standard I/O, or putting up a dialog box).
|
||||
*
|
||||
* A positive return value means that all prompts have had answers
|
||||
* filled in. A zero return means that the user performed a
|
||||
* deliberate 'cancel' UI action. A negative return means that no
|
||||
* answer can be given yet but please try again later.
|
||||
*
|
||||
* (FIXME: it would be nice to distinguish two classes of cancel
|
||||
* action, so the user could specify 'I want to abandon this
|
||||
* entire attempt to start a session' or the milder 'I want to
|
||||
* abandon this particular form of authentication and fall back to
|
||||
* a different one' - e.g. if you turn out not to be able to
|
||||
* remember your private key passphrase then perhaps you'd rather
|
||||
* fall back to password auth rather than aborting the whole
|
||||
* session.)
|
||||
*
|
||||
* (Also FIXME: currently, backends' only response to the 'try
|
||||
* again later' is to try again when more input data becomes
|
||||
* available, because they assume that a seat is returning that
|
||||
* value because it's consuming keyboard input. But a seat that
|
||||
* handled this function by putting up a dialog box might want to
|
||||
* put it up non-modally, and therefore would want to proactively
|
||||
* notify the backend to retry once the dialog went away. So if I
|
||||
* ever do want to move password prompts into a dialog box, I'll
|
||||
* want a backend method for sending that notification.)
|
||||
*/
|
||||
int (*get_userpass_input)(Seat *seat, prompts_t *p, bufchain *input);
|
||||
|
||||
/*
|
||||
* Notify the seat that the process running at the other end of
|
||||
* the connection has finished.
|
||||
*/
|
||||
void (*notify_remote_exit)(Seat *seat);
|
||||
|
||||
/*
|
||||
* Notify the seat that the connection has suffered a fatal error.
|
||||
*/
|
||||
void (*connection_fatal)(Seat *seat, const char *message);
|
||||
|
||||
/*
|
||||
* Notify the seat that the list of special commands available
|
||||
* from backend_get_specials() has changed, so that it might want
|
||||
* to call that function to repopulate its menu.
|
||||
*
|
||||
* Seats are not expected to call backend_get_specials()
|
||||
* proactively; they may start by assuming that the backend
|
||||
* provides no special commands at all, so if the backend does
|
||||
* provide any, then it should use this notification at startup
|
||||
* time. Of course it can also invoke it later if the set of
|
||||
* special commands changes.
|
||||
*
|
||||
* It does not need to invoke it at session shutdown.
|
||||
*/
|
||||
void (*update_specials_menu)(Seat *seat);
|
||||
|
||||
/*
|
||||
* Get the seat's preferred value for an SSH terminal mode
|
||||
* setting. Returning NULL indicates no preference (i.e. the SSH
|
||||
* connection will not attempt to set the mode at all).
|
||||
*
|
||||
* The returned value is dynamically allocated, and the caller
|
||||
* should free it.
|
||||
*/
|
||||
char *(*get_ttymode)(Seat *seat, const char *mode);
|
||||
|
||||
/*
|
||||
* Tell the seat whether the backend is currently doing anything
|
||||
* CPU-intensive (typically a cryptographic key exchange). See
|
||||
* BusyStatus enumeration above.
|
||||
*/
|
||||
void (*set_busy_status)(Seat *seat, BusyStatus status);
|
||||
|
||||
/*
|
||||
* Ask the seat whether a given SSH host key should be accepted.
|
||||
* This may return immediately after checking saved configuration
|
||||
* or command-line options, or it may have to present a prompt to
|
||||
* the user and return asynchronously later.
|
||||
*
|
||||
* Return values:
|
||||
*
|
||||
* - +1 means `key was OK' (either already known or the user just
|
||||
* approved it) `so continue with the connection'
|
||||
*
|
||||
* - 0 means `key was not OK, abandon the connection'
|
||||
*
|
||||
* - -1 means `I've initiated enquiries, please wait to be called
|
||||
* back via the provided function with a result that's either 0
|
||||
* or +1'.
|
||||
*/
|
||||
int (*verify_ssh_host_key)(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *key_fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Check with the seat whether it's OK to use a cryptographic
|
||||
* primitive from below the 'warn below this line' threshold in
|
||||
* the input Conf. Return values are the same as
|
||||
* verify_ssh_host_key above.
|
||||
*/
|
||||
int (*confirm_weak_crypto_primitive)(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Variant form of confirm_weak_crypto_primitive, which prints a
|
||||
* slightly different message but otherwise has the same
|
||||
* semantics.
|
||||
*
|
||||
* This form is used in the case where we're using a host key
|
||||
* below the warning threshold because that's the best one we have
|
||||
* cached, but at least one host key algorithm *above* the
|
||||
* threshold is available that we don't have cached. 'betteralgs'
|
||||
* lists the better algorithm(s).
|
||||
*/
|
||||
int (*confirm_weak_cached_hostkey)(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Indicates whether the seat is expecting to interact with the
|
||||
* user in the UTF-8 character set. (Affects e.g. visual erase
|
||||
* handling in local line editing.)
|
||||
*/
|
||||
int (*is_utf8)(Seat *seat);
|
||||
|
||||
/*
|
||||
* Notify the seat that the back end, and/or the ldisc between
|
||||
* them, have changed their idea of whether they currently want
|
||||
* local echo and/or local line editing enabled.
|
||||
*/
|
||||
void (*echoedit_update)(Seat *seat, int echoing, int editing);
|
||||
|
||||
/*
|
||||
* Return the local X display string relevant to a seat, or NULL
|
||||
* if there isn't one or if the concept is meaningless.
|
||||
*/
|
||||
const char *(*get_x_display)(Seat *seat);
|
||||
|
||||
/*
|
||||
* Return the X11 id of the X terminal window relevant to a seat,
|
||||
* by returning TRUE and filling in the output pointer. Return
|
||||
* FALSE if there isn't one or if the concept is meaningless.
|
||||
*/
|
||||
int (*get_windowid)(Seat *seat, long *id_out);
|
||||
|
||||
/*
|
||||
* Return the pixel size of a terminal character cell. If the
|
||||
* concept is meaningless or the information is unavailable,
|
||||
* return FALSE; otherwise fill in the output pointers and return
|
||||
* TRUE.
|
||||
*/
|
||||
int (*get_char_cell_size)(Seat *seat, int *width, int *height);
|
||||
};
|
||||
|
||||
#define seat_output(seat, is_stderr, data, len) \
|
||||
((seat)->vt->output(seat, is_stderr, data, len))
|
||||
#define seat_eof(seat) \
|
||||
((seat)->vt->eof(seat))
|
||||
#define seat_get_userpass_input(seat, p, input) \
|
||||
((seat)->vt->get_userpass_input(seat, p, input))
|
||||
#define seat_notify_remote_exit(seat) \
|
||||
((seat)->vt->notify_remote_exit(seat))
|
||||
#define seat_update_specials_menu(seat) \
|
||||
((seat)->vt->update_specials_menu(seat))
|
||||
#define seat_get_ttymode(seat, mode) \
|
||||
((seat)->vt->get_ttymode(seat, mode))
|
||||
#define seat_set_busy_status(seat, status) \
|
||||
((seat)->vt->set_busy_status(seat, status))
|
||||
#define seat_verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx) \
|
||||
((seat)->vt->verify_ssh_host_key(seat, h, p, typ, str, fp, cb, ctx))
|
||||
#define seat_confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx) \
|
||||
((seat)->vt->confirm_weak_crypto_primitive(seat, typ, alg, cb, ctx))
|
||||
#define seat_confirm_weak_cached_hostkey(seat, alg, better, cb, ctx) \
|
||||
((seat)->vt->confirm_weak_cached_hostkey(seat, alg, better, cb, ctx))
|
||||
#define seat_is_utf8(seat) \
|
||||
((seat)->vt->is_utf8(seat))
|
||||
#define seat_echoedit_update(seat, echoing, editing) \
|
||||
((seat)->vt->echoedit_update(seat, echoing, editing))
|
||||
#define seat_get_x_display(seat) \
|
||||
((seat)->vt->get_x_display(seat))
|
||||
#define seat_get_windowid(seat, out) \
|
||||
((seat)->vt->get_windowid(seat, out))
|
||||
#define seat_get_char_cell_size(seat, width, height) \
|
||||
((seat)->vt->get_char_cell_size(seat, width, height))
|
||||
|
||||
/* Unlike the seat's actual method, the public entry point
|
||||
* seat_connection_fatal is a wrapper function with a printf-like API,
|
||||
* defined in misc.c. */
|
||||
void seat_connection_fatal(Seat *seat, const char *fmt, ...);
|
||||
|
||||
/* Handy aliases for seat_output which set is_stderr to a fixed value. */
|
||||
#define seat_stdout(seat, data, len) \
|
||||
seat_output(seat, FALSE, data, len)
|
||||
#define seat_stderr(seat, data, len) \
|
||||
seat_output(seat, TRUE, data, len)
|
||||
|
||||
/*
|
||||
* Stub methods for seat implementations that want to use the obvious
|
||||
* null handling for a given method.
|
||||
*
|
||||
* These are generally obvious, except for is_utf8, where you might
|
||||
* plausibly want to return either fixed answer 'no' or 'yes'.
|
||||
*/
|
||||
int nullseat_output(Seat *seat, int is_stderr, const void *data, int len);
|
||||
int nullseat_eof(Seat *seat);
|
||||
int nullseat_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);
|
||||
void nullseat_notify_remote_exit(Seat *seat);
|
||||
void nullseat_connection_fatal(Seat *seat, const char *message);
|
||||
void nullseat_update_specials_menu(Seat *seat);
|
||||
char *nullseat_get_ttymode(Seat *seat, const char *mode);
|
||||
void nullseat_set_busy_status(Seat *seat, BusyStatus status);
|
||||
int nullseat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *key_fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int nullseat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int nullseat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int nullseat_is_never_utf8(Seat *seat);
|
||||
int nullseat_is_always_utf8(Seat *seat);
|
||||
void nullseat_echoedit_update(Seat *seat, int echoing, int editing);
|
||||
const char *nullseat_get_x_display(Seat *seat);
|
||||
int nullseat_get_windowid(Seat *seat, long *id_out);
|
||||
int nullseat_get_char_cell_size(Seat *seat, int *width, int *height);
|
||||
|
||||
/*
|
||||
* Seat functions provided by the platform's console-application
|
||||
* support module (wincons.c, uxcons.c).
|
||||
*/
|
||||
|
||||
void console_connection_fatal(Seat *seat, const char *message);
|
||||
int console_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *key_fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int console_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int console_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Other centralised seat functions.
|
||||
*/
|
||||
int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);
|
||||
|
||||
/*
|
||||
* Exports from the front end.
|
||||
*/
|
||||
@ -721,7 +1020,6 @@ void write_clip(Frontend *frontend, int clipboard, wchar_t *, int *,
|
||||
truecolour *, int, int);
|
||||
void optimised_move(Frontend *frontend, int, int, int);
|
||||
void set_raw_mouse_mode(Frontend *frontend, int);
|
||||
void connection_fatal(Frontend *frontend, const char *, ...);
|
||||
void nonfatal(const char *, ...);
|
||||
void modalfatalbox(const char *, ...);
|
||||
#ifdef macintosh
|
||||
@ -730,28 +1028,6 @@ void modalfatalbox(const char *, ...);
|
||||
void do_beep(Frontend *frontend, int);
|
||||
void sys_cursor(Frontend *frontend, int x, int y);
|
||||
void frontend_request_paste(Frontend *frontend, int clipboard);
|
||||
void frontend_echoedit_update(Frontend *frontend, int echo, int edit);
|
||||
/* It's the backend's responsibility to invoke this at the start of a
|
||||
* connection, if necessary; it can also invoke it later if the set of
|
||||
* special commands changes. It does not need to invoke it at session
|
||||
* shutdown. */
|
||||
void update_specials_menu(Frontend *frontend);
|
||||
int from_backend(Frontend *frontend, int is_stderr, const void *data, int len);
|
||||
/* Called when the back end wants to indicate that EOF has arrived on
|
||||
* the server-to-client stream. Returns FALSE to indicate that we
|
||||
* intend to keep the session open in the other direction, or TRUE to
|
||||
* indicate that if they're closing so are we. */
|
||||
int from_backend_eof(Frontend *frontend);
|
||||
void notify_remote_exit(Frontend *frontend);
|
||||
/* Get a sensible value for a tty mode. NULL return = don't set.
|
||||
* Otherwise, returned value should be freed by caller. */
|
||||
char *get_ttymode(Frontend *frontend, const char *mode);
|
||||
/*
|
||||
* >0 = `got all results, carry on'
|
||||
* 0 = `user cancelled' (FIXME distinguish "give up entirely" and "next auth"?)
|
||||
* <0 = `please call back later with a fuller bufchain'
|
||||
*/
|
||||
int get_userpass_input(prompts_t *p, bufchain *input);
|
||||
#define OPTIMISE_IS_SCROLL 1
|
||||
|
||||
void set_iconic(Frontend *frontend, int iconic);
|
||||
@ -763,16 +1039,6 @@ int is_iconic(Frontend *frontend);
|
||||
void get_window_pos(Frontend *frontend, int *x, int *y);
|
||||
void get_window_pixels(Frontend *frontend, int *x, int *y);
|
||||
char *get_window_title(Frontend *frontend, int icon);
|
||||
/* Hint from backend to frontend about time-consuming operations.
|
||||
* Initial state is assumed to be BUSY_NOT. */
|
||||
enum {
|
||||
BUSY_NOT, /* Not busy, all user interaction OK */
|
||||
BUSY_WAITING, /* Waiting for something; local event loops still running
|
||||
so some local interaction (e.g. menus) OK, but network
|
||||
stuff is suspended */
|
||||
BUSY_CPU /* Locally busy (e.g. crypto); user interaction suspended */
|
||||
};
|
||||
void set_busy_status(Frontend *frontend, int status);
|
||||
int frontend_is_utf8(Frontend *frontend);
|
||||
|
||||
void cleanup_exit(int);
|
||||
@ -1274,7 +1540,7 @@ extern const struct BackendVtable ssh_backend;
|
||||
/*
|
||||
* Exports from ldisc.c.
|
||||
*/
|
||||
Ldisc *ldisc_create(Conf *, Terminal *, Backend *, Frontend *);
|
||||
Ldisc *ldisc_create(Conf *, Terminal *, Backend *, Seat *);
|
||||
void ldisc_configure(Ldisc *, Conf *);
|
||||
void ldisc_free(Ldisc *);
|
||||
void ldisc_send(Ldisc *, const void *buf, int len, int interactive);
|
||||
@ -1403,38 +1669,11 @@ int wc_unescape(char *output, const char *wildcard);
|
||||
* Exports from frontend (windlg.c etc)
|
||||
*/
|
||||
void pgp_fingerprints(void);
|
||||
/*
|
||||
* verify_ssh_host_key() can return one of three values:
|
||||
*
|
||||
* - +1 means `key was OK' (either already known or the user just
|
||||
* approved it) `so continue with the connection'
|
||||
*
|
||||
* - 0 means `key was not OK, abandon the connection'
|
||||
*
|
||||
* - -1 means `I've initiated enquiries, please wait to be called
|
||||
* back via the provided function with a result that's either 0
|
||||
* or +1'.
|
||||
*/
|
||||
int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
/*
|
||||
* have_ssh_host_key() just returns true if a key of that type is
|
||||
* already cached and false otherwise.
|
||||
*/
|
||||
int have_ssh_host_key(const char *host, int port, const char *keytype);
|
||||
/*
|
||||
* askalg and askhk have the same set of return values as
|
||||
* verify_ssh_host_key.
|
||||
*
|
||||
* (askhk is used in the case where we're using a host key below the
|
||||
* warning threshold because that's all we have cached, but at least
|
||||
* one acceptable algorithm is available that we don't have cached.)
|
||||
*/
|
||||
int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Exports from console frontends (wincons.c, uxcons.c)
|
||||
@ -1443,6 +1682,10 @@ int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
extern int console_batch_mode;
|
||||
int console_get_userpass_input(prompts_t *p);
|
||||
int is_interactive(void);
|
||||
void console_print_error_msg(const char *prefix, const char *msg);
|
||||
void console_print_error_msg_fmt_v(
|
||||
const char *prefix, const char *fmt, va_list ap);
|
||||
void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Exports from printing.c.
|
||||
|
18
raw.c
18
raw.c
@ -15,7 +15,7 @@ struct Raw {
|
||||
Socket *s;
|
||||
int closed_on_socket_error;
|
||||
int bufsize;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
LogContext *logctx;
|
||||
int sent_console_eof, sent_socket_eof, session_started;
|
||||
|
||||
@ -29,7 +29,7 @@ static void raw_size(Backend *be, int width, int height);
|
||||
|
||||
static void c_write(Raw *raw, const void *buf, int len)
|
||||
{
|
||||
int backlog = from_backend(raw->frontend, 0, buf, len);
|
||||
int backlog = seat_stdout(raw->seat, buf, len);
|
||||
sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ static void raw_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
Raw *raw = container_of(plug, Raw, plug);
|
||||
backend_socket_log(raw->frontend, raw->logctx, type, addr, port,
|
||||
backend_socket_log(raw->seat, raw->logctx, type, addr, port,
|
||||
error_msg, error_code, raw->conf, raw->session_started);
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ static void raw_check_close(Raw *raw)
|
||||
if (raw->s) {
|
||||
sk_close(raw->s);
|
||||
raw->s = NULL;
|
||||
notify_remote_exit(raw->frontend);
|
||||
seat_notify_remote_exit(raw->seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,13 +67,13 @@ static void raw_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
sk_close(raw->s);
|
||||
raw->s = NULL;
|
||||
raw->closed_on_socket_error = TRUE;
|
||||
notify_remote_exit(raw->frontend);
|
||||
seat_notify_remote_exit(raw->seat);
|
||||
}
|
||||
logevent(raw->logctx, error_msg);
|
||||
connection_fatal(raw->frontend, "%s", error_msg);
|
||||
seat_connection_fatal(raw->seat, "%s", error_msg);
|
||||
} else {
|
||||
/* Otherwise, the remote side closed the connection normally. */
|
||||
if (!raw->sent_console_eof && from_backend_eof(raw->frontend)) {
|
||||
if (!raw->sent_console_eof && seat_eof(raw->seat)) {
|
||||
/*
|
||||
* The front end wants us to close the outgoing side of the
|
||||
* connection as soon as we see EOF from the far end.
|
||||
@ -119,7 +119,7 @@ static const PlugVtable Raw_plugvt = {
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *raw_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *raw_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive)
|
||||
@ -141,7 +141,7 @@ static const char *raw_init(Frontend *frontend, Backend **backend_handle,
|
||||
raw->session_started = FALSE;
|
||||
raw->conf = conf_copy(conf);
|
||||
|
||||
raw->frontend = frontend;
|
||||
raw->seat = seat;
|
||||
raw->logctx = logctx;
|
||||
|
||||
addressfamily = conf_get_int(conf, CONF_addressfamily);
|
||||
|
20
rlogin.c
20
rlogin.c
@ -19,7 +19,7 @@ struct Rlogin {
|
||||
int firstbyte;
|
||||
int cansize;
|
||||
int term_width, term_height;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
LogContext *logctx;
|
||||
|
||||
Conf *conf;
|
||||
@ -33,7 +33,7 @@ struct Rlogin {
|
||||
|
||||
static void c_write(Rlogin *rlogin, const void *buf, int len)
|
||||
{
|
||||
int backlog = from_backend(rlogin->frontend, 0, buf, len);
|
||||
int backlog = seat_stdout(rlogin->seat, buf, len);
|
||||
sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG);
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ static void rlogin_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
Rlogin *rlogin = container_of(plug, Rlogin, plug);
|
||||
backend_socket_log(rlogin->frontend, rlogin->logctx, type, addr, port,
|
||||
backend_socket_log(rlogin->seat, rlogin->logctx, type, addr, port,
|
||||
error_msg, error_code,
|
||||
rlogin->conf, !rlogin->firstbyte);
|
||||
}
|
||||
@ -62,12 +62,12 @@ static void rlogin_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
rlogin->s = NULL;
|
||||
if (error_msg)
|
||||
rlogin->closed_on_socket_error = TRUE;
|
||||
notify_remote_exit(rlogin->frontend);
|
||||
seat_notify_remote_exit(rlogin->seat);
|
||||
}
|
||||
if (error_msg) {
|
||||
/* A socket error has occurred. */
|
||||
logevent(rlogin->logctx, error_msg);
|
||||
connection_fatal(rlogin->frontend, "%s", error_msg);
|
||||
seat_connection_fatal(rlogin->seat, "%s", error_msg);
|
||||
} /* Otherwise, the remote side closed the connection normally. */
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ static const PlugVtable Rlogin_plugvt = {
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *rlogin_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *rlogin_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive)
|
||||
@ -167,7 +167,7 @@ static const char *rlogin_init(Frontend *frontend, Backend **backend_handle,
|
||||
rlogin->backend.vt = &rlogin_backend;
|
||||
rlogin->s = NULL;
|
||||
rlogin->closed_on_socket_error = FALSE;
|
||||
rlogin->frontend = frontend;
|
||||
rlogin->seat = seat;
|
||||
rlogin->logctx = logctx;
|
||||
rlogin->term_width = conf_get_int(conf, CONF_width);
|
||||
rlogin->term_height = conf_get_int(conf, CONF_height);
|
||||
@ -223,11 +223,11 @@ static const char *rlogin_init(Frontend *frontend, Backend **backend_handle,
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
rlogin->prompt = new_prompts(rlogin->frontend);
|
||||
rlogin->prompt = new_prompts();
|
||||
rlogin->prompt->to_server = TRUE;
|
||||
rlogin->prompt->name = dupstr("Rlogin login name");
|
||||
add_prompt(rlogin->prompt, dupstr("rlogin username: "), TRUE);
|
||||
ret = get_userpass_input(rlogin->prompt, NULL);
|
||||
ret = seat_get_userpass_input(rlogin->seat, rlogin->prompt, NULL);
|
||||
if (ret >= 0) {
|
||||
rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result);
|
||||
}
|
||||
@ -274,7 +274,7 @@ static int rlogin_send(Backend *be, const char *buf, int len)
|
||||
* We're still prompting for a username, and aren't talking
|
||||
* directly to the network connection yet.
|
||||
*/
|
||||
int ret = get_userpass_input(rlogin->prompt, &bc);
|
||||
int ret = seat_get_userpass_input(rlogin->seat, rlogin->prompt, &bc);
|
||||
if (ret >= 0) {
|
||||
rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result);
|
||||
/* that nulls out rlogin->prompt, so then we'll start sending
|
||||
|
32
ssh.c
32
ssh.c
@ -31,7 +31,7 @@
|
||||
|
||||
struct Ssh {
|
||||
Socket *s;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
Conf *conf;
|
||||
|
||||
struct ssh_version_receiver version_receiver;
|
||||
@ -140,7 +140,7 @@ static void ssh_connect_ppl(Ssh *ssh, PacketProtocolLayer *ppl)
|
||||
{
|
||||
ppl->bpp = ssh->bpp;
|
||||
ppl->user_input = &ssh->user_input;
|
||||
ppl->frontend = ssh->frontend;
|
||||
ppl->seat = ssh->seat;
|
||||
ppl->ssh = ssh;
|
||||
ppl->remote_bugs = ssh->remote_bugs;
|
||||
}
|
||||
@ -282,7 +282,7 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
|
||||
ssh->base_layer->selfptr = &ssh->base_layer;
|
||||
ssh_ppl_setup_queues(ssh->base_layer, &ssh->bpp->in_pq, &ssh->bpp->out_pq);
|
||||
|
||||
update_specials_menu(ssh->frontend);
|
||||
seat_update_specials_menu(ssh->seat);
|
||||
ssh->pinger = pinger_new(ssh->conf, &ssh->backend);
|
||||
|
||||
queue_idempotent_callback(&ssh->bpp->ic_in_raw);
|
||||
@ -408,7 +408,7 @@ void ssh_remote_error(Ssh *ssh, const char *fmt, ...)
|
||||
ssh_shutdown(ssh);
|
||||
|
||||
logevent(ssh->logctx, msg);
|
||||
connection_fatal(ssh->frontend, "%s", msg);
|
||||
seat_connection_fatal(ssh->seat, "%s", msg);
|
||||
sfree(msg);
|
||||
}
|
||||
}
|
||||
@ -428,7 +428,7 @@ void ssh_remote_eof(Ssh *ssh, const char *fmt, ...)
|
||||
|
||||
logevent(ssh->logctx, msg);
|
||||
sfree(msg);
|
||||
notify_remote_exit(ssh->frontend);
|
||||
seat_notify_remote_exit(ssh->seat);
|
||||
} else {
|
||||
/* This is responding to EOF after we've already seen some
|
||||
* other reason for terminating the session. */
|
||||
@ -448,7 +448,7 @@ void ssh_proto_error(Ssh *ssh, const char *fmt, ...)
|
||||
ssh_initiate_connection_close(ssh);
|
||||
|
||||
logevent(ssh->logctx, msg);
|
||||
connection_fatal(ssh->frontend, "%s", msg);
|
||||
seat_connection_fatal(ssh->seat, "%s", msg);
|
||||
sfree(msg);
|
||||
}
|
||||
}
|
||||
@ -463,10 +463,10 @@ void ssh_sw_abort(Ssh *ssh, const char *fmt, ...)
|
||||
ssh_initiate_connection_close(ssh);
|
||||
|
||||
logevent(ssh->logctx, msg);
|
||||
connection_fatal(ssh->frontend, "%s", msg);
|
||||
seat_connection_fatal(ssh->seat, "%s", msg);
|
||||
sfree(msg);
|
||||
|
||||
notify_remote_exit(ssh->frontend);
|
||||
seat_notify_remote_exit(ssh->seat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +489,7 @@ void ssh_user_close(Ssh *ssh, const char *fmt, ...)
|
||||
logevent(ssh->logctx, msg);
|
||||
sfree(msg);
|
||||
|
||||
notify_remote_exit(ssh->frontend);
|
||||
seat_notify_remote_exit(ssh->seat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ static void ssh_socket_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
*/
|
||||
|
||||
if (!ssh->attempting_connshare)
|
||||
backend_socket_log(ssh->frontend, ssh->logctx, type, addr, port,
|
||||
backend_socket_log(ssh->seat, ssh->logctx, type, addr, port,
|
||||
error_msg, error_code, ssh->conf,
|
||||
ssh->session_started);
|
||||
}
|
||||
@ -665,7 +665,7 @@ static const char *connect_to_host(Ssh *ssh, const char *host, int port,
|
||||
* behave in quite the usual way. */
|
||||
const char *msg =
|
||||
"Reusing a shared connection to this server.\r\n";
|
||||
from_backend(ssh->frontend, TRUE, msg, strlen(msg));
|
||||
seat_stderr(ssh->seat, msg, strlen(msg));
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@ -689,7 +689,7 @@ static const char *connect_to_host(Ssh *ssh, const char *host, int port,
|
||||
&ssh->plug, ssh->conf);
|
||||
if ((err = sk_socket_error(ssh->s)) != NULL) {
|
||||
ssh->s = NULL;
|
||||
notify_remote_exit(ssh->frontend);
|
||||
seat_notify_remote_exit(ssh->seat);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -788,7 +788,7 @@ static void ssh_cache_conf_values(Ssh *ssh)
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*/
|
||||
static const char *ssh_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *ssh_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive)
|
||||
@ -813,7 +813,7 @@ static const char *ssh_init(Frontend *frontend, Backend **backend_handle,
|
||||
ssh->backend.vt = &ssh_backend;
|
||||
*backend_handle = &ssh->backend;
|
||||
|
||||
ssh->frontend = frontend;
|
||||
ssh->seat = seat;
|
||||
ssh->cl_dummy.logctx = ssh->logctx = logctx;
|
||||
|
||||
random_ref(); /* do this now - may be needed by sharing setup code */
|
||||
@ -1003,8 +1003,8 @@ static void ssh_special(Backend *be, SessionSpecialCode code, int arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called when stdout/stderr (the entity to which
|
||||
* from_backend sends data) manages to clear some backlog.
|
||||
* This is called when the seat's output channel manages to clear some
|
||||
* backlog.
|
||||
*/
|
||||
static void ssh_unthrottle(Backend *be, int bufsize)
|
||||
{
|
||||
|
2
ssh.h
2
ssh.h
@ -1397,7 +1397,7 @@ enum { SSH_IMPL_BUG_LIST(TMP_DECLARE_REAL_ENUM) };
|
||||
|
||||
/* Shared function that writes tty modes into a pty request */
|
||||
void write_ttymodes_to_packet_from_conf(
|
||||
BinarySink *bs, Frontend *frontend, Conf *conf,
|
||||
BinarySink *bs, Seat *seat, Conf *conf,
|
||||
int ssh_version, int ospeed, int ispeed);
|
||||
|
||||
/* Shared system for allocating local SSH channel ids. Expects to be
|
||||
|
@ -579,8 +579,8 @@ static int ssh1_connection_filter_queue(struct ssh1_connection_state *s)
|
||||
case SSH1_SMSG_STDERR_DATA:
|
||||
data = get_string(pktin);
|
||||
if (!get_err(pktin)) {
|
||||
int bufsize = from_backend(
|
||||
s->ppl.frontend, pktin->type == SSH1_SMSG_STDERR_DATA,
|
||||
int bufsize = seat_output(
|
||||
s->ppl.seat, pktin->type == SSH1_SMSG_STDERR_DATA,
|
||||
data.ptr, data.len);
|
||||
if (!s->stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
|
||||
s->stdout_throttling = 1;
|
||||
@ -706,7 +706,7 @@ static void ssh1_connection_process_queue(PacketProtocolLayer *ppl)
|
||||
put_uint32(pktout, 0); /* width in pixels */
|
||||
put_uint32(pktout, 0); /* height in pixels */
|
||||
write_ttymodes_to_packet_from_conf(
|
||||
BinarySink_UPCAST(pktout), s->ppl.frontend, s->conf,
|
||||
BinarySink_UPCAST(pktout), s->ppl.seat, s->conf,
|
||||
1, s->ospeed, s->ispeed);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
crMaybeWaitUntilV((pktin = ssh1_connection_pop(s)) != NULL);
|
||||
|
36
ssh1login.c
36
ssh1login.c
@ -279,8 +279,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
"configured list");
|
||||
return;
|
||||
} else if (s->dlgret < 0) { /* none configured; use standard handling */
|
||||
s->dlgret = verify_ssh_host_key(
|
||||
s->ppl.frontend, s->savedhost, s->savedport,
|
||||
s->dlgret = seat_verify_ssh_host_key(
|
||||
s->ppl.seat, s->savedhost, s->savedport,
|
||||
"rsa", keystr, fingerprint, ssh1_login_dialog_callback, s);
|
||||
sfree(keystr);
|
||||
#ifdef FUZZING
|
||||
@ -359,8 +359,9 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
|
||||
/* Warn about chosen cipher if necessary. */
|
||||
if (warn) {
|
||||
s->dlgret = askalg(s->ppl.frontend, "cipher", cipher_string,
|
||||
ssh1_login_dialog_callback, s);
|
||||
s->dlgret = seat_confirm_weak_crypto_primitive(
|
||||
s->ppl.seat, "cipher", cipher_string,
|
||||
ssh1_login_dialog_callback, s);
|
||||
crMaybeWaitUntilV(s->dlgret >= 0);
|
||||
if (s->dlgret == 0) {
|
||||
ssh_user_close(s->ppl.ssh, "User aborted at cipher warning");
|
||||
@ -434,16 +435,17 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
ppl_logevent(("Successfully started encryption"));
|
||||
|
||||
if ((s->username = get_remote_username(s->conf)) == NULL) {
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = TRUE;
|
||||
s->cur_prompt->name = dupstr("SSH login name");
|
||||
add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -691,18 +693,19 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
ppl_printf(("No passphrase required.\r\n"));
|
||||
passphrase = NULL;
|
||||
} else {
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts(s->ppl.seat);
|
||||
s->cur_prompt->to_server = FALSE;
|
||||
s->cur_prompt->name = dupstr("SSH key passphrase");
|
||||
add_prompt(s->cur_prompt,
|
||||
dupprintf("Passphrase for key \"%.100s\": ",
|
||||
s->publickey_comment), FALSE);
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -830,7 +833,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
/*
|
||||
* Otherwise, try various forms of password-like authentication.
|
||||
*/
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts(s->ppl.seat);
|
||||
|
||||
if (conf_get_int(s->conf, CONF_try_tis_auth) &&
|
||||
(s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
|
||||
@ -950,12 +953,13 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
* or CryptoCard exchange if we're doing TIS or CryptoCard
|
||||
* authentication.
|
||||
*/
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
|
@ -1689,7 +1689,7 @@ static void ssh2_setup_pty(struct ssh2_channel *c, PktIn *pktin, void *ctx)
|
||||
{
|
||||
strbuf *modebuf = strbuf_new();
|
||||
write_ttymodes_to_packet_from_conf(
|
||||
BinarySink_UPCAST(modebuf), cs->ppl.frontend, cs->conf,
|
||||
BinarySink_UPCAST(modebuf), cs->ppl.seat, cs->conf,
|
||||
2, s->ospeed, s->ispeed);
|
||||
put_stringsb(pktout, modebuf);
|
||||
}
|
||||
@ -2224,7 +2224,7 @@ static void mainchan_open_confirmation(Channel *chan)
|
||||
struct ssh2_connection_state *s = mc->connlayer;
|
||||
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
|
||||
|
||||
update_specials_menu(s->ppl.frontend);
|
||||
seat_update_specials_menu(s->ppl.seat);
|
||||
ppl_logevent(("Opened main channel"));
|
||||
}
|
||||
|
||||
@ -2248,7 +2248,7 @@ static int mainchan_send(Channel *chan, int is_stderr,
|
||||
assert(chan->vt == &mainchan_channelvt);
|
||||
mainchan *mc = container_of(chan, mainchan, chan);
|
||||
struct ssh2_connection_state *s = mc->connlayer;
|
||||
return from_backend(s->ppl.frontend, is_stderr, data, length);
|
||||
return seat_output(s->ppl.seat, is_stderr, data, length);
|
||||
}
|
||||
|
||||
static void mainchan_send_eof(Channel *chan)
|
||||
@ -2258,14 +2258,13 @@ static void mainchan_send_eof(Channel *chan)
|
||||
struct ssh2_connection_state *s = mc->connlayer;
|
||||
PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
|
||||
|
||||
if (!s->mainchan_eof_sent &&
|
||||
(from_backend_eof(s->ppl.frontend) || s->got_pty)) {
|
||||
if (!s->mainchan_eof_sent && (seat_eof(s->ppl.seat) || s->got_pty)) {
|
||||
/*
|
||||
* Either from_backend_eof told us that the front end wants us
|
||||
* to close the outgoing side of the connection as soon as we
|
||||
* see EOF from the far end, or else we've unilaterally
|
||||
* decided to do that because we've allocated a remote pty and
|
||||
* hence EOF isn't a particularly meaningful concept.
|
||||
* Either seat_eof told us that the front end wants us to
|
||||
* close the outgoing side of the connection as soon as we see
|
||||
* EOF from the far end, or else we've unilaterally decided to
|
||||
* do that because we've allocated a remote pty and hence EOF
|
||||
* isn't a particularly meaningful concept.
|
||||
*/
|
||||
sshfwd_write_eof(mc->sc);
|
||||
ppl_logevent(("Sent EOF message"));
|
||||
|
@ -1136,9 +1136,9 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
BinarySource_UPCAST(pktin)->len + 1);
|
||||
|
||||
if (s->warn_kex) {
|
||||
s->dlgret = askalg(s->ppl.frontend, "key-exchange algorithm",
|
||||
s->kex_alg->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
s->dlgret = seat_confirm_weak_crypto_primitive(
|
||||
s->ppl.seat, "key-exchange algorithm", s->kex_alg->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
crMaybeWaitUntilV(s->dlgret >= 0);
|
||||
if (s->dlgret == 0) {
|
||||
ssh_user_close(s->ppl.ssh, "User aborted at kex warning");
|
||||
@ -1153,9 +1153,9 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
/*
|
||||
* Change warning box wording depending on why we chose a
|
||||
* warning-level host key algorithm. If it's because
|
||||
* that's all we have *cached*, use the askhk mechanism,
|
||||
* and list the host keys we could usefully cross-certify.
|
||||
* Otherwise, use askalg for the standard wording.
|
||||
* that's all we have *cached*, list the host keys we
|
||||
* could usefully cross-certify. Otherwise, use the same
|
||||
* standard wording as any other weak crypto primitive.
|
||||
*/
|
||||
betteralgs = NULL;
|
||||
for (j = 0; j < s->n_uncert_hostkeys; j++) {
|
||||
@ -1184,14 +1184,18 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
}
|
||||
}
|
||||
if (betteralgs) {
|
||||
s->dlgret = askhk(
|
||||
s->ppl.frontend, s->hostkey_alg->ssh_id, betteralgs,
|
||||
/* Use the special warning prompt that lets us provide
|
||||
* a list of better algorithms */
|
||||
s->dlgret = seat_confirm_weak_cached_hostkey(
|
||||
s->ppl.seat, s->hostkey_alg->ssh_id, betteralgs,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
sfree(betteralgs);
|
||||
} else {
|
||||
s->dlgret = askalg(s->ppl.frontend, "host key type",
|
||||
s->hostkey_alg->ssh_id,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
/* If none exist, use the more general 'weak crypto'
|
||||
* warning prompt */
|
||||
s->dlgret = seat_confirm_weak_crypto_primitive(
|
||||
s->ppl.seat, "host key type", s->hostkey_alg->ssh_id,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
}
|
||||
crMaybeWaitUntilV(s->dlgret >= 0);
|
||||
if (s->dlgret == 0) {
|
||||
@ -1201,10 +1205,9 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
}
|
||||
|
||||
if (s->warn_cscipher) {
|
||||
s->dlgret = askalg(s->ppl.frontend,
|
||||
"client-to-server cipher",
|
||||
s->out.cipher->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
s->dlgret = seat_confirm_weak_crypto_primitive(
|
||||
s->ppl.seat, "client-to-server cipher", s->out.cipher->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
crMaybeWaitUntilV(s->dlgret >= 0);
|
||||
if (s->dlgret == 0) {
|
||||
ssh_user_close(s->ppl.ssh, "User aborted at cipher warning");
|
||||
@ -1213,10 +1216,9 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
}
|
||||
|
||||
if (s->warn_sccipher) {
|
||||
s->dlgret = askalg(s->ppl.frontend,
|
||||
"server-to-client cipher",
|
||||
s->in.cipher->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
s->dlgret = seat_confirm_weak_crypto_primitive(
|
||||
s->ppl.seat, "server-to-client cipher", s->in.cipher->name,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
crMaybeWaitUntilV(s->dlgret >= 0);
|
||||
if (s->dlgret == 0) {
|
||||
ssh_user_close(s->ppl.ssh, "User aborted at cipher warning");
|
||||
@ -1309,13 +1311,13 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
/*
|
||||
* Now generate and send e for Diffie-Hellman.
|
||||
*/
|
||||
set_busy_status(s->ppl.frontend, BUSY_CPU); /* this can take a while */
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_CPU);
|
||||
s->e = dh_create_e(s->dh_ctx, s->nbits * 2);
|
||||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, s->kex_init_value);
|
||||
put_mp_ssh2(pktout, s->e);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
|
||||
set_busy_status(s->ppl.frontend, BUSY_WAITING); /* wait for server */
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_WAITING);
|
||||
crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
|
||||
if (pktin->type != s->kex_reply_value) {
|
||||
ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
|
||||
@ -1326,7 +1328,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
pktin->type));
|
||||
return;
|
||||
}
|
||||
set_busy_status(s->ppl.frontend, BUSY_CPU); /* cogitate */
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_CPU);
|
||||
s->hostkeydata = get_string(pktin);
|
||||
s->hkey = ssh_key_new_pub(s->hostkey_alg, s->hostkeydata);
|
||||
s->f = get_mp_ssh2(pktin);
|
||||
@ -1349,7 +1351,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
|
||||
/* We assume everything from now on will be quick, and it might
|
||||
* involve user interaction. */
|
||||
set_busy_status(s->ppl.frontend, BUSY_NOT);
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_NOT);
|
||||
|
||||
put_stringpl(s->exhash, s->hostkeydata);
|
||||
if (dh_is_gex(s->kex_alg)) {
|
||||
@ -1505,7 +1507,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
ppl_logevent(("Doing GSSAPI (with Kerberos V5) Diffie-Hellman key "
|
||||
"exchange with hash %s", s->kex_alg->hash->text_name));
|
||||
/* Now generate e for Diffie-Hellman. */
|
||||
set_busy_status(s->ppl.frontend, BUSY_CPU); /* this can take a while */
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_CPU);
|
||||
s->e = dh_create_e(s->dh_ctx, s->nbits * 2);
|
||||
|
||||
if (s->shgss->lib->gsslogmsg)
|
||||
@ -1664,7 +1666,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
|
||||
/* We assume everything from now on will be quick, and it might
|
||||
* involve user interaction. */
|
||||
set_busy_status(s->ppl.frontend, BUSY_NOT);
|
||||
seat_set_busy_status(s->ppl.seat, BUSY_NOT);
|
||||
|
||||
if (!s->hkey)
|
||||
put_stringz(s->exhash, "");
|
||||
@ -2021,11 +2023,10 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
"configured list");
|
||||
return;
|
||||
} else if (s->dlgret < 0) { /* none configured; use standard handling */
|
||||
s->dlgret = verify_ssh_host_key(s->ppl.frontend,
|
||||
s->savedhost, s->savedport,
|
||||
ssh_key_cache_id(s->hkey),
|
||||
s->keystr, s->fingerprint,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
s->dlgret = seat_verify_ssh_host_key(
|
||||
s->ppl.seat, s->savedhost, s->savedport,
|
||||
ssh_key_cache_id(s->hkey), s->keystr, s->fingerprint,
|
||||
ssh2_transport_dialog_callback, s);
|
||||
#ifdef FUZZING
|
||||
s->dlgret = 1;
|
||||
#endif
|
||||
@ -2205,7 +2206,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
||||
* Update the specials menu to list the remaining uncertified host
|
||||
* keys.
|
||||
*/
|
||||
update_specials_menu(s->ppl.frontend);
|
||||
seat_update_specials_menu(s->ppl.seat);
|
||||
|
||||
/*
|
||||
* Key exchange is over. Loop straight back round if we have a
|
||||
|
@ -362,16 +362,17 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
* it again.
|
||||
*/
|
||||
} else if ((s->username = s->default_username) == NULL) {
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = TRUE;
|
||||
s->cur_prompt->name = dupstr("SSH login name");
|
||||
add_prompt(s->cur_prompt, dupstr("login as: "), TRUE);
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -382,7 +383,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
}
|
||||
if (!s->userpass_ret) {
|
||||
/*
|
||||
* get_userpass_input() failed to get a username.
|
||||
* seat_get_userpass_input() failed to get a username.
|
||||
* Terminate.
|
||||
*/
|
||||
free_prompts(s->cur_prompt);
|
||||
@ -453,7 +454,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
*
|
||||
* The banner data has been sanitised already by this
|
||||
* point, so we can safely pass it straight to
|
||||
* from_backend.
|
||||
* seat_stderr.
|
||||
*/
|
||||
if (bufchain_size(&s->banner) &&
|
||||
(flags & (FLAG_VERBOSE | FLAG_INTERACTIVE))) {
|
||||
@ -461,7 +462,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
void *data;
|
||||
int len;
|
||||
bufchain_prefix(&s->banner, &data, &len);
|
||||
from_backend(s->ppl.frontend, TRUE, data, len);
|
||||
seat_stderr(s->ppl.seat, data, len);
|
||||
bufchain_consume(&s->banner, len);
|
||||
}
|
||||
}
|
||||
@ -766,20 +767,21 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
/*
|
||||
* Get a passphrase from the user.
|
||||
*/
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = FALSE;
|
||||
s->cur_prompt->name = dupstr("SSH key passphrase");
|
||||
add_prompt(s->cur_prompt,
|
||||
dupprintf("Passphrase for key \"%.100s\": ",
|
||||
s->publickey_comment),
|
||||
FALSE);
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt,
|
||||
s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -1089,7 +1091,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
name = get_string(pktin);
|
||||
inst = get_string(pktin);
|
||||
get_string(pktin); /* skip language tag */
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = TRUE;
|
||||
|
||||
/*
|
||||
@ -1144,12 +1146,13 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
* Display any instructions, and get the user's
|
||||
* response(s).
|
||||
*/
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -1213,19 +1216,20 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
|
||||
s->ppl.bpp->pls->actx = SSH2_PKTCTX_PASSWORD;
|
||||
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = TRUE;
|
||||
s->cur_prompt->name = dupstr("SSH password");
|
||||
add_prompt(s->cur_prompt, dupprintf("%s@%s's password: ",
|
||||
s->username, s->hostname),
|
||||
FALSE);
|
||||
|
||||
s->userpass_ret = get_userpass_input(s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
@ -1306,7 +1310,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
|
||||
prompt = get_string(pktin);
|
||||
|
||||
s->cur_prompt = new_prompts(s->ppl.frontend);
|
||||
s->cur_prompt = new_prompts();
|
||||
s->cur_prompt->to_server = TRUE;
|
||||
s->cur_prompt->name = dupstr("New SSH password");
|
||||
s->cur_prompt->instruction = mkstr(prompt);
|
||||
@ -1336,13 +1340,14 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
||||
* password twice.
|
||||
*/
|
||||
while (!got_new) {
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, NULL);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
while (s->userpass_ret < 0 &&
|
||||
bufchain_size(s->ppl.user_input) > 0)
|
||||
s->userpass_ret = get_userpass_input(
|
||||
s->cur_prompt, s->ppl.user_input);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt,
|
||||
s->ppl.user_input);
|
||||
|
||||
if (s->userpass_ret >= 0)
|
||||
break;
|
||||
|
@ -345,7 +345,7 @@ int chan_no_eager_close(Channel *chan, int sent_local_eof, int rcvd_remote_eof)
|
||||
*/
|
||||
|
||||
void write_ttymodes_to_packet_from_conf(
|
||||
BinarySink *bs, Frontend *frontend, Conf *conf,
|
||||
BinarySink *bs, Seat *seat, Conf *conf,
|
||||
int ssh_version, int ospeed, int ispeed)
|
||||
{
|
||||
int i;
|
||||
@ -446,7 +446,7 @@ void write_ttymodes_to_packet_from_conf(
|
||||
* mode.
|
||||
*/
|
||||
if (sval[0] == 'A') {
|
||||
sval = to_free = get_ttymode(frontend, mode->mode);
|
||||
sval = to_free = seat_get_ttymode(seat, mode->mode);
|
||||
} else if (sval[0] == 'V') {
|
||||
sval++; /* skip the 'V' */
|
||||
} else {
|
||||
@ -644,7 +644,7 @@ void ssh_ppl_replace(PacketProtocolLayer *old, PacketProtocolLayer *new)
|
||||
ssh_ppl_setup_queues(new, old->in_pq, old->out_pq);
|
||||
new->selfptr = old->selfptr;
|
||||
new->user_input = old->user_input;
|
||||
new->frontend = old->frontend;
|
||||
new->seat = old->seat;
|
||||
new->ssh = old->ssh;
|
||||
|
||||
*new->selfptr = new;
|
||||
@ -689,7 +689,7 @@ void ssh_ppl_user_output_string_and_free(PacketProtocolLayer *ppl, char *text)
|
||||
/* Messages sent via this function are from the SSH layer, not
|
||||
* from the server-side process, so they always have the stderr
|
||||
* flag set. */
|
||||
from_backend(ppl->frontend, TRUE, text, strlen(text));
|
||||
seat_stderr(ppl->seat, text, strlen(text));
|
||||
sfree(text);
|
||||
}
|
||||
|
||||
|
2
sshppl.h
2
sshppl.h
@ -54,7 +54,7 @@ struct PacketProtocolLayer {
|
||||
|
||||
/* Logging and error-reporting facilities. */
|
||||
LogContext *logctx;
|
||||
void *frontend; /* for dialog boxes etc */
|
||||
Seat *seat; /* for dialog boxes, session output etc */
|
||||
Ssh *ssh; /* for session termination + assorted connection-layer ops */
|
||||
|
||||
/* Known bugs in the remote implementation. */
|
||||
|
16
telnet.c
16
telnet.c
@ -173,7 +173,7 @@ struct Telnet {
|
||||
Socket *s;
|
||||
int closed_on_socket_error;
|
||||
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
LogContext *logctx;
|
||||
Ldisc *ldisc;
|
||||
int term_width, term_height;
|
||||
@ -209,7 +209,7 @@ struct Telnet {
|
||||
static void c_write(Telnet *telnet, const void *buf, int len)
|
||||
{
|
||||
int backlog;
|
||||
backlog = from_backend(telnet->frontend, 0, buf, len);
|
||||
backlog = seat_stdout(telnet->seat, buf, len);
|
||||
sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG);
|
||||
}
|
||||
|
||||
@ -627,7 +627,7 @@ static void telnet_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
Telnet *telnet = container_of(plug, Telnet, plug);
|
||||
backend_socket_log(telnet->frontend, telnet->logctx, type, addr, port,
|
||||
backend_socket_log(telnet->seat, telnet->logctx, type, addr, port,
|
||||
error_msg, error_code, telnet->conf,
|
||||
telnet->session_started);
|
||||
}
|
||||
@ -648,11 +648,11 @@ static void telnet_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
telnet->s = NULL;
|
||||
if (error_msg)
|
||||
telnet->closed_on_socket_error = TRUE;
|
||||
notify_remote_exit(telnet->frontend);
|
||||
seat_notify_remote_exit(telnet->seat);
|
||||
}
|
||||
if (error_msg) {
|
||||
logevent(telnet->logctx, error_msg);
|
||||
connection_fatal(telnet->frontend, "%s", error_msg);
|
||||
seat_connection_fatal(telnet->seat, "%s", error_msg);
|
||||
}
|
||||
/* Otherwise, the remote side closed the connection normally. */
|
||||
}
|
||||
@ -687,7 +687,7 @@ static const PlugVtable Telnet_plugvt = {
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *telnet_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *telnet_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive)
|
||||
@ -709,7 +709,7 @@ static const char *telnet_init(Frontend *frontend, Backend **backend_handle,
|
||||
telnet->activated = FALSE;
|
||||
telnet->sb_buf = NULL;
|
||||
telnet->sb_size = 0;
|
||||
telnet->frontend = frontend;
|
||||
telnet->seat = seat;
|
||||
telnet->logctx = logctx;
|
||||
telnet->term_width = conf_get_int(telnet->conf, CONF_width);
|
||||
telnet->term_height = conf_get_int(telnet->conf, CONF_height);
|
||||
@ -770,7 +770,7 @@ static const char *telnet_init(Frontend *frontend, Backend **backend_handle,
|
||||
/*
|
||||
* We can send special commands from the start.
|
||||
*/
|
||||
update_specials_menu(telnet->frontend);
|
||||
seat_update_specials_menu(telnet->seat);
|
||||
|
||||
/*
|
||||
* loghost overrides realhost, if specified.
|
||||
|
12
terminal.h
12
terminal.h
@ -249,12 +249,12 @@ struct terminal_tag {
|
||||
Conf *conf;
|
||||
|
||||
/*
|
||||
* from_backend calls term_out, but it can also be called from
|
||||
* the ldisc if the ldisc is called _within_ term_out. So we
|
||||
* have to guard against re-entrancy - if from_backend is
|
||||
* called recursively like this, it will simply add data to the
|
||||
* end of the buffer term_out is in the process of working
|
||||
* through.
|
||||
* GUI implementations of seat_output call term_out, but it can
|
||||
* also be called from the ldisc if the ldisc is called _within_
|
||||
* term_out. So we have to guard against re-entrancy - if
|
||||
* seat_output is called recursively like this, it will simply add
|
||||
* data to the end of the buffer term_out is in the process of
|
||||
* working through.
|
||||
*/
|
||||
int in_term_out;
|
||||
|
||||
|
32
testback.c
32
testback.c
@ -32,10 +32,10 @@
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
static const char *null_init(Frontend *, Backend **, Conf *, const char *, int,
|
||||
char **, int, int);
|
||||
static const char *loop_init(Frontend *, Backend **, Conf *, const char *, int,
|
||||
char **, int, int);
|
||||
static const char *null_init(Seat *, Backend **, LogContext *, Conf *,
|
||||
const char *, int, char **, int, int);
|
||||
static const char *loop_init(Seat *, Backend **, LogContext *, Conf *,
|
||||
const char *, int, char **, int, int);
|
||||
static void null_free(Backend *);
|
||||
static void loop_free(Backend *);
|
||||
static void null_reconfig(Backend *, Conf *);
|
||||
@ -68,23 +68,25 @@ const struct BackendVtable loop_backend = {
|
||||
};
|
||||
|
||||
struct loop_state {
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
Backend backend;
|
||||
};
|
||||
|
||||
static const char *null_init(Frontend *frontend, Backend **backend_handle,
|
||||
Conf *conf, const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive) {
|
||||
static const char *null_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive) {
|
||||
*backend_handle = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *loop_init(Frontend *frontend, Backend **backend_handle,
|
||||
Conf *conf, const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive) {
|
||||
static const char *loop_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive) {
|
||||
struct loop_state *st = snew(struct loop_state);
|
||||
|
||||
st->frontend = frontend;
|
||||
st->seat = seat;
|
||||
*backend_handle = &st->backend;
|
||||
return NULL;
|
||||
}
|
||||
@ -113,7 +115,7 @@ static int null_send(Backend *be, const char *buf, int len) {
|
||||
static int loop_send(Backend *be, const char *buf, int len) {
|
||||
struct loop_state *st = container_of(be, struct loop_state, backend);
|
||||
|
||||
return from_backend(st->frontend, 0, buf, len);
|
||||
return seat_output(st->seat, 0, buf, len);
|
||||
}
|
||||
|
||||
static int null_sendbuffer(Backend *be) {
|
||||
@ -162,10 +164,6 @@ static void null_provide_ldisc (Backend *be, Ldisc *ldisc) {
|
||||
|
||||
}
|
||||
|
||||
static void null_provide_logctx(Backend *be, LogContext *logctx) {
|
||||
|
||||
}
|
||||
|
||||
static int null_cfg_info(Backend *be)
|
||||
{
|
||||
return 0;
|
||||
|
@ -3416,7 +3416,7 @@ struct verify_ssh_host_key_result_ctx {
|
||||
char *keystr;
|
||||
void (*callback)(void *callback_ctx, int result);
|
||||
void *callback_ctx;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
};
|
||||
|
||||
static void verify_ssh_host_key_result_callback(void *vctx, int result)
|
||||
@ -3449,7 +3449,7 @@ static void verify_ssh_host_key_result_callback(void *vctx, int result)
|
||||
* Clean up this context structure, whether or not a result was
|
||||
* ever actually delivered from the dialog box.
|
||||
*/
|
||||
unregister_dialog(ctx->frontend, DIALOG_SLOT_NETWORK_PROMPT);
|
||||
unregister_dialog(ctx->seat, DIALOG_SLOT_NETWORK_PROMPT);
|
||||
|
||||
sfree(ctx->host);
|
||||
sfree(ctx->keytype);
|
||||
@ -3457,9 +3457,10 @@ static void verify_ssh_host_key_result_callback(void *vctx, int result)
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int gtk_seat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char absenttxt[] =
|
||||
"The server's host key is not cached. You have no guarantee "
|
||||
@ -3518,13 +3519,13 @@ int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
result_ctx->port = port;
|
||||
result_ctx->keytype = dupstr(keytype);
|
||||
result_ctx->keystr = dupstr(keystr);
|
||||
result_ctx->frontend = frontend;
|
||||
result_ctx->seat = seat;
|
||||
|
||||
mainwin = GTK_WIDGET(get_window(frontend));
|
||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||
msgbox = create_message_box(
|
||||
mainwin, "PuTTY Security Alert", text, string_width(fingerprint), TRUE,
|
||||
&buttons_hostkey, verify_ssh_host_key_result_callback, result_ctx);
|
||||
register_dialog(frontend, DIALOG_SLOT_NETWORK_PROMPT, msgbox);
|
||||
register_dialog(seat, DIALOG_SLOT_NETWORK_PROMPT, msgbox);
|
||||
|
||||
sfree(text);
|
||||
|
||||
@ -3534,7 +3535,7 @@ int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
struct simple_prompt_result_ctx {
|
||||
void (*callback)(void *callback_ctx, int result);
|
||||
void *callback_ctx;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
enum DialogSlot dialog_slot;
|
||||
};
|
||||
|
||||
@ -3550,7 +3551,7 @@ static void simple_prompt_result_callback(void *vctx, int result)
|
||||
* Clean up this context structure, whether or not a result was
|
||||
* ever actually delivered from the dialog box.
|
||||
*/
|
||||
unregister_dialog(ctx->frontend, ctx->dialog_slot);
|
||||
unregister_dialog(ctx->seat, ctx->dialog_slot);
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
@ -3558,8 +3559,9 @@ static void simple_prompt_result_callback(void *vctx, int result)
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
*/
|
||||
int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int gtk_seat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first %s supported by the server is "
|
||||
@ -3575,23 +3577,24 @@ int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
result_ctx = snew(struct simple_prompt_result_ctx);
|
||||
result_ctx->callback = callback;
|
||||
result_ctx->callback_ctx = ctx;
|
||||
result_ctx->frontend = frontend;
|
||||
result_ctx->seat = seat;
|
||||
result_ctx->dialog_slot = DIALOG_SLOT_NETWORK_PROMPT;
|
||||
|
||||
mainwin = GTK_WIDGET(get_window(frontend));
|
||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||
msgbox = create_message_box(
|
||||
mainwin, "PuTTY Security Alert", text,
|
||||
string_width("Reasonably long line of text as a width template"),
|
||||
FALSE, &buttons_yn, simple_prompt_result_callback, result_ctx);
|
||||
register_dialog(frontend, result_ctx->dialog_slot, msgbox);
|
||||
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
||||
|
||||
sfree(text);
|
||||
|
||||
return -1; /* dialog still in progress */
|
||||
}
|
||||
|
||||
int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int gtk_seat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first host key type we have stored for this server\n"
|
||||
@ -3610,16 +3613,16 @@ int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
result_ctx = snew(struct simple_prompt_result_ctx);
|
||||
result_ctx->callback = callback;
|
||||
result_ctx->callback_ctx = ctx;
|
||||
result_ctx->frontend = frontend;
|
||||
result_ctx->seat = seat;
|
||||
result_ctx->dialog_slot = DIALOG_SLOT_NETWORK_PROMPT;
|
||||
|
||||
mainwin = GTK_WIDGET(get_window(frontend));
|
||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||
msgbox = create_message_box(
|
||||
mainwin, "PuTTY Security Alert", text,
|
||||
string_width("is ecdsa-nistp521, which is below the configured"
|
||||
" warning threshold."),
|
||||
FALSE, &buttons_yn, simple_prompt_result_callback, result_ctx);
|
||||
register_dialog(frontend, result_ctx->dialog_slot, msgbox);
|
||||
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
||||
|
||||
sfree(text);
|
||||
|
||||
@ -4048,7 +4051,7 @@ void logevent_dlg(eventlog_stuff *es, const char *string)
|
||||
}
|
||||
}
|
||||
|
||||
int gtkdlg_askappend(Frontend *frontend, Filename *filename,
|
||||
int gtkdlg_askappend(Seat *seat, Filename *filename,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char msgtemplate[] =
|
||||
@ -4076,15 +4079,15 @@ int gtkdlg_askappend(Frontend *frontend, Filename *filename,
|
||||
result_ctx = snew(struct simple_prompt_result_ctx);
|
||||
result_ctx->callback = callback;
|
||||
result_ctx->callback_ctx = ctx;
|
||||
result_ctx->frontend = frontend;
|
||||
result_ctx->seat = seat;
|
||||
result_ctx->dialog_slot = DIALOG_SLOT_LOGFILE_PROMPT;
|
||||
|
||||
mainwin = GTK_WIDGET(get_window(frontend));
|
||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||
msgbox = create_message_box(
|
||||
mainwin, mbtitle, message,
|
||||
string_width("LINE OF TEXT SUITABLE FOR THE ASKAPPEND WIDTH"),
|
||||
FALSE, &buttons_append, simple_prompt_result_callback, result_ctx);
|
||||
register_dialog(frontend, result_ctx->dialog_slot, msgbox);
|
||||
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
||||
|
||||
sfree(message);
|
||||
sfree(mbtitle);
|
||||
|
145
unix/gtkwin.c
145
unix/gtkwin.c
@ -152,7 +152,7 @@ struct Frontend {
|
||||
int width, height, scale;
|
||||
int ignore_sbar;
|
||||
int mouseptr_visible;
|
||||
int busy_status;
|
||||
BusyStatus busy_status;
|
||||
int alt_keycode;
|
||||
int alt_digits;
|
||||
char *wintitle;
|
||||
@ -181,6 +181,7 @@ struct Frontend {
|
||||
int system_mod_mask;
|
||||
#endif
|
||||
|
||||
Seat seat;
|
||||
LogPolicy logpolicy;
|
||||
};
|
||||
|
||||
@ -222,7 +223,7 @@ static void post_fatal_message_box_toplevel(void *vctx)
|
||||
static void post_fatal_message_box(void *vctx, int result)
|
||||
{
|
||||
Frontend *inst = (Frontend *)vctx;
|
||||
unregister_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL);
|
||||
unregister_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL);
|
||||
queue_toplevel_callback(post_fatal_message_box_toplevel, inst);
|
||||
}
|
||||
|
||||
@ -234,7 +235,7 @@ static void common_connfatal_message_box(
|
||||
inst->window, title, msg,
|
||||
string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"),
|
||||
FALSE, &buttons_ok, postfn, inst);
|
||||
register_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL, dialog);
|
||||
register_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL, dialog);
|
||||
sfree(title);
|
||||
}
|
||||
|
||||
@ -252,22 +253,17 @@ static void connection_fatal_callback(void *vctx)
|
||||
static void post_nonfatal_message_box(void *vctx, int result)
|
||||
{
|
||||
Frontend *inst = (Frontend *)vctx;
|
||||
unregister_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL);
|
||||
unregister_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL);
|
||||
}
|
||||
|
||||
void connection_fatal(Frontend *inst, const char *p, ...)
|
||||
static void gtk_seat_connection_fatal(Seat *seat, const char *msg)
|
||||
{
|
||||
va_list ap;
|
||||
char *msg;
|
||||
va_start(ap, p);
|
||||
msg = dupvprintf(p, ap);
|
||||
va_end(ap);
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
if (conf_get_int(inst->conf, CONF_close_on_exit) == FORCE_ON) {
|
||||
fatal_message_box(inst, msg);
|
||||
} else {
|
||||
common_connfatal_message_box(inst, msg, post_nonfatal_message_box);
|
||||
}
|
||||
sfree(msg);
|
||||
|
||||
inst->exited = TRUE; /* suppress normal exit handling */
|
||||
queue_toplevel_callback(connection_fatal_callback, inst);
|
||||
@ -308,29 +304,29 @@ int platform_default_i(const char *name, int def)
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Dummy routine, only required in plink. */
|
||||
void frontend_echoedit_update(Frontend *inst, int echo, int edit)
|
||||
{
|
||||
}
|
||||
|
||||
char *get_ttymode(Frontend *inst, const char *mode)
|
||||
static char *gtk_seat_get_ttymode(Seat *seat, const char *mode)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
return term_get_ttymode(inst->term, mode);
|
||||
}
|
||||
|
||||
int from_backend(Frontend *inst, int is_stderr, const void *data, int len)
|
||||
static int gtk_seat_output(Seat *seat, int is_stderr,
|
||||
const void *data, int len)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
return term_data(inst->term, is_stderr, data, len);
|
||||
}
|
||||
|
||||
int from_backend_eof(Frontend *inst)
|
||||
static int gtk_seat_eof(Seat *seat)
|
||||
{
|
||||
/* Frontend *inst = container_of(seat, Frontend, seat); */
|
||||
return TRUE; /* do respond to incoming EOF with outgoing */
|
||||
}
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
static int gtk_seat_get_userpass_input(Seat *seat, prompts_t *p,
|
||||
bufchain *input)
|
||||
{
|
||||
Frontend *inst = p->frontend;
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
if (ret == -1)
|
||||
@ -338,6 +334,51 @@ int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gtk_seat_is_utf8(Seat *seat)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
return frontend_is_utf8(inst);
|
||||
}
|
||||
|
||||
static int gtk_seat_get_char_cell_size(Seat *seat, int *w, int *h)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
*w = inst->font_width;
|
||||
*h = inst->font_height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void gtk_seat_notify_remote_exit(Seat *seat);
|
||||
static void gtk_seat_update_specials_menu(Seat *seat);
|
||||
static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status);
|
||||
static const char *gtk_seat_get_x_display(Seat *seat);
|
||||
#ifndef NOT_X_WINDOWS
|
||||
static int gtk_seat_get_windowid(Seat *seat, long *id);
|
||||
#endif
|
||||
|
||||
static const SeatVtable gtk_seat_vt = {
|
||||
gtk_seat_output,
|
||||
gtk_seat_eof,
|
||||
gtk_seat_get_userpass_input,
|
||||
gtk_seat_notify_remote_exit,
|
||||
gtk_seat_connection_fatal,
|
||||
gtk_seat_update_specials_menu,
|
||||
gtk_seat_get_ttymode,
|
||||
gtk_seat_set_busy_status,
|
||||
gtk_seat_verify_ssh_host_key,
|
||||
gtk_seat_confirm_weak_crypto_primitive,
|
||||
gtk_seat_confirm_weak_cached_hostkey,
|
||||
gtk_seat_is_utf8,
|
||||
nullseat_echoedit_update,
|
||||
gtk_seat_get_x_display,
|
||||
#ifdef NOT_X_WINDOWS
|
||||
nullseat_get_windowid,
|
||||
#else
|
||||
gtk_seat_get_windowid,
|
||||
#endif
|
||||
gtk_seat_get_char_cell_size,
|
||||
};
|
||||
|
||||
static void gtk_eventlog(LogPolicy *lp, const char *string)
|
||||
{
|
||||
Frontend *inst = container_of(lp, Frontend, logpolicy);
|
||||
@ -348,10 +389,7 @@ static int gtk_askappend(LogPolicy *lp, Filename *filename,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
Frontend *inst = container_of(lp, Frontend, logpolicy);
|
||||
|
||||
int gtkdlg_askappend(Frontend *frontend, Filename *filename,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
return gtkdlg_askappend(inst, filename, callback, ctx);
|
||||
return gtkdlg_askappend(&inst->seat, filename, callback, ctx);
|
||||
}
|
||||
|
||||
static void gtk_logging_error(LogPolicy *lp, const char *event)
|
||||
@ -360,8 +398,8 @@ static void gtk_logging_error(LogPolicy *lp, const char *event)
|
||||
|
||||
/* Send 'can't open log file' errors to the terminal window.
|
||||
* (Marked as stderr, although terminal.c won't care.) */
|
||||
from_backend(inst, 1, event, strlen(event));
|
||||
from_backend(inst, 1, "\r\n", 2);
|
||||
seat_stderr(&inst->seat, event, strlen(event));
|
||||
seat_stderr(&inst->seat, "\r\n", 2);
|
||||
}
|
||||
|
||||
static const LogPolicyVtable gtk_logpolicy_vt = {
|
||||
@ -370,14 +408,6 @@ static const LogPolicyVtable gtk_logpolicy_vt = {
|
||||
gtk_logging_error,
|
||||
};
|
||||
|
||||
int font_dimension(Frontend *inst, int which) /* 0 for width, 1 for height */
|
||||
{
|
||||
if (which)
|
||||
return inst->font_height;
|
||||
else
|
||||
return inst->font_width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
|
||||
* into a cooked one (SELECT, EXTEND, PASTE).
|
||||
@ -402,8 +432,9 @@ static Mouse_Button translate_button(Mouse_Button button)
|
||||
* Return the top-level GtkWindow associated with a particular
|
||||
* front end instance.
|
||||
*/
|
||||
GtkWidget *get_window(Frontend *inst)
|
||||
GtkWidget *gtk_seat_get_window(Seat *seat)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
return inst->window;
|
||||
}
|
||||
|
||||
@ -412,14 +443,20 @@ GtkWidget *get_window(Frontend *inst)
|
||||
* network code wanting to ask an asynchronous user question (e.g.
|
||||
* 'what about this dodgy host key, then?').
|
||||
*/
|
||||
void register_dialog(Frontend *inst, enum DialogSlot slot, GtkWidget *dialog)
|
||||
void register_dialog(Seat *seat, enum DialogSlot slot, GtkWidget *dialog)
|
||||
{
|
||||
Frontend *inst;
|
||||
assert(seat->vt == >k_seat_vt);
|
||||
inst = container_of(seat, Frontend, seat);
|
||||
assert(slot < DIALOG_SLOT_LIMIT);
|
||||
assert(!inst->dialogs[slot]);
|
||||
inst->dialogs[slot] = dialog;
|
||||
}
|
||||
void unregister_dialog(Frontend *inst, enum DialogSlot slot)
|
||||
void unregister_dialog(Seat *seat, enum DialogSlot slot)
|
||||
{
|
||||
Frontend *inst;
|
||||
assert(seat->vt == >k_seat_vt);
|
||||
inst = container_of(seat, Frontend, seat);
|
||||
assert(slot < DIALOG_SLOT_LIMIT);
|
||||
assert(inst->dialogs[slot]);
|
||||
inst->dialogs[slot] = NULL;
|
||||
@ -570,7 +607,7 @@ char *get_window_title(Frontend *inst, int icon)
|
||||
static void warn_on_close_callback(void *vctx, int result)
|
||||
{
|
||||
Frontend *inst = (Frontend *)vctx;
|
||||
unregister_dialog(inst, DIALOG_SLOT_WARN_ON_CLOSE);
|
||||
unregister_dialog(&inst->seat, DIALOG_SLOT_WARN_ON_CLOSE);
|
||||
if (result)
|
||||
gtk_widget_destroy(inst->window);
|
||||
}
|
||||
@ -600,7 +637,7 @@ gint delete_window(GtkWidget *widget, GdkEvent *event, Frontend *inst)
|
||||
"Are you sure you want to close this session?",
|
||||
string_width("Most of the width of the above text"),
|
||||
FALSE, &buttons_yn, warn_on_close_callback, inst);
|
||||
register_dialog(inst, DIALOG_SLOT_WARN_ON_CLOSE, dialog);
|
||||
register_dialog(&inst->seat, DIALOG_SLOT_WARN_ON_CLOSE, dialog);
|
||||
sfree(title);
|
||||
}
|
||||
return TRUE;
|
||||
@ -2435,8 +2472,9 @@ static void exit_callback(void *vctx)
|
||||
}
|
||||
}
|
||||
|
||||
void notify_remote_exit(Frontend *inst)
|
||||
static void gtk_seat_notify_remote_exit(Seat *seat)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
queue_toplevel_callback(exit_callback, inst);
|
||||
}
|
||||
|
||||
@ -2454,7 +2492,7 @@ static void destroy_inst_connection(Frontend *inst)
|
||||
if (inst->term)
|
||||
term_provide_backend(inst->term, NULL);
|
||||
if (inst->menu) {
|
||||
update_specials_menu(inst);
|
||||
seat_update_specials_menu(&inst->seat);
|
||||
gtk_widget_set_sensitive(inst->restartitem, TRUE);
|
||||
}
|
||||
}
|
||||
@ -2537,8 +2575,9 @@ gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void set_busy_status(Frontend *inst, int status)
|
||||
static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
inst->busy_status = status;
|
||||
update_mouseptr(inst);
|
||||
}
|
||||
@ -4190,14 +4229,15 @@ void modalfatalbox(const char *p, ...)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char *get_x_display(Frontend *frontend)
|
||||
static const char *gtk_seat_get_x_display(Seat *seat)
|
||||
{
|
||||
return gdk_get_display();
|
||||
}
|
||||
|
||||
#ifndef NOT_X_WINDOWS
|
||||
int get_windowid(Frontend *inst, long *id)
|
||||
static int gtk_seat_get_windowid(Seat *seat, long *id)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
GdkWindow *window = gtk_widget_get_window(inst->area);
|
||||
if (!GDK_IS_X11_WINDOW(window))
|
||||
return FALSE;
|
||||
@ -4583,7 +4623,7 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
|
||||
title, ctx->newconf, 1,
|
||||
inst->backend ? backend_cfg_info(inst->backend) : 0,
|
||||
after_change_settings_dialog, ctx);
|
||||
register_dialog(inst, DIALOG_SLOT_RECONFIGURE, dialog);
|
||||
register_dialog(&inst->seat, DIALOG_SLOT_RECONFIGURE, dialog);
|
||||
|
||||
sfree(title);
|
||||
}
|
||||
@ -4613,7 +4653,7 @@ static void after_change_settings_dialog(void *vctx, int retval)
|
||||
|
||||
assert(lenof(ww) == NCFGCOLOURS);
|
||||
|
||||
unregister_dialog(inst, DIALOG_SLOT_RECONFIGURE);
|
||||
unregister_dialog(&inst->seat, DIALOG_SLOT_RECONFIGURE);
|
||||
|
||||
if (retval) {
|
||||
inst->conf = newconf;
|
||||
@ -4979,8 +5019,9 @@ void set_window_icon(GtkWidget *window, const char *const *const *icon,
|
||||
|
||||
static void free_special_cmd(gpointer data) { sfree(data); }
|
||||
|
||||
void update_specials_menu(Frontend *inst)
|
||||
static void gtk_seat_update_specials_menu(Seat *seat)
|
||||
{
|
||||
Frontend *inst = container_of(seat, Frontend, seat);
|
||||
const SessionSpecial *specials;
|
||||
|
||||
if (inst->backend)
|
||||
@ -5055,7 +5096,7 @@ static void start_backend(Frontend *inst)
|
||||
|
||||
vt = select_backend(inst->conf);
|
||||
|
||||
error = backend_init(vt, (void *)inst, &inst->backend,
|
||||
error = backend_init(vt, &inst->seat, &inst->backend,
|
||||
inst->logctx, inst->conf,
|
||||
conf_get_str(inst->conf, CONF_host),
|
||||
conf_get_int(inst->conf, CONF_port),
|
||||
@ -5067,7 +5108,7 @@ static void start_backend(Frontend *inst)
|
||||
char *msg = dupprintf("Unable to open connection to %s:\n%s",
|
||||
conf_dest(inst->conf), error);
|
||||
inst->exited = TRUE;
|
||||
connection_fatal(inst, msg);
|
||||
seat_connection_fatal(&inst->seat, msg);
|
||||
sfree(msg);
|
||||
return;
|
||||
}
|
||||
@ -5084,7 +5125,8 @@ static void start_backend(Frontend *inst)
|
||||
|
||||
term_provide_backend(inst->term, inst->backend);
|
||||
|
||||
inst->ldisc = ldisc_create(inst->conf, inst->term, inst->backend, inst);
|
||||
inst->ldisc = ldisc_create(inst->conf, inst->term, inst->backend,
|
||||
&inst->seat);
|
||||
|
||||
gtk_widget_set_sensitive(inst->restartitem, FALSE);
|
||||
}
|
||||
@ -5139,6 +5181,7 @@ void new_session_window(Conf *conf, const char *geometry_string)
|
||||
#endif
|
||||
inst->drawing_area_setup_needed = TRUE;
|
||||
|
||||
inst->seat.vt = >k_seat_vt;
|
||||
inst->logpolicy.vt = >k_logpolicy_vt;
|
||||
|
||||
#ifndef NOT_X_WINDOWS
|
||||
|
23
unix/unix.h
23
unix/unix.h
@ -191,14 +191,8 @@ enum MenuAction {
|
||||
};
|
||||
void app_menu_action(Frontend *frontend, enum MenuAction);
|
||||
|
||||
/* Things pty.c needs from pterm.c */
|
||||
const char *get_x_display(Frontend *frontend);
|
||||
int font_dimension(Frontend *frontend, int which);/* 0 for width, 1 for height */
|
||||
int get_windowid(Frontend *frontend, long *id);
|
||||
|
||||
/* Things gtkdlg.c needs from pterm.c */
|
||||
#ifdef MAY_REFER_TO_GTK_IN_HEADERS
|
||||
GtkWidget *get_window(Frontend *frontend);
|
||||
enum DialogSlot {
|
||||
DIALOG_SLOT_RECONFIGURE,
|
||||
DIALOG_SLOT_NETWORK_PROMPT,
|
||||
@ -207,8 +201,9 @@ enum DialogSlot {
|
||||
DIALOG_SLOT_CONNECTION_FATAL,
|
||||
DIALOG_SLOT_LIMIT /* must remain last */
|
||||
};
|
||||
void register_dialog(Frontend *frontend, enum DialogSlot slot, GtkWidget *dialog);
|
||||
void unregister_dialog(Frontend *frontend, enum DialogSlot slot);
|
||||
GtkWidget *gtk_seat_get_window(Seat *seat);
|
||||
void register_dialog(Seat *seat, enum DialogSlot slot, GtkWidget *dialog);
|
||||
void unregister_dialog(Seat *seat, enum DialogSlot slot);
|
||||
#endif
|
||||
|
||||
/* Things pterm.c needs from gtkdlg.c */
|
||||
@ -224,6 +219,18 @@ eventlog_stuff *eventlogstuff_new(void);
|
||||
void eventlogstuff_free(eventlog_stuff *);
|
||||
void showeventlog(eventlog_stuff *estuff, void *parentwin);
|
||||
void logevent_dlg(eventlog_stuff *estuff, const char *string);
|
||||
int gtkdlg_askappend(Seat *seat, Filename *filename,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int gtk_seat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int gtk_seat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int gtk_seat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
#ifdef MAY_REFER_TO_GTK_IN_HEADERS
|
||||
struct message_box_button {
|
||||
const char *title;
|
||||
|
@ -61,16 +61,58 @@ void cleanup_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void set_busy_status(Frontend *frontend, int status)
|
||||
/*
|
||||
* Various error message and/or fatal exit functions.
|
||||
*/
|
||||
void console_print_error_msg(const char *prefix, const char *msg)
|
||||
{
|
||||
struct termios cf;
|
||||
premsg(&cf);
|
||||
fputs(prefix, stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs(msg, stderr);
|
||||
fputc('\n', stderr);
|
||||
fflush(stderr);
|
||||
postmsg(&cf);
|
||||
}
|
||||
|
||||
void update_specials_menu(Frontend *frontend)
|
||||
void console_print_error_msg_fmt_v(
|
||||
const char *prefix, const char *fmt, va_list ap)
|
||||
{
|
||||
char *msg = dupvprintf(fmt, ap);
|
||||
console_print_error_msg(prefix, msg);
|
||||
sfree(msg);
|
||||
}
|
||||
|
||||
void notify_remote_exit(Frontend *frontend)
|
||||
void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v(prefix, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void modalfatalbox(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("FATAL ERROR", fmt, ap);
|
||||
va_end(ap);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void nonfatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("ERROR", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void console_connection_fatal(Seat *seat, const char *msg)
|
||||
{
|
||||
console_print_error_msg("FATAL ERROR", msg);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void timer_change_notify(unsigned long next)
|
||||
@ -111,9 +153,10 @@ static int block_and_read(int fd, void *buf, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -217,12 +260,9 @@ int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
*/
|
||||
int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first %s supported by the server is\n"
|
||||
@ -268,8 +308,9 @@ int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
}
|
||||
}
|
||||
|
||||
int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first host key type we have stored for this server\n"
|
||||
|
@ -23,43 +23,12 @@
|
||||
SockAddr *unix_sock_addr(const char *path);
|
||||
Socket *new_unix_listener(SockAddr *listenaddr, Plug *plug);
|
||||
|
||||
void modalfatalbox(const char *p, ...)
|
||||
void cmdline_error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("pageant", fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
void nonfatal(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
void connection_fatal(Frontend *frontend, const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
void cmdline_error(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "pageant: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -92,8 +61,6 @@ int platform_default_i(const char *name, int def) { return def; }
|
||||
FontSpec *platform_default_fontspec(const char *name) { return fontspec_new(""); }
|
||||
Filename *platform_default_filename(const char *name) { return filename_from_str(""); }
|
||||
char *x_get_default(const char *key) { return NULL; }
|
||||
int from_backend(Frontend *fe, int is_stderr, const void *data, int datalen)
|
||||
{ assert(!"only here to satisfy notional call from backend_socket_log"); }
|
||||
|
||||
/*
|
||||
* Short description of parameters.
|
||||
@ -338,7 +305,7 @@ enum {
|
||||
static char *askpass_tty(const char *prompt)
|
||||
{
|
||||
int ret;
|
||||
prompts_t *p = new_prompts(NULL);
|
||||
prompts_t *p = new_prompts();
|
||||
p->to_server = FALSE;
|
||||
p->name = dupstr("Pageant passphrase prompt");
|
||||
add_prompt(p, dupcat(prompt, ": ", (const char *)NULL), FALSE);
|
||||
|
@ -29,63 +29,12 @@ static LogContext *logctx;
|
||||
|
||||
static struct termios orig_termios;
|
||||
|
||||
void modalfatalbox(const char *p, ...)
|
||||
void cmdline_error(const char *fmt, ...)
|
||||
{
|
||||
struct termios cf;
|
||||
va_list ap;
|
||||
premsg(&cf);
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("plink", fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
postmsg(&cf);
|
||||
if (logctx) {
|
||||
log_free(logctx);
|
||||
logctx = NULL;
|
||||
}
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void nonfatal(const char *p, ...)
|
||||
{
|
||||
struct termios cf;
|
||||
va_list ap;
|
||||
premsg(&cf);
|
||||
fprintf(stderr, "ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
postmsg(&cf);
|
||||
}
|
||||
void connection_fatal(Frontend *frontend, const 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;
|
||||
}
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void cmdline_error(const 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);
|
||||
}
|
||||
|
||||
@ -132,7 +81,7 @@ int term_ldisc(Terminal *term, int mode)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
void frontend_echoedit_update(Frontend *frontend, int echo, int edit)
|
||||
static void plink_echoedit_update(Seat *seat, int echo, int edit)
|
||||
{
|
||||
/* Update stdin read mode to reflect changes in line discipline. */
|
||||
struct termios mode;
|
||||
@ -158,7 +107,7 @@ void frontend_echoedit_update(Frontend *frontend, int echo, int edit)
|
||||
mode.c_cc[VMIN] = 1;
|
||||
mode.c_cc[VTIME] = 0;
|
||||
/* FIXME: perhaps what we do with IXON/IXOFF should be an
|
||||
* argument to frontend_echoedit_update(), to allow
|
||||
* argument to the echoedit_update() method, to allow
|
||||
* implementation of SSH-2 "xon-xoff" and Rlogin's
|
||||
* equivalent? */
|
||||
mode.c_iflag &= ~IXON;
|
||||
@ -190,7 +139,7 @@ static char *get_ttychar(struct termios *t, int index)
|
||||
return dupprintf("^<%d>", c);
|
||||
}
|
||||
|
||||
char *get_ttymode(Frontend *frontend, const char *mode)
|
||||
static char *plink_get_ttymode(Seat *seat, const char *mode)
|
||||
{
|
||||
/*
|
||||
* Propagate appropriate terminal modes from the local terminal,
|
||||
@ -400,8 +349,7 @@ int try_output(int is_stderr)
|
||||
return bufchain_size(&stdout_data) + bufchain_size(&stderr_data);
|
||||
}
|
||||
|
||||
int from_backend(Frontend *frontend, int is_stderr,
|
||||
const void *data, int len)
|
||||
static int plink_output(Seat *seat, int is_stderr, const void *data, int len)
|
||||
{
|
||||
if (is_stderr) {
|
||||
bufchain_add(&stderr_data, data, len);
|
||||
@ -413,7 +361,7 @@ int from_backend(Frontend *frontend, int is_stderr,
|
||||
}
|
||||
}
|
||||
|
||||
int from_backend_eof(Frontend *frontend)
|
||||
static int plink_eof(Seat *seat)
|
||||
{
|
||||
assert(outgoingeof == EOF_NO);
|
||||
outgoingeof = EOF_PENDING;
|
||||
@ -421,7 +369,7 @@ int from_backend_eof(Frontend *frontend)
|
||||
return FALSE; /* do not respond to incoming EOF with outgoing */
|
||||
}
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
static int plink_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
{
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
@ -430,6 +378,26 @@ int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const SeatVtable plink_seat_vt = {
|
||||
plink_output,
|
||||
plink_eof,
|
||||
plink_get_userpass_input,
|
||||
nullseat_notify_remote_exit,
|
||||
console_connection_fatal,
|
||||
nullseat_update_specials_menu,
|
||||
plink_get_ttymode,
|
||||
nullseat_set_busy_status,
|
||||
console_verify_ssh_host_key,
|
||||
console_confirm_weak_crypto_primitive,
|
||||
console_confirm_weak_cached_hostkey,
|
||||
nullseat_is_never_utf8,
|
||||
plink_echoedit_update,
|
||||
nullseat_get_x_display,
|
||||
nullseat_get_windowid,
|
||||
nullseat_get_char_cell_size,
|
||||
};
|
||||
static Seat plink_seat[1] = {{ &plink_seat_vt }};
|
||||
|
||||
/*
|
||||
* Handle data from a local tty in PARMRK format.
|
||||
*/
|
||||
@ -834,7 +802,7 @@ int main(int argc, char **argv)
|
||||
__AFL_INIT();
|
||||
#endif
|
||||
|
||||
error = backend_init(backvt, NULL, &backend, logctx, conf,
|
||||
error = backend_init(backvt, plink_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost, nodelay,
|
||||
@ -843,7 +811,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Unable to open connection:\n%s\n", error);
|
||||
return 1;
|
||||
}
|
||||
ldisc_create(conf, NULL, backend, NULL);
|
||||
ldisc_create(conf, NULL, backend, plink_seat);
|
||||
sfree(realhost);
|
||||
}
|
||||
|
||||
@ -854,7 +822,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0);
|
||||
atexit(cleanup_termios);
|
||||
frontend_echoedit_update(NULL, 1, 1);
|
||||
seat_echoedit_update(plink_seat, 1, 1);
|
||||
sending = FALSE;
|
||||
now = GETTICKCOUNT();
|
||||
|
||||
|
29
unix/uxpty.c
29
unix/uxpty.c
@ -71,7 +71,7 @@ static int pty_signal_pipe[2] = { -1, -1 }; /* obviously bogus initial val */
|
||||
struct Pty {
|
||||
Conf *conf;
|
||||
int master_fd, slave_fd;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
char name[FILENAME_MAX];
|
||||
pid_t child_pid;
|
||||
int term_width, term_height;
|
||||
@ -633,7 +633,7 @@ void pty_real_select_result(Pty *pty, int event, int status)
|
||||
perror("read pty master");
|
||||
exit(1);
|
||||
} else if (ret > 0) {
|
||||
from_backend(pty->frontend, 0, buf, ret);
|
||||
seat_stdout(pty->seat, buf, ret);
|
||||
}
|
||||
} else if (event == 2) {
|
||||
/*
|
||||
@ -675,10 +675,10 @@ void pty_real_select_result(Pty *pty, int event, int status)
|
||||
" %d (%.400s)]\r\n", WTERMSIG(pty->exit_code),
|
||||
strsignal(WTERMSIG(pty->exit_code)));
|
||||
#endif
|
||||
from_backend(pty->frontend, 0, message, strlen(message));
|
||||
seat_stdout(pty->seat, message, strlen(message));
|
||||
}
|
||||
|
||||
notify_remote_exit(pty->frontend);
|
||||
seat_notify_remote_exit(pty->seat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -736,7 +736,7 @@ static void pty_uxsel_setup(Pty *pty)
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *pty_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive)
|
||||
@ -760,7 +760,7 @@ static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
#endif
|
||||
}
|
||||
|
||||
pty->frontend = frontend;
|
||||
pty->seat = seat;
|
||||
pty->backend.vt = &pty_backend;
|
||||
*backend_handle = &pty->backend;
|
||||
|
||||
@ -781,7 +781,7 @@ static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
close(pty_utmp_helper_pipe); /* just let the child process die */
|
||||
pty_utmp_helper_pipe = -1;
|
||||
} else {
|
||||
const char *location = get_x_display(pty->frontend);
|
||||
const char *location = seat_get_x_display(pty->seat);
|
||||
int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
|
||||
while (pos < len) {
|
||||
int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
|
||||
@ -798,7 +798,7 @@ static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
#endif
|
||||
|
||||
#ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */
|
||||
got_windowid = get_windowid(pty->frontend, &windowid);
|
||||
got_windowid = seat_get_windowid(pty->seat, &windowid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -888,7 +888,7 @@ static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
* Set the IUTF8 bit iff the character set is UTF-8.
|
||||
*/
|
||||
#ifdef IUTF8
|
||||
if (frontend_is_utf8(frontend))
|
||||
if (seat_is_utf8(seat))
|
||||
attrs.c_iflag |= IUTF8;
|
||||
else
|
||||
attrs.c_iflag &= ~IUTF8;
|
||||
@ -928,7 +928,7 @@ static const char *pty_init(Frontend *frontend, Backend **backend_handle,
|
||||
* terminal to match the display the terminal itself is
|
||||
* on.
|
||||
*/
|
||||
const char *x_display = get_x_display(pty->frontend);
|
||||
const char *x_display = seat_get_x_display(pty->seat);
|
||||
char *x_display_env_var = dupprintf("DISPLAY=%s", x_display);
|
||||
putenv(x_display_env_var);
|
||||
/* As above, we don't free this. */
|
||||
@ -1150,16 +1150,17 @@ static void pty_size(Backend *be, int width, int height)
|
||||
{
|
||||
Pty *pty = container_of(be, Pty, backend);
|
||||
struct winsize size;
|
||||
int xpixel = 0, ypixel = 0;
|
||||
|
||||
pty->term_width = width;
|
||||
pty->term_height = height;
|
||||
|
||||
seat_get_char_cell_size(pty->seat, &xpixel, &ypixel);
|
||||
|
||||
size.ws_row = (unsigned short)pty->term_height;
|
||||
size.ws_col = (unsigned short)pty->term_width;
|
||||
size.ws_xpixel = (unsigned short) pty->term_width *
|
||||
font_dimension(pty->frontend, 0);
|
||||
size.ws_ypixel = (unsigned short) pty->term_height *
|
||||
font_dimension(pty->frontend, 1);
|
||||
size.ws_xpixel = (unsigned short)pty->term_width * xpixel;
|
||||
size.ws_ypixel = (unsigned short)pty->term_height * ypixel;
|
||||
ioctl(pty->master_fd, TIOCSWINSZ, (void *)&size);
|
||||
return;
|
||||
}
|
||||
|
12
unix/uxser.c
12
unix/uxser.c
@ -19,7 +19,7 @@
|
||||
|
||||
typedef struct Serial Serial;
|
||||
struct Serial {
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
LogContext *logctx;
|
||||
int fd;
|
||||
int finished;
|
||||
@ -279,7 +279,7 @@ static const char *serial_configure(Serial *serial, Conf *conf)
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *serial_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
int nodelay, int keepalive)
|
||||
@ -292,7 +292,7 @@ static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
serial->backend.vt = &serial_backend;
|
||||
*backend_handle = &serial->backend;
|
||||
|
||||
serial->frontend = frontend;
|
||||
serial->seat = seat;
|
||||
serial->logctx = logctx;
|
||||
serial->finished = FALSE;
|
||||
serial->inbufsize = 0;
|
||||
@ -322,7 +322,7 @@ static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
/*
|
||||
* Specials are always available.
|
||||
*/
|
||||
update_specials_menu(serial->frontend);
|
||||
seat_update_specials_menu(serial->seat);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -390,7 +390,7 @@ static void serial_select_result(int fd, int event)
|
||||
perror("read serial port");
|
||||
exit(1);
|
||||
} else if (ret > 0) {
|
||||
serial->inbufsize = from_backend(serial->frontend, 0, buf, ret);
|
||||
serial->inbufsize = seat_stdout(serial->seat, buf, ret);
|
||||
serial_uxsel_setup(serial); /* might acquire backlog and freeze */
|
||||
}
|
||||
} else if (event == 2) {
|
||||
@ -405,7 +405,7 @@ static void serial_select_result(int fd, int event)
|
||||
|
||||
serial->finished = TRUE;
|
||||
|
||||
notify_remote_exit(serial->frontend);
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,7 @@ Filename *platform_default_filename(const char *name)
|
||||
return filename_from_str("");
|
||||
}
|
||||
|
||||
char *get_ttymode(Frontend *frontend, const char *mode) { return NULL; }
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
{
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
|
@ -28,21 +28,65 @@ void cleanup_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void set_busy_status(Frontend *frontend, int status)
|
||||
/*
|
||||
* Various error message and/or fatal exit functions.
|
||||
*/
|
||||
void console_print_error_msg(const char *prefix, const char *msg)
|
||||
{
|
||||
fputs(prefix, stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs(msg, stderr);
|
||||
fputc('\n', stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void notify_remote_exit(Frontend *frontend)
|
||||
void console_print_error_msg_fmt_v(
|
||||
const char *prefix, const char *fmt, va_list ap)
|
||||
{
|
||||
char *msg = dupvprintf(fmt, ap);
|
||||
console_print_error_msg(prefix, msg);
|
||||
sfree(msg);
|
||||
}
|
||||
|
||||
void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v(prefix, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void modalfatalbox(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("FATAL ERROR", fmt, ap);
|
||||
va_end(ap);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void nonfatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("ERROR", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void console_connection_fatal(Seat *seat, const char *msg)
|
||||
{
|
||||
console_print_error_msg("FATAL ERROR", msg);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
void timer_change_notify(unsigned long next)
|
||||
{
|
||||
}
|
||||
|
||||
int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
int ret;
|
||||
HANDLE hin;
|
||||
@ -145,16 +189,9 @@ int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
}
|
||||
}
|
||||
|
||||
void update_specials_menu(Frontend *frontend)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
*/
|
||||
int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
HANDLE hin;
|
||||
DWORD savemode, i;
|
||||
@ -194,8 +231,9 @@ int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
}
|
||||
}
|
||||
|
||||
int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int console_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
HANDLE hin;
|
||||
DWORD savemode, i;
|
||||
|
@ -798,10 +798,11 @@ static void win_gui_eventlog(LogPolicy *lp, const char *string)
|
||||
|
||||
static void win_gui_logging_error(LogPolicy *lp, const char *event)
|
||||
{
|
||||
extern Seat win_seat[1];
|
||||
/* Send 'can't open log file' errors to the terminal window.
|
||||
* (Marked as stderr, although terminal.c won't care.) */
|
||||
from_backend(NULL, 1, event, strlen(event));
|
||||
from_backend(NULL, 1, "\r\n", 2);
|
||||
seat_stderr(win_seat, event, strlen(event));
|
||||
seat_stderr(win_seat, "\r\n", 2);
|
||||
}
|
||||
|
||||
void showeventlog(HWND hwnd)
|
||||
@ -819,9 +820,10 @@ void showabout(HWND hwnd)
|
||||
DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
|
||||
}
|
||||
|
||||
int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int win_seat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -903,8 +905,9 @@ int verify_ssh_host_key(Frontend *frontend, char *host, int port,
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
*/
|
||||
int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int win_seat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char mbtitle[] = "%s Security Alert";
|
||||
static const char msg[] =
|
||||
@ -928,8 +931,9 @@ int askalg(Frontend *frontend, const char *algtype, const char *algname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int askhk(Frontend *frontend, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
int win_seat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx)
|
||||
{
|
||||
static const char mbtitle[] = "%s Security Alert";
|
||||
static const char msg[] =
|
||||
|
@ -213,7 +213,7 @@ static Mouse_Button lastbtn;
|
||||
static int send_raw_mouse = 0;
|
||||
static int wheel_accumulator = 0;
|
||||
|
||||
static int busy_status = BUSY_NOT;
|
||||
static BusyStatus busy_status = BUSY_NOT;
|
||||
|
||||
static char *window_name, *icon_name;
|
||||
|
||||
@ -230,21 +230,57 @@ static UINT wm_mousewheel = WM_MOUSEWHEEL;
|
||||
const int share_can_be_downstream = TRUE;
|
||||
const int share_can_be_upstream = TRUE;
|
||||
|
||||
/* Dummy routine, only required in plink. */
|
||||
void frontend_echoedit_update(Frontend *frontend, int echo, int edit)
|
||||
{
|
||||
}
|
||||
|
||||
int frontend_is_utf8(Frontend *frontend)
|
||||
{
|
||||
return ucsdata.line_codepage == CP_UTF8;
|
||||
}
|
||||
|
||||
char *get_ttymode(Frontend *frontend, const char *mode)
|
||||
static int win_seat_is_utf8(Seat *seat)
|
||||
{
|
||||
return frontend_is_utf8(NULL);
|
||||
}
|
||||
|
||||
char *win_seat_get_ttymode(Seat *seat, const char *mode)
|
||||
{
|
||||
return term_get_ttymode(term, mode);
|
||||
}
|
||||
|
||||
int win_seat_get_char_cell_size(Seat *seat, int *x, int *y)
|
||||
{
|
||||
*x = font_width;
|
||||
*y = font_height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int win_seat_output(Seat *seat, int is_stderr, const void *, int);
|
||||
static int win_seat_eof(Seat *seat);
|
||||
static int win_seat_get_userpass_input(
|
||||
Seat *seat, prompts_t *p, bufchain *input);
|
||||
static void win_seat_notify_remote_exit(Seat *seat);
|
||||
static void win_seat_connection_fatal(Seat *seat, const char *msg);
|
||||
static void win_seat_update_specials_menu(Seat *seat);
|
||||
static void win_seat_set_busy_status(Seat *seat, BusyStatus status);
|
||||
|
||||
static const SeatVtable win_seat_vt = {
|
||||
win_seat_output,
|
||||
win_seat_eof,
|
||||
win_seat_get_userpass_input,
|
||||
win_seat_notify_remote_exit,
|
||||
win_seat_connection_fatal,
|
||||
win_seat_update_specials_menu,
|
||||
win_seat_get_ttymode,
|
||||
win_seat_set_busy_status,
|
||||
win_seat_verify_ssh_host_key,
|
||||
win_seat_confirm_weak_crypto_primitive,
|
||||
win_seat_confirm_weak_cached_hostkey,
|
||||
win_seat_is_utf8,
|
||||
nullseat_echoedit_update,
|
||||
nullseat_get_x_display,
|
||||
nullseat_get_windowid,
|
||||
win_seat_get_char_cell_size,
|
||||
};
|
||||
Seat win_seat[1] = {{ &win_seat_vt }};
|
||||
|
||||
static void start_backend(void)
|
||||
{
|
||||
const struct BackendVtable *vt;
|
||||
@ -266,7 +302,7 @@ static void start_backend(void)
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
error = backend_init(vt, NULL, &backend, logctx, conf,
|
||||
error = backend_init(vt, win_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost,
|
||||
@ -298,7 +334,7 @@ static void start_backend(void)
|
||||
/*
|
||||
* Set up a line discipline.
|
||||
*/
|
||||
ldisc = ldisc_create(conf, term, backend, NULL);
|
||||
ldisc = ldisc_create(conf, term, backend, win_seat);
|
||||
|
||||
/*
|
||||
* Destroy the Restart Session menu item. (This will return
|
||||
@ -332,7 +368,7 @@ static void close_session(void *ignored_context)
|
||||
backend_free(backend);
|
||||
backend = NULL;
|
||||
term_provide_backend(term, NULL);
|
||||
update_specials_menu(NULL);
|
||||
seat_update_specials_menu(win_seat);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -945,7 +981,7 @@ static void update_savedsess_menu(void)
|
||||
/*
|
||||
* Update the Special Commands submenu.
|
||||
*/
|
||||
void update_specials_menu(Frontend *frontend)
|
||||
static void win_seat_update_specials_menu(Seat *seat)
|
||||
{
|
||||
HMENU new_menu;
|
||||
int i, j;
|
||||
@ -1051,7 +1087,7 @@ static void update_mouse_pointer(void)
|
||||
}
|
||||
}
|
||||
|
||||
void set_busy_status(Frontend *frontend, int status)
|
||||
static void win_seat_set_busy_status(Seat *seat, BusyStatus status)
|
||||
{
|
||||
busy_status = status;
|
||||
update_mouse_pointer();
|
||||
@ -1070,17 +1106,12 @@ void set_raw_mouse_mode(Frontend *frontend, int activate)
|
||||
/*
|
||||
* Print a message box and close the connection.
|
||||
*/
|
||||
void connection_fatal(Frontend *frontend, const char *fmt, ...)
|
||||
static void win_seat_connection_fatal(Seat *seat, const char *msg)
|
||||
{
|
||||
va_list ap;
|
||||
char *stuff, morestuff[100];
|
||||
char title[100];
|
||||
|
||||
va_start(ap, fmt);
|
||||
stuff = dupvprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
sprintf(morestuff, "%.70s Fatal Error", appname);
|
||||
MessageBox(hwnd, stuff, morestuff, MB_ICONERROR | MB_OK);
|
||||
sfree(stuff);
|
||||
sprintf(title, "%.70s Fatal Error", appname);
|
||||
MessageBox(hwnd, msg, title, MB_ICONERROR | MB_OK);
|
||||
|
||||
if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON)
|
||||
PostQuitMessage(1);
|
||||
@ -1969,7 +2000,7 @@ static int is_alt_pressed(void)
|
||||
|
||||
static int resizing;
|
||||
|
||||
void notify_remote_exit(Frontend *frontend)
|
||||
static void win_seat_notify_remote_exit(Seat *seat)
|
||||
{
|
||||
int exitcode, close_on_exit;
|
||||
|
||||
@ -5907,17 +5938,19 @@ static void flip_full_screen()
|
||||
}
|
||||
}
|
||||
|
||||
int from_backend(Frontend *frontend, int is_stderr, const void *data, int len)
|
||||
static int win_seat_output(Seat *seat, int is_stderr,
|
||||
const void *data, int len)
|
||||
{
|
||||
return term_data(term, is_stderr, data, len);
|
||||
}
|
||||
|
||||
int from_backend_eof(Frontend *frontend)
|
||||
static int win_seat_eof(Seat *seat)
|
||||
{
|
||||
return TRUE; /* do respond to incoming EOF with outgoing */
|
||||
}
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
static int win_seat_get_userpass_input(
|
||||
Seat *seat, prompts_t *p, bufchain *input)
|
||||
{
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
|
@ -22,51 +22,12 @@ struct agent_callback {
|
||||
int len;
|
||||
};
|
||||
|
||||
void modalfatalbox(const char *p, ...)
|
||||
void cmdline_error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_start(ap, fmt);
|
||||
console_print_error_msg_fmt_v("plink", fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
if (logctx) {
|
||||
log_free(logctx);
|
||||
logctx = NULL;
|
||||
}
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void nonfatal(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
void connection_fatal(Frontend *frontend, const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "FATAL ERROR: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
if (logctx) {
|
||||
log_free(logctx);
|
||||
logctx = NULL;
|
||||
}
|
||||
cleanup_exit(1);
|
||||
}
|
||||
void cmdline_error(const char *p, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "plink: ");
|
||||
va_start(ap, p);
|
||||
vfprintf(stderr, p, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -83,7 +44,7 @@ int term_ldisc(Terminal *term, int mode)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
void frontend_echoedit_update(Frontend *frontend, int echo, int edit)
|
||||
static void plink_echoedit_update(Seat *seat, int echo, int edit)
|
||||
{
|
||||
/* Update stdin read mode to reflect changes in line discipline. */
|
||||
DWORD mode;
|
||||
@ -100,10 +61,7 @@ void frontend_echoedit_update(Frontend *frontend, int echo, int edit)
|
||||
SetConsoleMode(inhandle, mode);
|
||||
}
|
||||
|
||||
char *get_ttymode(Frontend *frontend, const char *mode) { return NULL; }
|
||||
|
||||
int from_backend(Frontend *frontend, int is_stderr,
|
||||
const void *data, int len)
|
||||
static int plink_output(Seat *seat, int is_stderr, const void *data, int len)
|
||||
{
|
||||
if (is_stderr) {
|
||||
handle_write(stderr_handle, data, len);
|
||||
@ -114,13 +72,13 @@ int from_backend(Frontend *frontend, int is_stderr,
|
||||
return handle_backlog(stdout_handle) + handle_backlog(stderr_handle);
|
||||
}
|
||||
|
||||
int from_backend_eof(Frontend *frontend)
|
||||
static int plink_eof(Seat *seat)
|
||||
{
|
||||
handle_write_eof(stdout_handle);
|
||||
return FALSE; /* do not respond to incoming EOF with outgoing */
|
||||
}
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
static int plink_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
{
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
@ -129,6 +87,26 @@ int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const SeatVtable plink_seat_vt = {
|
||||
plink_output,
|
||||
plink_eof,
|
||||
plink_get_userpass_input,
|
||||
nullseat_notify_remote_exit,
|
||||
console_connection_fatal,
|
||||
nullseat_update_specials_menu,
|
||||
nullseat_get_ttymode,
|
||||
nullseat_set_busy_status,
|
||||
console_verify_ssh_host_key,
|
||||
console_confirm_weak_crypto_primitive,
|
||||
console_confirm_weak_cached_hostkey,
|
||||
nullseat_is_never_utf8,
|
||||
plink_echoedit_update,
|
||||
nullseat_get_x_display,
|
||||
nullseat_get_windowid,
|
||||
nullseat_get_char_cell_size,
|
||||
};
|
||||
static Seat plink_seat[1] = {{ &plink_seat_vt }};
|
||||
|
||||
static DWORD main_thread_id;
|
||||
|
||||
void agent_schedule_callback(void (*callback)(void *, void *, int),
|
||||
@ -476,7 +454,7 @@ int main(int argc, char **argv)
|
||||
int nodelay = conf_get_int(conf, CONF_tcp_nodelay) &&
|
||||
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
|
||||
|
||||
error = backend_init(vt, NULL, &backend, logctx, conf,
|
||||
error = backend_init(vt, plink_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost, nodelay,
|
||||
|
@ -14,7 +14,7 @@ typedef struct Serial Serial;
|
||||
struct Serial {
|
||||
HANDLE port;
|
||||
struct handle *out, *in;
|
||||
Frontend *frontend;
|
||||
Seat *seat;
|
||||
LogContext *logctx;
|
||||
int bufsize;
|
||||
long clearbreak_time;
|
||||
@ -60,15 +60,15 @@ static int serial_gotdata(struct handle *h, void *data, int len)
|
||||
|
||||
serial_terminate(serial);
|
||||
|
||||
notify_remote_exit(serial->frontend);
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
|
||||
logevent(serial->logctx, error_msg);
|
||||
|
||||
connection_fatal(serial->frontend, "%s", error_msg);
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
|
||||
return 0; /* placate optimiser */
|
||||
} else {
|
||||
return from_backend(serial->frontend, 0, data, len);
|
||||
return seat_stdout(serial->seat, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,11 +80,11 @@ static void serial_sentdata(struct handle *h, int new_backlog)
|
||||
|
||||
serial_terminate(serial);
|
||||
|
||||
notify_remote_exit(serial->frontend);
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
|
||||
logevent(serial->logctx, error_msg);
|
||||
|
||||
connection_fatal(serial->frontend, "%s", error_msg);
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
} else {
|
||||
serial->bufsize = new_backlog;
|
||||
}
|
||||
@ -190,7 +190,7 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
* freed by the caller.
|
||||
*/
|
||||
static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
static const char *serial_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port,
|
||||
char **realhost, int nodelay, int keepalive)
|
||||
@ -208,7 +208,7 @@ static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
serial->backend.vt = &serial_backend;
|
||||
*backend_handle = &serial->backend;
|
||||
|
||||
serial->frontend = frontend;
|
||||
serial->seat = seat;
|
||||
serial->logctx = logctx;
|
||||
|
||||
serline = conf_get_str(conf, CONF_serline);
|
||||
@ -265,7 +265,7 @@ static const char *serial_init(Frontend *frontend, Backend **backend_handle,
|
||||
/*
|
||||
* Specials are always available.
|
||||
*/
|
||||
update_specials_menu(serial->frontend);
|
||||
seat_update_specials_menu(serial->seat);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -13,9 +13,7 @@
|
||||
#include "int64.h"
|
||||
#include "winsecur.h"
|
||||
|
||||
char *get_ttymode(Frontend *frontend, const char *mode) { return NULL; }
|
||||
|
||||
int get_userpass_input(prompts_t *p, bufchain *input)
|
||||
int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
{
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
|
@ -237,11 +237,25 @@ void quit_help(HWND hwnd);
|
||||
/*
|
||||
* The terminal and logging context are notionally local to the
|
||||
* Windows front end, but they must be shared between window.c and
|
||||
* windlg.c. Likewise the saved-sessions list.
|
||||
* windlg.c. Likewise the Seat structure for the Windows GUI.
|
||||
*/
|
||||
GLOBAL Terminal *term;
|
||||
GLOBAL LogContext *logctx;
|
||||
|
||||
/*
|
||||
* GUI seat methods in windlg.c.
|
||||
*/
|
||||
int win_seat_verify_ssh_host_key(
|
||||
Seat *seat, const char *host, int port,
|
||||
const char *keytype, char *keystr, char *key_fingerprint,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int win_seat_confirm_weak_crypto_primitive(
|
||||
Seat *seat, const char *algtype, const char *algname,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
int win_seat_confirm_weak_cached_hostkey(
|
||||
Seat *seat, const char *algname, const char *betteralgs,
|
||||
void (*callback)(void *ctx, int result), void *ctx);
|
||||
|
||||
/*
|
||||
* Windows-specific clipboard helper function shared with windlg.c,
|
||||
* which takes the data string in the system code page instead of
|
||||
|
Loading…
Reference in New Issue
Block a user