1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05: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:
Simon Tatham
2018-10-11 19:58:42 +01:00
parent 109df9f46b
commit b4c8fd9d86
42 changed files with 1046 additions and 719 deletions

View File

@ -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);

View File

@ -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 == &gtk_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 == &gtk_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 = &gtk_seat_vt;
inst->logpolicy.vt = &gtk_logpolicy_vt;
#ifndef NOT_X_WINDOWS

View File

@ -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;

View File

@ -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"

View File

@ -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);

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);