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

Yet more global-removal. The static variables in logging.c are now

absent, and also (I think) all the frontend request functions (such
as request_resize) take a context pointer, so that multiple windows
can be handled sensibly. I wouldn't swear to this, but I _think_
that only leaves the Unicode stuff as the last stubborn holdout.

[originally from svn r2147]
This commit is contained in:
Simon Tatham 2002-10-26 12:58:13 +00:00
parent d17f035447
commit 4756c15fc9
24 changed files with 539 additions and 365 deletions

View File

@ -36,7 +36,7 @@ void cleanup_exit(int code)
exit(code); exit(code);
} }
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
char *keystr, char *fingerprint) char *keystr, char *fingerprint)
{ {
int ret; int ret;
@ -142,7 +142,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
* below the configured 'warn' threshold). * below the configured 'warn' threshold).
* cs: 0 = both ways, 1 = client->server, 2 = server->client * cs: 0 = both ways, 1 = client->server, 2 = server->client
*/ */
void askcipher(char *ciphername, int cs) void askcipher(void *frontend, char *ciphername, int cs)
{ {
HANDLE hin; HANDLE hin;
DWORD savemode, i; DWORD savemode, i;
@ -192,7 +192,7 @@ void askcipher(char *ciphername, int cs)
* Ask whether to wipe a session log file before writing to it. * Ask whether to wipe a session log file before writing to it.
* Returns 2 for wipe, 1 for append, 0 for cancel (don't log). * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
*/ */
int askappend(char *filename) int askappend(void *frontend, char *filename)
{ {
HANDLE hin; HANDLE hin;
DWORD savemode, i; DWORD savemode, i;
@ -240,6 +240,13 @@ int askappend(char *filename)
/* /*
* Warn about the obsolescent key file format. * Warn about the obsolescent key file format.
*
* Uniquely among these functions, this one does _not_ expect a
* frontend handle. This means that if PuTTY is ported to a
* platform which requires frontend handles, this function will be
* an anomaly. Fortunately, the problem it addresses will not have
* been present on that platform, so it can plausibly be
* implemented as an empty function.
*/ */
void old_keyfile_warning(void) void old_keyfile_warning(void)
{ {
@ -257,7 +264,7 @@ void old_keyfile_warning(void)
fputs(message, stderr); fputs(message, stderr);
} }
void logevent(char *string) void logevent(void *frontend, char *string)
{ {
} }

View File

@ -8,23 +8,27 @@
#include "putty.h" #include "putty.h"
/* log session to file stuff ... */ /* log session to file stuff ... */
static FILE *lgfp = NULL; struct LogContext {
static char currlogfilename[FILENAME_MAX]; FILE *lgfp;
char currlogfilename[FILENAME_MAX];
void *frontend;
};
static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm); static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm);
/* /*
* Log session traffic. * Log session traffic.
*/ */
void logtraffic(unsigned char c, int logmode) void logtraffic(void *handle, unsigned char c, int logmode)
{ {
struct LogContext *ctx = (struct LogContext *)handle;
if (cfg.logtype > 0) { if (cfg.logtype > 0) {
if (cfg.logtype == logmode) { if (cfg.logtype == logmode) {
/* deferred open file from pgm start? */ /* deferred open file from pgm start? */
if (!lgfp) if (!ctx->lgfp)
logfopen(); logfopen(ctx);
if (lgfp) if (ctx->lgfp)
fputc(c, lgfp); fputc(c, ctx->lgfp);
} }
} }
} }
@ -32,30 +36,33 @@ void logtraffic(unsigned char c, int logmode)
/* /*
* Log an Event Log entry (used in SSH packet logging mode). * Log an Event Log entry (used in SSH packet logging mode).
*/ */
void log_eventlog(char *event) void log_eventlog(void *handle, char *event)
{ {
struct LogContext *ctx = (struct LogContext *)handle;
if (cfg.logtype != LGTYP_PACKETS) if (cfg.logtype != LGTYP_PACKETS)
return; return;
if (!lgfp) if (!ctx->lgfp)
logfopen(); logfopen(ctx);
if (lgfp) if (ctx->lgfp)
fprintf(lgfp, "Event Log: %s\n", event); fprintf(ctx->lgfp, "Event Log: %s\n", event);
} }
/* /*
* Log an SSH packet. * Log an SSH packet.
*/ */
void log_packet(int direction, int type, char *texttype, void *data, int len) void log_packet(void *handle, int direction, int type,
char *texttype, void *data, int len)
{ {
struct LogContext *ctx = (struct LogContext *)handle;
int i, j; int i, j;
char dumpdata[80], smalldata[5]; char dumpdata[80], smalldata[5];
if (cfg.logtype != LGTYP_PACKETS) if (cfg.logtype != LGTYP_PACKETS)
return; return;
if (!lgfp) if (!ctx->lgfp)
logfopen(); logfopen(ctx);
if (lgfp) { if (ctx->lgfp) {
fprintf(lgfp, "%s packet type %d / 0x%02x (%s)\n", fprintf(ctx->lgfp, "%s packet type %d / 0x%02x (%s)\n",
direction == PKT_INCOMING ? "Incoming" : "Outgoing", direction == PKT_INCOMING ? "Incoming" : "Outgoing",
type, type, texttype); type, type, texttype);
for (i = 0; i < len; i += 16) { for (i = 0; i < len; i += 16) {
@ -68,22 +75,23 @@ void log_packet(int direction, int type, char *texttype, void *data, int len)
dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.'); dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.');
} }
strcpy(dumpdata + 10+1+3*16+2+j, "\n"); strcpy(dumpdata + 10+1+3*16+2+j, "\n");
fputs(dumpdata, lgfp); fputs(dumpdata, ctx->lgfp);
} }
fflush(lgfp); fflush(ctx->lgfp);
} }
} }
/* open log file append/overwrite mode */ /* open log file append/overwrite mode */
void logfopen(void) void logfopen(void *handle)
{ {
struct LogContext *ctx = (struct LogContext *)handle;
char buf[256]; char buf[256];
time_t t; time_t t;
struct tm tm; struct tm tm;
char writemod[4]; char writemod[4];
/* Prevent repeat calls */ /* Prevent repeat calls */
if (lgfp) if (ctx->lgfp)
return; return;
if (!cfg.logtype) if (!cfg.logtype)
@ -94,29 +102,29 @@ void logfopen(void)
tm = *localtime(&t); tm = *localtime(&t);
/* substitute special codes in file name */ /* substitute special codes in file name */
xlatlognam(currlogfilename,cfg.logfilename,cfg.host, &tm); xlatlognam(ctx->currlogfilename, cfg.logfilename,cfg.host, &tm);
lgfp = fopen(currlogfilename, "r"); /* file already present? */ ctx->lgfp = fopen(ctx->currlogfilename, "r"); /* file already present? */
if (lgfp) { if (ctx->lgfp) {
int i; int i;
fclose(lgfp); fclose(ctx->lgfp);
i = askappend(currlogfilename); i = askappend(ctx->frontend, ctx->currlogfilename);
if (i == 1) if (i == 1)
writemod[0] = 'a'; /* set append mode */ writemod[0] = 'a'; /* set append mode */
else if (i == 0) { /* cancelled */ else if (i == 0) { /* cancelled */
lgfp = NULL; ctx->lgfp = NULL;
cfg.logtype = 0; /* disable logging */ cfg.logtype = 0; /* disable logging */
return; return;
} }
} }
lgfp = fopen(currlogfilename, writemod); ctx->lgfp = fopen(ctx->currlogfilename, writemod);
if (lgfp) { /* enter into event log */ if (ctx->lgfp) { /* enter into event log */
/* --- write header line into log file */ /* --- write header line into log file */
fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp); fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", ctx->lgfp);
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
fputs(buf, lgfp); fputs(buf, ctx->lgfp);
fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp); fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", ctx->lgfp);
sprintf(buf, "%s session log (%s mode) to file: ", sprintf(buf, "%s session log (%s mode) to file: ",
(writemod[0] == 'a') ? "Appending" : "Writing new", (writemod[0] == 'a') ? "Appending" : "Writing new",
@ -124,20 +132,29 @@ void logfopen(void)
cfg.logtype == LGTYP_DEBUG ? "raw" : cfg.logtype == LGTYP_DEBUG ? "raw" :
cfg.logtype == LGTYP_PACKETS ? "SSH packets" : "<ukwn>")); cfg.logtype == LGTYP_PACKETS ? "SSH packets" : "<ukwn>"));
/* Make sure we do not exceed the output buffer size */ /* Make sure we do not exceed the output buffer size */
strncat(buf, currlogfilename, 128); strncat(buf, ctx->currlogfilename, 128);
buf[strlen(buf)] = '\0'; buf[strlen(buf)] = '\0';
logevent(buf); logevent(ctx->frontend, buf);
} }
} }
void logfclose(void) void logfclose(void *handle)
{ {
if (lgfp) { struct LogContext *ctx = (struct LogContext *)handle;
fclose(lgfp); if (ctx->lgfp) {
lgfp = NULL; fclose(ctx->lgfp);
ctx->lgfp = NULL;
} }
} }
void *log_init(void *frontend)
{
struct LogContext *ctx = smalloc(sizeof(struct LogContext));
ctx->lgfp = NULL;
ctx->frontend = frontend;
return ctx;
}
/* /*
* translate format codes into time/date strings * translate format codes into time/date strings
* and insert them into log file name * and insert them into log file name

View File

@ -153,14 +153,6 @@ struct blob {
}; };
static int cmpkeys_ssh2_asymm(void *av, void *bv); static int cmpkeys_ssh2_asymm(void *av, void *bv);
/*
* This function is needed to link with the DES code. We need not
* have it do anything at all.
*/
void logevent(char *msg)
{
}
#define GET_32BIT(cp) \ #define GET_32BIT(cp) \
(((unsigned long)(unsigned char)(cp)[0] << 24) | \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \
((unsigned long)(unsigned char)(cp)[1] << 16) | \ ((unsigned long)(unsigned char)(cp)[1] << 16) | \

View File

@ -40,7 +40,7 @@ void modalfatalbox(char *p, ...)
WSACleanup(); WSACleanup();
cleanup_exit(1); cleanup_exit(1);
} }
void connection_fatal(char *p, ...) void connection_fatal(void *frontend, char *p, ...)
{ {
va_list ap; va_list ap;
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
@ -538,6 +538,8 @@ int main(int argc, char **argv)
fprintf(stderr, "Unable to open connection:\n%s", error); fprintf(stderr, "Unable to open connection:\n%s", error);
return 1; return 1;
} }
logctx = log_init(NULL);
back->provide_logctx(backhandle, logctx);
sfree(realhost); sfree(realhost);
} }
connopen = 1; connopen = 1;

View File

@ -1472,7 +1472,7 @@ void modalfatalbox(char *fmt, ...)
cleanup_exit(1); cleanup_exit(1);
} }
void connection_fatal(char *fmt, ...) void connection_fatal(void *frontend, char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
@ -1829,6 +1829,8 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
fprintf(stderr, "ssh_init: %s\n", err); fprintf(stderr, "ssh_init: %s\n", err);
return 1; return 1;
} }
logctx = log_init(NULL);
back->provide_logctx(backhandle, logctx);
ssh_sftp_init(); ssh_sftp_init();
if (verbose && realhost != NULL) if (verbose && realhost != NULL)
printf("Connected to %s\n", realhost); printf("Connected to %s\n", realhost);

81
putty.h
View File

@ -16,9 +16,12 @@
#endif #endif
#endif #endif
#ifndef DONE_TYPEDEFS
#define DONE_TYPEDEFS
typedef struct config_tag Config; typedef struct config_tag Config;
typedef struct backend_tag Backend; typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal; typedef struct terminal_tag Terminal;
#endif
#include "puttyps.h" #include "puttyps.h"
#include "network.h" #include "network.h"
@ -187,6 +190,7 @@ struct backend_tag {
int (*sendok) (void *handle); int (*sendok) (void *handle);
int (*ldisc) (void *handle, int); int (*ldisc) (void *handle, int);
void (*provide_ldisc) (void *handle, void *ldisc); void (*provide_ldisc) (void *handle, void *ldisc);
void (*provide_logctx) (void *handle, void *logctx);
/* /*
* back->unthrottle() tells the back end that the front end * back->unthrottle() tells the back end that the front end
* buffer is clearing. * buffer is clearing.
@ -388,43 +392,43 @@ struct RSAKey; /* be a little careful of scope */
/* /*
* Exports from window.c. * Exports from window.c.
*/ */
void request_resize(int, int); void request_resize(void *frontend, int, int);
void do_text(Context, int, int, char *, int, unsigned long, int); void do_text(Context, int, int, char *, int, unsigned long, int);
void do_cursor(Context, int, int, char *, int, unsigned long, int); void do_cursor(Context, int, int, char *, int, unsigned long, int);
int CharWidth(Context ctx, int uc); int CharWidth(Context ctx, int uc);
void set_title(char *); void set_title(void *frontend, char *);
void set_icon(char *); void set_icon(void *frontend, char *);
void set_sbar(int, int, int); void set_sbar(void *frontend, int, int, int);
Context get_ctx(void); Context get_ctx(void *frontend);
void free_ctx(Context); void free_ctx(Context);
void palette_set(int, int, int, int); void palette_set(void *frontend, int, int, int, int);
void palette_reset(void); void palette_reset(void *frontend);
void write_aclip(char *, int, int); void write_aclip(void *frontend, char *, int, int);
void write_clip(wchar_t *, int, int); void write_clip(void *frontend, wchar_t *, int, int);
void get_clip(wchar_t **, int *); void get_clip(void *frontend, wchar_t **, int *);
void optimised_move(int, int, int); void optimised_move(void *frontend, int, int, int);
void set_raw_mouse_mode(int); void set_raw_mouse_mode(void *frontend, int);
Mouse_Button translate_button(Mouse_Button b); Mouse_Button translate_button(void *frontend, Mouse_Button b);
void connection_fatal(char *, ...); void connection_fatal(void *frontend, char *, ...);
void fatalbox(char *, ...); void fatalbox(char *, ...);
void modalfatalbox(char *, ...); void modalfatalbox(char *, ...);
void beep(int); void beep(void *frontend, int);
void begin_session(void); void begin_session(void *frontend);
void sys_cursor(int x, int y); void sys_cursor(void *frontend, int x, int y);
void request_paste(void); void request_paste(void *frontend);
void frontend_keypress(void *frontend); void frontend_keypress(void *frontend);
void ldisc_update(void *frontend, int echo, int edit); void ldisc_update(void *frontend, int echo, int edit);
#define OPTIMISE_IS_SCROLL 1 #define OPTIMISE_IS_SCROLL 1
void set_iconic(int iconic); void set_iconic(void *frontend, int iconic);
void move_window(int x, int y); void move_window(void *frontend, int x, int y);
void set_zorder(int top); void set_zorder(void *frontend, int top);
void refresh_window(void); void refresh_window(void *frontend);
void set_zoomed(int zoomed); void set_zoomed(void *frontend, int zoomed);
int is_iconic(void); int is_iconic(void *frontend);
void get_window_pos(int *x, int *y); void get_window_pos(void *frontend, int *x, int *y);
void get_window_pixels(int *x, int *y); void get_window_pixels(void *frontend, int *x, int *y);
char *get_window_title(int icon); char *get_window_title(void *frontend, int icon);
void cleanup_exit(int); void cleanup_exit(int);
@ -451,7 +455,7 @@ void registry_cleanup(void);
* Exports from terminal.c. * Exports from terminal.c.
*/ */
Terminal *term_init(void); Terminal *term_init(void *frontend);
void term_size(Terminal *, int, int, int); void term_size(Terminal *, int, int, int);
void term_out(Terminal *); void term_out(Terminal *);
void term_paint(Terminal *, Context, int, int, int, int); void term_paint(Terminal *, Context, int, int, int, int);
@ -475,16 +479,19 @@ int from_backend(void *, int is_stderr, char *data, int len);
void term_provide_resize_fn(Terminal *term, void term_provide_resize_fn(Terminal *term,
void (*resize_fn)(void *, int, int), void (*resize_fn)(void *, int, int),
void *resize_ctx); void *resize_ctx);
void term_provide_logctx(Terminal *term, void *logctx);
/* /*
* Exports from logging.c. * Exports from logging.c.
*/ */
void logfopen(); void *log_init(void *frontend);
void logfclose(); void logfopen(void *logctx);
void logtraffic(unsigned char c, int logmode); void logfclose(void *logctx);
void logtraffic(void *logctx, unsigned char c, int logmode);
void log_eventlog(void *logctx, char *string);
enum { PKT_INCOMING, PKT_OUTGOING }; enum { PKT_INCOMING, PKT_OUTGOING };
void log_eventlog(char *string); void log_packet(void *logctx, int direction, int type,
void log_packet(int direction, int type, char *texttype, void *data, int len); char *texttype, void *data, int len);
/* /*
* Exports from raw.c. * Exports from raw.c.
@ -591,11 +598,11 @@ int wc_unescape(char *output, const char *wildcard);
/* /*
* Exports from windlg.c * Exports from windlg.c
*/ */
void logevent(char *); void logevent(void *frontend, char *);
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
char *keystr, char *fingerprint); char *keystr, char *fingerprint);
void askcipher(char *ciphername, int cs); void askcipher(void *frontend, char *ciphername, int cs);
int askappend(char *filename); int askappend(void *frontend, char *filename);
/* /*
* Exports from console.c (that aren't equivalents to things in * Exports from console.c (that aren't equivalents to things in

View File

@ -221,14 +221,6 @@ static int prompt_keyfile(HWND hwnd, char *dlgtitle,
return GetOpenFileName(&of); return GetOpenFileName(&of);
} }
/*
* This function is needed to link with the DES code. We need not
* have it do anything at all.
*/
void logevent(char *msg)
{
}
/* /*
* Dialog-box function for the Licence box. * Dialog-box function for the Licence box.
*/ */

12
raw.c
View File

@ -41,7 +41,7 @@ static int raw_closing(Plug plug, char *error_msg, int error_code,
} }
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
logevent(error_msg); logevent(raw->frontend, error_msg);
connection_fatal("%s", error_msg); connection_fatal("%s", error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
@ -93,7 +93,7 @@ static char *raw_init(void *frontend_handle, void **backend_handle,
{ {
char buf[200]; char buf[200];
sprintf(buf, "Looking up host \"%.170s\"", host); sprintf(buf, "Looking up host \"%.170s\"", host);
logevent(buf); logevent(raw->frontend, buf);
} }
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
@ -109,7 +109,7 @@ static char *raw_init(void *frontend_handle, void **backend_handle,
char buf[200], addrbuf[100]; char buf[200], addrbuf[100];
sk_getaddr(addr, addrbuf, 100); sk_getaddr(addr, addrbuf, 100);
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(raw->frontend, buf);
} }
raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) raw); raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) raw);
if ((err = sk_socket_error(raw->s))) if ((err = sk_socket_error(raw->s)))
@ -191,6 +191,11 @@ static void raw_provide_ldisc(void *handle, void *ldisc)
/* This is a stub. */ /* This is a stub. */
} }
static void raw_provide_logctx(void *handle, void *logctx)
{
/* This is a stub. */
}
static int raw_exitcode(void *handle) static int raw_exitcode(void *handle)
{ {
/* Exit codes are a meaningless concept in the Raw protocol */ /* Exit codes are a meaningless concept in the Raw protocol */
@ -208,6 +213,7 @@ Backend raw_backend = {
raw_sendok, raw_sendok,
raw_ldisc, raw_ldisc,
raw_provide_ldisc, raw_provide_ldisc,
raw_provide_logctx,
raw_unthrottle, raw_unthrottle,
1 1
}; };

View File

@ -42,7 +42,7 @@ static int rlogin_closing(Plug plug, char *error_msg, int error_code,
} }
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
logevent(error_msg); logevent(rlogin->frontend, error_msg);
connection_fatal("%s", error_msg); connection_fatal("%s", error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
@ -124,7 +124,7 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle,
{ {
char buf[200]; char buf[200];
sprintf(buf, "Looking up host \"%.170s\"", host); sprintf(buf, "Looking up host \"%.170s\"", host);
logevent(buf); logevent(rlogin->frontend, buf);
} }
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
@ -140,7 +140,7 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle,
char buf[200], addrbuf[100]; char buf[200], addrbuf[100];
sk_getaddr(addr, addrbuf, 100); sk_getaddr(addr, addrbuf, 100);
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(rlogin->frontend, buf);
} }
rlogin->s = new_connection(addr, *realhost, port, 1, 0, rlogin->s = new_connection(addr, *realhost, port, 1, 0,
nodelay, (Plug) rlogin); nodelay, (Plug) rlogin);
@ -255,6 +255,11 @@ static void rlogin_provide_ldisc(void *handle, void *ldisc)
/* This is a stub. */ /* This is a stub. */
} }
static void rlogin_provide_logctx(void *handle, void *logctx)
{
/* This is a stub. */
}
static int rlogin_exitcode(void *handle) static int rlogin_exitcode(void *handle)
{ {
Rlogin rlogin = (Rlogin) handle; Rlogin rlogin = (Rlogin) handle;
@ -273,6 +278,7 @@ Backend rlogin_backend = {
rlogin_sendok, rlogin_sendok,
rlogin_ldisc, rlogin_ldisc,
rlogin_provide_ldisc, rlogin_provide_ldisc,
rlogin_provide_logctx,
rlogin_unthrottle, rlogin_unthrottle,
1 1
}; };

4
scp.c
View File

@ -260,7 +260,7 @@ void modalfatalbox(char *fmt, ...)
cleanup_exit(1); cleanup_exit(1);
} }
void connection_fatal(char *fmt, ...) void connection_fatal(void *frontend, char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
@ -571,6 +571,8 @@ static void do_cmd(char *host, char *user, char *cmd)
err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0); err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0);
if (err != NULL) if (err != NULL)
bump("ssh_init: %s", err); bump("ssh_init: %s", err);
logctx = log_init(NULL);
back->provide_logctx(backhandle, logctx);
ssh_scp_init(); ssh_scp_init();
if (verbose && realhost != NULL) if (verbose && realhost != NULL)
tell_user(stderr, "Connected to %s\n", realhost); tell_user(stderr, "Connected to %s\n", realhost);

2
sftp.c
View File

@ -942,8 +942,6 @@ struct fxp_name *fxp_dup_name(struct fxp_name *name)
*/ */
void fxp_free_name(struct fxp_name *name) void fxp_free_name(struct fxp_name *name)
{ {
int i;
sfree(name->filename); sfree(name->filename);
sfree(name->longname); sfree(name->longname);
sfree(name); sfree(name);

191
ssh.c
View File

@ -15,26 +15,6 @@
#define TRUE 1 #define TRUE 1
#endif #endif
#define logevent(s) { logevent(s); \
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
{ fprintf(stderr, "%s\n", s); fflush(stderr); } }
/* logevent, only printf-formatted. */
void logeventf(char *fmt, ...)
{
va_list ap;
char stuff[200];
va_start(ap, fmt);
vsprintf(stuff, fmt, ap);
va_end(ap);
logevent(stuff);
}
#define bombout(msg) ( ssh->state = SSH_STATE_CLOSED, \
(ssh->s ? sk_close(ssh->s), ssh->s = NULL : 0), \
logeventf msg, connection_fatal msg )
#define SSH1_MSG_DISCONNECT 1 /* 0x1 */ #define SSH1_MSG_DISCONNECT 1 /* 0x1 */
#define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */ #define SSH1_SMSG_PUBLIC_KEY 2 /* 0x2 */
#define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */ #define SSH1_CMSG_SESSION_KEY 3 /* 0x3 */
@ -557,6 +537,7 @@ struct ssh_tag {
Socket s; Socket s;
void *ldisc; void *ldisc;
void *logctx;
unsigned char session_key[32]; unsigned char session_key[32];
int v1_compressing; int v1_compressing;
@ -658,6 +639,26 @@ struct ssh_tag {
int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen); int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
}; };
#define logevent(s) { logevent(ssh->frontend, s); \
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
{ fprintf(stderr, "%s\n", s); fflush(stderr); } }
/* logevent, only printf-formatted. */
void logeventf(Ssh ssh, char *fmt, ...)
{
va_list ap;
char stuff[200];
va_start(ap, fmt);
vsprintf(stuff, fmt, ap);
va_end(ap);
logevent(stuff);
}
#define bombout(msg) ( ssh->state = SSH_STATE_CLOSED, \
(ssh->s ? sk_close(ssh->s), ssh->s = NULL : 0), \
logeventf msg, connection_fatal msg )
static int ssh_channelcmp(void *av, void *bv) static int ssh_channelcmp(void *av, void *bv)
{ {
struct ssh_channel *a = (struct ssh_channel *) av; struct ssh_channel *a = (struct ssh_channel *) av;
@ -823,7 +824,7 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
if (ssh->cipher && detect_attack(ssh->crcda_ctx, ssh->pktin.data, if (ssh->cipher && detect_attack(ssh->crcda_ctx, ssh->pktin.data,
st->biglen, NULL)) { st->biglen, NULL)) {
bombout(("Network attack (CRC compensation) detected!")); bombout((ssh,"Network attack (CRC compensation) detected!"));
crReturn(0); crReturn(0);
} }
@ -833,7 +834,7 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
st->realcrc = crc32(ssh->pktin.data, st->biglen - 4); st->realcrc = crc32(ssh->pktin.data, st->biglen - 4);
st->gotcrc = GET_32BIT(ssh->pktin.data + st->biglen - 4); st->gotcrc = GET_32BIT(ssh->pktin.data + st->biglen - 4);
if (st->gotcrc != st->realcrc) { if (st->gotcrc != st->realcrc) {
bombout(("Incorrect CRC received on packet")); bombout((ssh,"Incorrect CRC received on packet"));
crReturn(0); crReturn(0);
} }
@ -860,8 +861,11 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
ssh->pktin.type = ssh->pktin.body[-1]; ssh->pktin.type = ssh->pktin.body[-1];
log_packet(PKT_INCOMING, ssh->pktin.type, ssh1_pkt_type(ssh->pktin.type), if (ssh->logctx)
ssh->pktin.body, ssh->pktin.length); log_packet(ssh->logctx,
PKT_INCOMING, ssh->pktin.type,
ssh1_pkt_type(ssh->pktin.type),
ssh->pktin.body, ssh->pktin.length);
if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA || if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA ||
ssh->pktin.type == SSH1_SMSG_STDERR_DATA || ssh->pktin.type == SSH1_SMSG_STDERR_DATA ||
@ -870,7 +874,7 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
ssh->pktin.type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) { ssh->pktin.type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
long stringlen = GET_32BIT(ssh->pktin.body); long stringlen = GET_32BIT(ssh->pktin.body);
if (stringlen + 4 != ssh->pktin.length) { if (stringlen + 4 != ssh->pktin.length) {
bombout(("Received data packet with bogus string length")); bombout((ssh,"Received data packet with bogus string length"));
crReturn(0); crReturn(0);
} }
} }
@ -903,7 +907,7 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
memcpy(buf + nowlen, ssh->pktin.body + 4, msglen); memcpy(buf + nowlen, ssh->pktin.body + 4, msglen);
buf[nowlen + msglen] = '\0'; buf[nowlen + msglen] = '\0';
/* logevent(buf); (this is now done within the bombout macro) */ /* logevent(buf); (this is now done within the bombout macro) */
bombout(("Server sent disconnect message:\n\"%s\"", buf+nowlen)); bombout((ssh,"Server sent disconnect message:\n\"%s\"", buf+nowlen));
crReturn(0); crReturn(0);
} }
@ -957,7 +961,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
* do us any more damage. * do us any more damage.
*/ */
if (st->len < 0 || st->pad < 0 || st->len + st->pad < 0) { if (st->len < 0 || st->pad < 0 || st->len + st->pad < 0) {
bombout(("Incoming packet was garbled on decryption")); bombout((ssh,"Incoming packet was garbled on decryption"));
crReturn(0); crReturn(0);
} }
@ -1005,7 +1009,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
if (ssh->scmac if (ssh->scmac
&& !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4, && !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4,
st->incoming_sequence)) { st->incoming_sequence)) {
bombout(("Incorrect MAC received on packet")); bombout((ssh,"Incorrect MAC received on packet"));
crReturn(0); crReturn(0);
} }
st->incoming_sequence++; /* whether or not we MACed */ st->incoming_sequence++; /* whether or not we MACed */
@ -1034,9 +1038,10 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
ssh->pktin.savedpos = 6; ssh->pktin.savedpos = 6;
ssh->pktin.type = ssh->pktin.data[5]; ssh->pktin.type = ssh->pktin.data[5];
log_packet(PKT_INCOMING, ssh->pktin.type, if (ssh->logctx)
ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type), log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type,
ssh->pktin.data+6, ssh->pktin.length-6); ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),
ssh->pktin.data+6, ssh->pktin.length-6);
switch (ssh->pktin.type) { switch (ssh->pktin.type) {
/* /*
@ -1064,7 +1069,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
memcpy(buf + nowlen, ssh->pktin.data + 14, msglen); memcpy(buf + nowlen, ssh->pktin.data + 14, msglen);
buf[nowlen + msglen] = '\0'; buf[nowlen + msglen] = '\0';
logevent(buf); logevent(buf);
bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"", bombout((ssh,"Server sent disconnect message\ntype %d (%s):\n\"%s\"",
reason, reason,
(reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ? (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
ssh2_disconnect_reasons[reason] : "unknown", ssh2_disconnect_reasons[reason] : "unknown",
@ -1177,8 +1182,10 @@ static int s_wrpkt_prepare(Ssh ssh)
ssh->pktout.body[-1] = ssh->pktout.type; ssh->pktout.body[-1] = ssh->pktout.type;
log_packet(PKT_OUTGOING, ssh->pktout.type, ssh1_pkt_type(ssh->pktout.type), if (ssh->logctx)
ssh->pktout.body, ssh->pktout.length); log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.type,
ssh1_pkt_type(ssh->pktout.type),
ssh->pktout.body, ssh->pktout.length);
if (ssh->v1_compressing) { if (ssh->v1_compressing) {
unsigned char *compblk; unsigned char *compblk;
@ -1459,9 +1466,10 @@ static int ssh2_pkt_construct(Ssh ssh)
{ {
int cipherblk, maclen, padding, i; int cipherblk, maclen, padding, i;
log_packet(PKT_OUTGOING, ssh->pktout.data[5], if (ssh->logctx)
ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]), log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.data[5],
ssh->pktout.data + 6, ssh->pktout.length - 6); ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]),
ssh->pktout.data + 6, ssh->pktout.length - 6);
/* /*
* Compress packet payload. * Compress packet payload.
@ -1626,7 +1634,7 @@ static Bignum ssh2_pkt_getmp(Ssh ssh)
if (!p) if (!p)
return NULL; return NULL;
if (p[0] & 0x80) { if (p[0] & 0x80) {
bombout(("internal error: Can't handle negative mpints")); bombout((ssh,"internal error: Can't handle negative mpints"));
return NULL; return NULL;
} }
b = bignum_from_bytes(p, length); b = bignum_from_bytes(p, length);
@ -1878,11 +1886,11 @@ static int do_ssh_init(Ssh ssh, unsigned char c)
s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0; s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0;
if (cfg.sshprot == 0 && !s->proto1) { if (cfg.sshprot == 0 && !s->proto1) {
bombout(("SSH protocol version 1 required by user but not provided by server")); bombout((ssh,"SSH protocol version 1 required by user but not provided by server"));
crReturn(0); crReturn(0);
} }
if (cfg.sshprot == 3 && !s->proto2) { if (cfg.sshprot == 3 && !s->proto2) {
bombout(("SSH protocol version 2 required by user but not provided by server")); bombout((ssh,"SSH protocol version 2 required by user but not provided by server"));
crReturn(0); crReturn(0);
} }
@ -1989,7 +1997,7 @@ static int ssh_closing(Plug plug, char *error_msg, int error_code,
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
logevent(error_msg); logevent(error_msg);
connection_fatal(error_msg); connection_fatal(ssh->frontend, error_msg);
} else { } else {
/* Otherwise, the remote side closed the connection normally. */ /* Otherwise, the remote side closed the connection normally. */
} }
@ -2238,7 +2246,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (ssh->pktin.type != SSH1_SMSG_PUBLIC_KEY) { if (ssh->pktin.type != SSH1_SMSG_PUBLIC_KEY) {
bombout(("Public key packet not received")); bombout((ssh,"Public key packet not received"));
crReturn(0); crReturn(0);
} }
@ -2299,7 +2307,8 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
fatalbox("Out of memory"); fatalbox("Out of memory");
rsastr_fmt(keystr, &hostkey); rsastr_fmt(keystr, &hostkey);
rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey); rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);
verify_ssh_host_key(ssh->savedhost, ssh->savedport, "rsa", keystr, verify_ssh_host_key(ssh->frontend,
ssh->savedhost, ssh->savedport, "rsa", keystr,
fingerprint); fingerprint);
sfree(keystr); sfree(keystr);
} }
@ -2347,17 +2356,17 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} }
if (!cipher_chosen) { if (!cipher_chosen) {
if ((s->supported_ciphers_mask & (1 << SSH_CIPHER_3DES)) == 0) if ((s->supported_ciphers_mask & (1 << SSH_CIPHER_3DES)) == 0)
bombout(("Server violates SSH 1 protocol by not " bombout((ssh,"Server violates SSH 1 protocol by not "
"supporting 3DES encryption")); "supporting 3DES encryption"));
else else
/* shouldn't happen */ /* shouldn't happen */
bombout(("No supported ciphers found")); bombout((ssh,"No supported ciphers found"));
crReturn(0); crReturn(0);
} }
/* Warn about chosen cipher if necessary. */ /* Warn about chosen cipher if necessary. */
if (warn) if (warn)
askcipher(cipher_string, 0); askcipher(ssh->frontend, cipher_string, 0);
} }
switch (s->cipher_type) { switch (s->cipher_type) {
@ -2400,7 +2409,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS) { if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
bombout(("Encryption not successfully enabled")); bombout((ssh,"Encryption not successfully enabled"));
crReturn(0); crReturn(0);
} }
@ -2694,7 +2703,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
PKT_STR, "No more passwords available to try", PKT_STR, "No more passwords available to try",
PKT_END); PKT_END);
logevent("Unable to authenticate"); logevent("Unable to authenticate");
connection_fatal("Unable to authenticate"); connection_fatal(ssh->frontend, "Unable to authenticate");
ssh->state = SSH_STATE_CLOSED; ssh->state = SSH_STATE_CLOSED;
crReturn(1); crReturn(1);
} }
@ -2750,7 +2759,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
continue; /* go and try password */ continue; /* go and try password */
} }
if (ssh->pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) { if (ssh->pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
bombout(("Bizarre response to offer of public key")); bombout((ssh,"Bizarre response to offer of public key"));
crReturn(0); crReturn(0);
} }
@ -2786,7 +2795,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
" our public key.\r\n"); " our public key.\r\n");
continue; /* go and try password */ continue; /* go and try password */
} else if (ssh->pktin.type != SSH1_SMSG_SUCCESS) { } else if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
bombout(("Bizarre response to RSA authentication response")); bombout((ssh,"Bizarre response to RSA authentication response"));
crReturn(0); crReturn(0);
} }
@ -2919,7 +2928,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
c_write_str(ssh, "Access denied\r\n"); c_write_str(ssh, "Access denied\r\n");
logevent("Authentication refused"); logevent("Authentication refused");
} else if (ssh->pktin.type != SSH1_SMSG_SUCCESS) { } else if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
bombout(("Strange packet received, type %d", ssh->pktin.type)); bombout((ssh,"Strange packet received, type %d", ssh->pktin.type));
crReturn(0); crReturn(0);
} }
} }
@ -3019,7 +3028,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (!ispkt); } while (!ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS if (ssh->pktin.type != SSH1_SMSG_SUCCESS
&& ssh->pktin.type != SSH1_SMSG_FAILURE) { && ssh->pktin.type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion")); bombout((ssh,"Protocol confusion"));
crReturnV; crReturnV;
} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) { } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
logevent("Agent forwarding refused"); logevent("Agent forwarding refused");
@ -3047,7 +3056,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (!ispkt); } while (!ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS if (ssh->pktin.type != SSH1_SMSG_SUCCESS
&& ssh->pktin.type != SSH1_SMSG_FAILURE) { && ssh->pktin.type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion")); bombout((ssh,"Protocol confusion"));
crReturnV; crReturnV;
} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) { } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
logevent("X11 forwarding refused"); logevent("X11 forwarding refused");
@ -3156,7 +3165,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (!ispkt); } while (!ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS if (ssh->pktin.type != SSH1_SMSG_SUCCESS
&& ssh->pktin.type != SSH1_SMSG_FAILURE) { && ssh->pktin.type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion")); bombout((ssh,"Protocol confusion"));
crReturnV; crReturnV;
} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) { } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
c_write_str(ssh, "Server refused port" c_write_str(ssh, "Server refused port"
@ -3181,7 +3190,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (!ispkt); } while (!ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS if (ssh->pktin.type != SSH1_SMSG_SUCCESS
&& ssh->pktin.type != SSH1_SMSG_FAILURE) { && ssh->pktin.type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion")); bombout((ssh,"Protocol confusion"));
crReturnV; crReturnV;
} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) { } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
c_write_str(ssh, "Server refused to allocate pty\r\n"); c_write_str(ssh, "Server refused to allocate pty\r\n");
@ -3199,7 +3208,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (!ispkt); } while (!ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS if (ssh->pktin.type != SSH1_SMSG_SUCCESS
&& ssh->pktin.type != SSH1_SMSG_FAILURE) { && ssh->pktin.type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion")); bombout((ssh,"Protocol confusion"));
crReturnV; crReturnV;
} else if (ssh->pktin.type == SSH1_SMSG_FAILURE) { } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
c_write_str(ssh, "Server refused to compress\r\n"); c_write_str(ssh, "Server refused to compress\r\n");
@ -3450,7 +3459,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
sfree(c); sfree(c);
} }
} else { } else {
bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n", bombout((ssh,"Received CHANNEL_CLOSE%s for %s channel %d\n",
ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE ? "" : ssh->pktin.type == SSH1_MSG_CHANNEL_CLOSE ? "" :
"_CONFIRMATION", c ? "half-open" : "nonexistent", "_CONFIRMATION", c ? "half-open" : "nonexistent",
i)); i));
@ -3552,7 +3561,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh->state = SSH_STATE_CLOSED; ssh->state = SSH_STATE_CLOSED;
crReturnV; crReturnV;
} else { } else {
bombout(("Strange packet received: type %d", ssh->pktin.type)); bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
} else { } else {
@ -3820,7 +3829,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
int i, j, len; int i, j, len;
if (ssh->pktin.type != SSH2_MSG_KEXINIT) { if (ssh->pktin.type != SSH2_MSG_KEXINIT) {
bombout(("expected key exchange packet from server")); bombout((ssh,"expected key exchange packet from server"));
crReturn(0); crReturn(0);
} }
ssh->kex = NULL; ssh->kex = NULL;
@ -3865,12 +3874,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} }
if (s->cscipher_tobe) { if (s->cscipher_tobe) {
if (s->warn) if (s->warn)
askcipher(s->cscipher_tobe->name, 1); askcipher(ssh->frontend, s->cscipher_tobe->name, 1);
break; break;
} }
} }
if (!s->cscipher_tobe) { if (!s->cscipher_tobe) {
bombout(("Couldn't agree a client-to-server cipher (available: %s)", str)); bombout((ssh,"Couldn't agree a client-to-server cipher (available: %s)", str));
crReturn(0); crReturn(0);
} }
@ -3890,12 +3899,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} }
if (s->sccipher_tobe) { if (s->sccipher_tobe) {
if (s->warn) if (s->warn)
askcipher(s->sccipher_tobe->name, 2); askcipher(ssh->frontend, s->sccipher_tobe->name, 2);
break; break;
} }
} }
if (!s->sccipher_tobe) { if (!s->sccipher_tobe) {
bombout(("Couldn't agree a server-to-client cipher (available: %s)", str)); bombout((ssh,"Couldn't agree a server-to-client cipher (available: %s)", str));
crReturn(0); crReturn(0);
} }
@ -3968,7 +3977,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (ssh->pktin.type != SSH2_MSG_KEX_DH_GEX_GROUP) { if (ssh->pktin.type != SSH2_MSG_KEX_DH_GEX_GROUP) {
bombout(("expected key exchange group packet from server")); bombout((ssh,"expected key exchange group packet from server"));
crReturn(0); crReturn(0);
} }
s->p = ssh2_pkt_getmp(ssh); s->p = ssh2_pkt_getmp(ssh);
@ -3994,7 +4003,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (ssh->pktin.type != s->kex_reply_value) { if (ssh->pktin.type != s->kex_reply_value) {
bombout(("expected key exchange reply packet from server")); bombout((ssh,"expected key exchange reply packet from server"));
crReturn(0); crReturn(0);
} }
ssh2_pkt_getstring(ssh, &s->hostkeydata, &s->hostkeylen); ssh2_pkt_getstring(ssh, &s->hostkeydata, &s->hostkeylen);
@ -4025,7 +4034,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (!s->hkey || if (!s->hkey ||
!ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen, !ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,
s->exchange_hash, 20)) { s->exchange_hash, 20)) {
bombout(("Server's host key did not match the signature supplied")); bombout((ssh,"Server's host key did not match the signature supplied"));
crReturn(0); crReturn(0);
} }
@ -4035,7 +4044,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
*/ */
s->keystr = ssh->hostkey->fmtkey(s->hkey); s->keystr = ssh->hostkey->fmtkey(s->hkey);
s->fingerprint = ssh->hostkey->fingerprint(s->hkey); s->fingerprint = ssh->hostkey->fingerprint(s->hkey);
verify_ssh_host_key(ssh->savedhost, ssh->savedport, ssh->hostkey->keytype, verify_ssh_host_key(ssh->frontend,
ssh->savedhost, ssh->savedport, ssh->hostkey->keytype,
s->keystr, s->fingerprint); s->keystr, s->fingerprint);
if (s->first_kex) { /* don't bother logging this in rekeys */ if (s->first_kex) { /* don't bother logging this in rekeys */
logevent("Host key fingerprint is:"); logevent("Host key fingerprint is:");
@ -4056,7 +4066,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
*/ */
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (ssh->pktin.type != SSH2_MSG_NEWKEYS) { if (ssh->pktin.type != SSH2_MSG_NEWKEYS) {
bombout(("expected new-keys packet from server")); bombout((ssh,"expected new-keys packet from server"));
crReturn(0); crReturn(0);
} }
@ -4281,7 +4291,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_send(ssh); ssh2_pkt_send(ssh);
crWaitUntilV(ispkt); crWaitUntilV(ispkt);
if (ssh->pktin.type != SSH2_MSG_SERVICE_ACCEPT) { if (ssh->pktin.type != SSH2_MSG_SERVICE_ACCEPT) {
bombout(("Server refused user authentication protocol")); bombout((ssh,"Server refused user authentication protocol"));
crReturnV; crReturnV;
} }
@ -4381,7 +4391,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
/* Load the pub half of cfg.keyfile so we notice if it's in Pageant */ /* Load the pub half of cfg.keyfile so we notice if it's in Pageant */
if (*cfg.keyfile) { if (*cfg.keyfile) {
int keytype; int keytype;
logeventf("Reading private key file \"%.150s\"", cfg.keyfile); logeventf(ssh->frontend,
"Reading private key file \"%.150s\"", cfg.keyfile);
keytype = key_type(cfg.keyfile); keytype = key_type(cfg.keyfile);
if (keytype == SSH_KEYTYPE_SSH2) { if (keytype == SSH_KEYTYPE_SSH2) {
s->publickey_blob = s->publickey_blob =
@ -4389,8 +4400,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
&s->publickey_bloblen); &s->publickey_bloblen);
} else { } else {
char msgbuf[256]; char msgbuf[256];
logeventf("Unable to use this key file (%s)", logeventf(ssh->frontend,
key_type_to_str(keytype)); "Unable to use this key file (%s)",
key_type_to_str(keytype));
sprintf(msgbuf, "Unable to use key file \"%.150s\" (%s)\r\n", sprintf(msgbuf, "Unable to use key file \"%.150s\" (%s)\r\n",
cfg.keyfile, key_type_to_str(keytype)); cfg.keyfile, key_type_to_str(keytype));
c_write_str(ssh, msgbuf); c_write_str(ssh, msgbuf);
@ -4441,7 +4453,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (!s->gotit) if (!s->gotit)
s->curr_prompt = 0; s->curr_prompt = 0;
} else if (ssh->pktin.type != SSH2_MSG_USERAUTH_FAILURE) { } else if (ssh->pktin.type != SSH2_MSG_USERAUTH_FAILURE) {
bombout(("Strange packet received during authentication: type %d", bombout((ssh,"Strange packet received during authentication: type %d",
ssh->pktin.type)); ssh->pktin.type));
crReturnV; crReturnV;
} }
@ -4830,7 +4842,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_addstring(ssh, "en"); /* language tag */ ssh2_pkt_addstring(ssh, "en"); /* language tag */
ssh2_pkt_send(ssh); ssh2_pkt_send(ssh);
logevent("Unable to authenticate"); logevent("Unable to authenticate");
connection_fatal("Unable to authenticate"); connection_fatal(ssh->frontend,
"Unable to authenticate");
ssh->state = SSH_STATE_CLOSED; ssh->state = SSH_STATE_CLOSED;
crReturnV; crReturnV;
} }
@ -5038,12 +5051,12 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_send(ssh); ssh2_pkt_send(ssh);
crWaitUntilV(ispkt); crWaitUntilV(ispkt);
if (ssh->pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
bombout(("Server refused to open a session")); bombout((ssh,"Server refused to open a session"));
crReturnV; crReturnV;
/* FIXME: error data comes back in FAILURE packet */ /* FIXME: error data comes back in FAILURE packet */
} }
if (ssh2_pkt_getuint32(ssh) != ssh->mainchan->localid) { if (ssh2_pkt_getuint32(ssh) != ssh->mainchan->localid) {
bombout(("Server's channel confirmation cited wrong channel")); bombout((ssh,"Server's channel confirmation cited wrong channel"));
crReturnV; crReturnV;
} }
ssh->mainchan->remoteid = ssh2_pkt_getuint32(ssh); ssh->mainchan->remoteid = ssh2_pkt_getuint32(ssh);
@ -5087,7 +5100,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to X11 forwarding request:" bombout((ssh,"Unexpected response to X11 forwarding request:"
" packet type %d", ssh->pktin.type)); " packet type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
@ -5215,7 +5228,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (ssh->pktin.type != SSH2_MSG_REQUEST_SUCCESS) { if (ssh->pktin.type != SSH2_MSG_REQUEST_SUCCESS) {
if (ssh->pktin.type != SSH2_MSG_REQUEST_FAILURE) { if (ssh->pktin.type != SSH2_MSG_REQUEST_FAILURE) {
bombout(("Unexpected response to port " bombout((ssh,"Unexpected response to port "
"forwarding request: packet type %d", "forwarding request: packet type %d",
ssh->pktin.type)); ssh->pktin.type));
crReturnV; crReturnV;
@ -5255,7 +5268,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to agent forwarding request:" bombout((ssh,"Unexpected response to agent forwarding request:"
" packet type %d", ssh->pktin.type)); " packet type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
@ -5298,7 +5311,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to pty request:" bombout((ssh,"Unexpected response to pty request:"
" packet type %d", ssh->pktin.type)); " packet type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
@ -5356,7 +5369,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} while (ssh->pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST); } while (ssh->pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) { if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to shell/command request:" bombout((ssh,"Unexpected response to shell/command request:"
" packet type %d", ssh->pktin.type)); " packet type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
@ -5371,7 +5384,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh->fallback_cmd = TRUE; ssh->fallback_cmd = TRUE;
continue; continue;
} }
bombout(("Server refused to start a shell/command")); bombout((ssh,"Server refused to start a shell/command"));
crReturnV; crReturnV;
} else { } else {
logevent("Started a shell/command"); logevent("Started a shell/command");
@ -5508,7 +5521,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
c = find234(ssh->channels, &i, ssh_channelfind); c = find234(ssh->channels, &i, ssh_channelfind);
if (!c || ((int)c->remoteid) == -1) { if (!c || ((int)c->remoteid) == -1) {
bombout(("Received CHANNEL_CLOSE for %s channel %d\n", bombout((ssh,"Received CHANNEL_CLOSE for %s channel %d\n",
c ? "half-open" : "nonexistent", i)); c ? "half-open" : "nonexistent", i));
} }
/* Do pre-close processing on the channel. */ /* Do pre-close processing on the channel. */
@ -5777,7 +5790,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_send(ssh); ssh2_pkt_send(ssh);
} }
} else { } else {
bombout(("Strange packet received: type %d", ssh->pktin.type)); bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));
crReturnV; crReturnV;
} }
} else { } else {
@ -5851,7 +5864,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
ssh->sccipher = NULL; ssh->sccipher = NULL;
ssh->sc_cipher_ctx = NULL; ssh->sc_cipher_ctx = NULL;
ssh->csmac = NULL; ssh->csmac = NULL;
ssh->sc_mac_ctx = NULL; ssh->cs_mac_ctx = NULL;
ssh->scmac = NULL; ssh->scmac = NULL;
ssh->sc_mac_ctx = NULL; ssh->sc_mac_ctx = NULL;
ssh->cscomp = NULL; ssh->cscomp = NULL;
@ -5865,6 +5878,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
ssh->size_needed = FALSE; ssh->size_needed = FALSE;
ssh->eof_needed = FALSE; ssh->eof_needed = FALSE;
ssh->ldisc = NULL; ssh->ldisc = NULL;
ssh->logctx = NULL;
{ {
static const struct Packet empty = { 0, 0, NULL, NULL, 0 }; static const struct Packet empty = { 0, 0, NULL, NULL, 0 };
ssh->pktin = ssh->pktout = empty; ssh->pktin = ssh->pktout = empty;
@ -6148,6 +6162,12 @@ static void ssh_provide_ldisc(void *handle, void *ldisc)
ssh->ldisc = ldisc; ssh->ldisc = ldisc;
} }
static void ssh_provide_logctx(void *handle, void *logctx)
{
Ssh ssh = (Ssh) handle;
ssh->logctx = logctx;
}
static int ssh_return_exitcode(void *handle) static int ssh_return_exitcode(void *handle)
{ {
Ssh ssh = (Ssh) handle; Ssh ssh = (Ssh) handle;
@ -6176,6 +6196,7 @@ Backend ssh_backend = {
ssh_sendok, ssh_sendok,
ssh_ldisc, ssh_ldisc,
ssh_provide_ldisc, ssh_provide_ldisc,
ssh_provide_logctx,
ssh_unthrottle, ssh_unthrottle,
22 22
}; };

2
ssh.h
View File

@ -248,7 +248,7 @@ int random_byte(void);
void random_add_noise(void *noise, int length); void random_add_noise(void *noise, int length);
void random_add_heavynoise(void *noise, int length); void random_add_heavynoise(void *noise, int length);
void logevent(char *); void logevent(void *, char *);
/* Allocate and register a new channel for port forwarding */ /* Allocate and register a new channel for port forwarding */
void *new_sock_channel(void *handle, Socket s); void *new_sock_channel(void *handle, Socket s);

View File

@ -956,6 +956,7 @@ void *zlib_decompress_init(void)
dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL; dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL;
dctx->bits = 0; dctx->bits = 0;
dctx->nbits = 0; dctx->nbits = 0;
dctx->winpos = 0;
return dctx; return dctx;
} }

View File

@ -224,14 +224,14 @@ static void c_write1(Telnet telnet, int c)
sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG); sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG);
} }
static void log_option(char *sender, int cmd, int option) static void log_option(Telnet telnet, char *sender, int cmd, int option)
{ {
char buf[50]; char buf[50];
sprintf(buf, "%s:\t%s %s", sender, sprintf(buf, "%s:\t%s %s", sender,
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" : (cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"), cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
telopt(option)); telopt(option));
logevent(buf); logevent(telnet->frontend, buf);
} }
static void send_opt(Telnet telnet, int cmd, int option) static void send_opt(Telnet telnet, int cmd, int option)
@ -242,7 +242,7 @@ static void send_opt(Telnet telnet, int cmd, int option)
b[1] = cmd; b[1] = cmd;
b[2] = option; b[2] = option;
telnet->bufsize = sk_write(telnet->s, b, 3); telnet->bufsize = sk_write(telnet->s, b, 3);
log_option("client", cmd, option); log_option(telnet, "client", cmd, option);
} }
static void deactivate_option(Telnet telnet, const struct Opt *o) static void deactivate_option(Telnet telnet, const struct Opt *o)
@ -314,7 +314,7 @@ static void proc_rec_opt(Telnet telnet, int cmd, int option)
{ {
const struct Opt *const *o; const struct Opt *const *o;
log_option("server", cmd, option); log_option(telnet, "server", cmd, option);
for (o = opts; *o; o++) { for (o = opts; *o; o++) {
if ((*o)->option == option && (*o)->ack == cmd) { if ((*o)->option == option && (*o)->ack == cmd) {
switch (telnet->opt_states[(*o)->index]) { switch (telnet->opt_states[(*o)->index]) {
@ -378,11 +378,11 @@ static void process_subneg(Telnet telnet)
b[n] = IAC; b[n] = IAC;
b[n + 1] = SE; b[n + 1] = SE;
telnet->bufsize = sk_write(telnet->s, b, n + 2); telnet->bufsize = sk_write(telnet->s, b, n + 2);
logevent("server:\tSB TSPEED SEND"); logevent(telnet->frontend, "server:\tSB TSPEED SEND");
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed); sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
logevent(logbuf); logevent(telnet->frontend, logbuf);
} else } else
logevent("server:\tSB TSPEED <something weird>"); logevent(telnet->frontend, "server:\tSB TSPEED <something weird>");
break; break;
case TELOPT_TTYPE: case TELOPT_TTYPE:
if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) {
@ -400,11 +400,11 @@ static void process_subneg(Telnet telnet)
b[n + 5] = SE; b[n + 5] = SE;
telnet->bufsize = sk_write(telnet->s, b, n + 6); telnet->bufsize = sk_write(telnet->s, b, n + 6);
b[n + 4] = 0; b[n + 4] = 0;
logevent("server:\tSB TTYPE SEND"); logevent(telnet->frontend, "server:\tSB TTYPE SEND");
sprintf(logbuf, "client:\tSB TTYPE IS %s", b + 4); sprintf(logbuf, "client:\tSB TTYPE IS %s", b + 4);
logevent(logbuf); logevent(telnet->frontend, logbuf);
} else } else
logevent("server:\tSB TTYPE <something weird>\r\n"); logevent(telnet->frontend, "server:\tSB TTYPE <something weird>\r\n");
break; break;
case TELOPT_OLD_ENVIRON: case TELOPT_OLD_ENVIRON:
case TELOPT_NEW_ENVIRON: case TELOPT_NEW_ENVIRON:
@ -414,7 +414,7 @@ static void process_subneg(Telnet telnet)
char logbuf[50]; char logbuf[50];
p++; p++;
sprintf(logbuf, "server:\tSB %s SEND", telopt(telnet->sb_opt)); sprintf(logbuf, "server:\tSB %s SEND", telopt(telnet->sb_opt));
logevent(logbuf); logevent(telnet->frontend, logbuf);
if (telnet->sb_opt == TELOPT_OLD_ENVIRON) { if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
if (cfg.rfc_environ) { if (cfg.rfc_environ) {
value = RFC_VALUE; value = RFC_VALUE;
@ -477,7 +477,7 @@ static void process_subneg(Telnet telnet)
telnet->bufsize = sk_write(telnet->s, b, n); telnet->bufsize = sk_write(telnet->s, b, n);
sprintf(logbuf, "client:\tSB %s IS %s", telopt(telnet->sb_opt), sprintf(logbuf, "client:\tSB %s IS %s", telopt(telnet->sb_opt),
n == 6 ? "<nothing>" : "<stuff>"); n == 6 ? "<nothing>" : "<stuff>");
logevent(logbuf); logevent(telnet->frontend, logbuf);
} }
break; break;
} }
@ -605,7 +605,7 @@ static int telnet_closing(Plug plug, char *error_msg, int error_code,
} }
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
logevent(error_msg); logevent(telnet->frontend, error_msg);
connection_fatal("%s", error_msg); connection_fatal("%s", error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
@ -666,7 +666,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle,
{ {
char buf[200]; char buf[200];
sprintf(buf, "Looking up host \"%.170s\"", host); sprintf(buf, "Looking up host \"%.170s\"", host);
logevent(buf); logevent(telnet->frontend, buf);
} }
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
@ -682,7 +682,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle,
char buf[200], addrbuf[100]; char buf[200], addrbuf[100];
sk_getaddr(addr, addrbuf, 100); sk_getaddr(addr, addrbuf, 100);
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(telnet->frontend, buf);
} }
telnet->s = new_connection(addr, *realhost, port, 0, 1, telnet->s = new_connection(addr, *realhost, port, 0, 1,
nodelay, (Plug) telnet); nodelay, (Plug) telnet);
@ -788,7 +788,7 @@ static void telnet_size(void *handle, int width, int height)
sprintf(logbuf, "client:\tSB NAWS %d,%d", sprintf(logbuf, "client:\tSB NAWS %d,%d",
((unsigned char) b[3] << 8) + (unsigned char) b[4], ((unsigned char) b[3] << 8) + (unsigned char) b[4],
((unsigned char) b[5] << 8) + (unsigned char) b[6]); ((unsigned char) b[5] << 8) + (unsigned char) b[6]);
logevent(logbuf); logevent(telnet->frontend, logbuf);
} }
/* /*
@ -916,6 +916,11 @@ static void telnet_provide_ldisc(void *handle, void *ldisc)
telnet->ldisc = ldisc; telnet->ldisc = ldisc;
} }
static void telnet_provide_logctx(void *handle, void *logctx)
{
/* This is a stub. */
}
static int telnet_exitcode(void *handle) static int telnet_exitcode(void *handle)
{ {
Telnet telnet = (Telnet) handle; Telnet telnet = (Telnet) handle;
@ -934,6 +939,7 @@ Backend telnet_backend = {
telnet_sendok, telnet_sendok,
telnet_ldisc, telnet_ldisc,
telnet_provide_ldisc, telnet_provide_ldisc,
telnet_provide_logctx,
telnet_unthrottle, telnet_unthrottle,
23 23
}; };

View File

@ -188,7 +188,7 @@ static void power_on(Terminal *term)
void term_update(Terminal *term) void term_update(Terminal *term)
{ {
Context ctx; Context ctx;
ctx = get_ctx(); ctx = get_ctx(term->frontend);
if (ctx) { if (ctx) {
int need_sbar_update = term->seen_disp_event; int need_sbar_update = term->seen_disp_event;
if (term->seen_disp_event && cfg.scroll_on_disp) { if (term->seen_disp_event && cfg.scroll_on_disp) {
@ -199,7 +199,7 @@ void term_update(Terminal *term)
if (need_sbar_update) if (need_sbar_update)
update_sbar(term); update_sbar(term);
do_paint(term, ctx, TRUE); do_paint(term, ctx, TRUE);
sys_cursor(term->curs.x, term->curs.y - term->disptop); sys_cursor(term->frontend, term->curs.x, term->curs.y - term->disptop);
free_ctx(ctx); free_ctx(ctx);
} }
} }
@ -261,7 +261,7 @@ void term_reconfig(Terminal *term)
swap_screen(term, 0, FALSE, FALSE); swap_screen(term, 0, FALSE, FALSE);
if (cfg.no_mouse_rep) { if (cfg.no_mouse_rep) {
term->xterm_mouse = 0; term->xterm_mouse = 0;
set_raw_mouse_mode(0); set_raw_mouse_mode(term->frontend, 0);
} }
if (cfg.no_remote_charset) { if (cfg.no_remote_charset) {
term->cset_attr[0] = term->cset_attr[1] = ATTR_ASCII; term->cset_attr[0] = term->cset_attr[1] = ATTR_ASCII;
@ -289,7 +289,7 @@ void term_clrsb(Terminal *term)
/* /*
* Initialise the terminal. * Initialise the terminal.
*/ */
Terminal *term_init(void) Terminal *term_init(void *frontend)
{ {
Terminal *term; Terminal *term;
@ -298,6 +298,8 @@ Terminal *term_init(void)
* that need it. * that need it.
*/ */
term = smalloc(sizeof(Terminal)); term = smalloc(sizeof(Terminal));
term->frontend = frontend;
term->logctx = NULL;
term->compatibility_level = TM_PUTTY; term->compatibility_level = TM_PUTTY;
strcpy(term->id_string, "\033[?6c"); strcpy(term->id_string, "\033[?6c");
term->last_blink = term->last_tblink = 0; term->last_blink = term->last_tblink = 0;
@ -558,7 +560,8 @@ static void update_sbar(Terminal *term)
nscroll = count234(term->scrollback); nscroll = count234(term->scrollback);
set_sbar(nscroll + term->rows, nscroll + term->disptop, term->rows); set_sbar(term->frontend, nscroll + term->rows,
nscroll + term->disptop, term->rows);
} }
/* /*
@ -873,7 +876,7 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
case 3: /* 80/132 columns */ case 3: /* 80/132 columns */
deselect(term); deselect(term);
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(state ? 132 : 80, term->rows); request_resize(term->frontend, state ? 132 : 80, term->rows);
term->reset_132 = state; term->reset_132 = state;
break; break;
case 5: /* reverse video */ case 5: /* reverse video */
@ -932,11 +935,11 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
break; break;
case 1000: /* xterm mouse 1 */ case 1000: /* xterm mouse 1 */
term->xterm_mouse = state ? 1 : 0; term->xterm_mouse = state ? 1 : 0;
set_raw_mouse_mode(state); set_raw_mouse_mode(term->frontend, state);
break; break;
case 1002: /* xterm mouse 2 */ case 1002: /* xterm mouse 2 */
term->xterm_mouse = state ? 2 : 0; term->xterm_mouse = state ? 2 : 0;
set_raw_mouse_mode(state); set_raw_mouse_mode(term->frontend, state);
break; break;
case 1047: /* alternate screen */ case 1047: /* alternate screen */
compatibility(OTHER); compatibility(OTHER);
@ -994,14 +997,14 @@ static void do_osc(Terminal *term)
case 0: case 0:
case 1: case 1:
if (!cfg.no_remote_wintitle) if (!cfg.no_remote_wintitle)
set_icon(term->osc_string); set_icon(term->frontend, term->osc_string);
if (term->esc_args[0] == 1) if (term->esc_args[0] == 1)
break; break;
/* fall through: parameter 0 means set both */ /* fall through: parameter 0 means set both */
case 2: case 2:
case 21: case 21:
if (!cfg.no_remote_wintitle) if (!cfg.no_remote_wintitle)
set_title(term->osc_string); set_title(term->frontend, term->osc_string);
break; break;
} }
} }
@ -1087,8 +1090,8 @@ void term_out(Terminal *term)
* Optionally log the session traffic to a file. Useful for * Optionally log the session traffic to a file. Useful for
* debugging and possibly also useful for actual logging. * debugging and possibly also useful for actual logging.
*/ */
if (cfg.logtype == LGTYP_DEBUG) if (cfg.logtype == LGTYP_DEBUG && term->logctx)
logtraffic((unsigned char) c, LGTYP_DEBUG); logtraffic(term->logctx, (unsigned char) c, LGTYP_DEBUG);
} else { } else {
c = unget; c = unget;
unget = -1; unget = -1;
@ -1374,7 +1377,7 @@ void term_out(Terminal *term)
term->vbell_startpoint = ticks; term->vbell_startpoint = ticks;
term_update(term); term_update(term);
} else } else
beep(cfg.beep); beep(term->frontend, cfg.beep);
} }
term->disptop = 0; term->disptop = 0;
} }
@ -1415,7 +1418,8 @@ void term_out(Terminal *term)
fix_cpos; fix_cpos;
term->seen_disp_event = TRUE; term->seen_disp_event = TRUE;
term->paste_hold = 0; term->paste_hold = 0;
logtraffic((unsigned char) c, LGTYP_ASCII); if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break; break;
case '\014': case '\014':
if (has_compat(SCOANSI)) { if (has_compat(SCOANSI)) {
@ -1439,7 +1443,8 @@ void term_out(Terminal *term)
term->wrapnext = FALSE; term->wrapnext = FALSE;
term->seen_disp_event = 1; term->seen_disp_event = 1;
term->paste_hold = 0; term->paste_hold = 0;
logtraffic((unsigned char) c, LGTYP_ASCII); if (term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
break; break;
case '\t': case '\t':
{ {
@ -1487,8 +1492,9 @@ void term_out(Terminal *term)
incpos(cursplus); incpos(cursplus);
check_selection(term, term->curs, cursplus); check_selection(term, term->curs, cursplus);
} }
if ((c & CSET_MASK) == ATTR_ASCII || (c & CSET_MASK) == 0) if (((c & CSET_MASK) == ATTR_ASCII || (c & CSET_MASK) == 0) &&
logtraffic((unsigned char) c, LGTYP_ASCII); term->logctx)
logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
{ {
extern int wcwidth(wchar_t ucs); extern int wcwidth(wchar_t ucs);
int width = 0; int width = 0;
@ -1632,7 +1638,7 @@ void term_out(Terminal *term)
ldisc_send(term->ldisc, NULL, 0, 0); ldisc_send(term->ldisc, NULL, 0, 0);
if (term->reset_132) { if (term->reset_132) {
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(80, term->rows); request_resize(term->frontend, 80, term->rows);
term->reset_132 = 0; term->reset_132 = 0;
} }
fix_cpos; fix_cpos;
@ -2134,7 +2140,7 @@ void term_out(Terminal *term)
term->esc_args[0] >= 24)) { term->esc_args[0] >= 24)) {
compatibility(VT340TEXT); compatibility(VT340TEXT);
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(term->cols, request_resize(term->frontend, term->cols,
def(term->esc_args[0], 24)); def(term->esc_args[0], 24));
deselect(term); deselect(term);
} else if (term->esc_nargs >= 1 && } else if (term->esc_nargs >= 1 &&
@ -2146,15 +2152,16 @@ void term_out(Terminal *term)
int x, y, len; int x, y, len;
char buf[80], *p; char buf[80], *p;
case 1: case 1:
set_iconic(FALSE); set_iconic(term->frontend, FALSE);
break; break;
case 2: case 2:
set_iconic(TRUE); set_iconic(term->frontend, TRUE);
break; break;
case 3: case 3:
if (term->esc_nargs >= 3) { if (term->esc_nargs >= 3) {
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
move_window(def(term->esc_args[1], 0), move_window(term->frontend,
def(term->esc_args[1], 0),
def(term->esc_args[2], 0)); def(term->esc_args[2], 0));
} }
break; break;
@ -2165,42 +2172,46 @@ void term_out(Terminal *term)
* manage it. */ * manage it. */
break; break;
case 5: case 5:
set_zorder(TRUE); /* move to top */ /* move to top */
set_zorder(term->frontend, TRUE);
break; break;
case 6: case 6:
set_zorder(FALSE); /* move to bottom */ /* move to bottom */
set_zorder(term->frontend, FALSE);
break; break;
case 7: case 7:
refresh_window(); refresh_window(term->frontend);
break; break;
case 8: case 8:
if (term->esc_nargs >= 3) { if (term->esc_nargs >= 3) {
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(def(term->esc_args[2], cfg.width), request_resize(term->frontend,
def(term->esc_args[2], cfg.width),
def(term->esc_args[1], cfg.height)); def(term->esc_args[1], cfg.height));
} }
break; break;
case 9: case 9:
if (term->esc_nargs >= 2) if (term->esc_nargs >= 2)
set_zoomed(term->esc_args[1] ? set_zoomed(term->frontend,
term->esc_args[1] ?
TRUE : FALSE); TRUE : FALSE);
break; break;
case 11: case 11:
if (term->ldisc) if (term->ldisc)
ldisc_send(term->ldisc, ldisc_send(term->ldisc,
is_iconic() ? "\033[1t" : is_iconic(term->frontend) ?
"\033[2t", 4, 0); "\033[1t" : "\033[2t", 4, 0);
break; break;
case 13: case 13:
if (term->ldisc) { if (term->ldisc) {
get_window_pos(&x, &y); get_window_pos(term->frontend, &x, &y);
len = sprintf(buf, "\033[3;%d;%dt", x, y); len = sprintf(buf, "\033[3;%d;%dt", x, y);
ldisc_send(term->ldisc, buf, len, 0); ldisc_send(term->ldisc, buf, len, 0);
} }
break; break;
case 14: case 14:
if (term->ldisc) { if (term->ldisc) {
get_window_pixels(&x, &y); get_window_pixels(term->frontend, &x, &y);
len = sprintf(buf, "\033[4;%d;%dt", x, y); len = sprintf(buf, "\033[4;%d;%dt", x, y);
ldisc_send(term->ldisc, buf, len, 0); ldisc_send(term->ldisc, buf, len, 0);
} }
@ -2231,7 +2242,7 @@ void term_out(Terminal *term)
break; break;
case 20: case 20:
if (term->ldisc) { if (term->ldisc) {
p = get_window_title(TRUE); p = get_window_title(term->frontend, TRUE);
len = strlen(p); len = strlen(p);
ldisc_send(term->ldisc, "\033]L", 3, 0); ldisc_send(term->ldisc, "\033]L", 3, 0);
ldisc_send(term->ldisc, p, len, 0); ldisc_send(term->ldisc, p, len, 0);
@ -2240,7 +2251,7 @@ void term_out(Terminal *term)
break; break;
case 21: case 21:
if (term->ldisc) { if (term->ldisc) {
p = get_window_title(FALSE); p = get_window_title(term->frontend,FALSE);
len = strlen(p); len = strlen(p);
ldisc_send(term->ldisc, "\033]l", 3, 0); ldisc_send(term->ldisc, "\033]l", 3, 0);
ldisc_send(term->ldisc, p, len, 0); ldisc_send(term->ldisc, p, len, 0);
@ -2275,7 +2286,7 @@ void term_out(Terminal *term)
compatibility(VT420); compatibility(VT420);
if (term->esc_nargs == 1 && term->esc_args[0] > 0) { if (term->esc_nargs == 1 && term->esc_args[0] > 0) {
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(term->cols, request_resize(term->frontend, term->cols,
def(term->esc_args[0], def(term->esc_args[0],
cfg.height)); cfg.height));
deselect(term); deselect(term);
@ -2289,7 +2300,8 @@ void term_out(Terminal *term)
compatibility(VT340TEXT); compatibility(VT340TEXT);
if (term->esc_nargs <= 1) { if (term->esc_nargs <= 1) {
if (!cfg.no_remote_resize) if (!cfg.no_remote_resize)
request_resize(def(term->esc_args[0], request_resize(term->frontend,
def(term->esc_args[0],
cfg.width), term->rows); cfg.width), term->rows);
deselect(term); deselect(term);
} }
@ -2441,7 +2453,7 @@ void term_out(Terminal *term)
term->osc_strlen = 0; term->osc_strlen = 0;
break; break;
case 'R': /* Linux palette reset */ case 'R': /* Linux palette reset */
palette_reset(); palette_reset(term->frontend);
term_invalidate(term); term_invalidate(term);
term->termstate = TOPLEVEL; term->termstate = TOPLEVEL;
break; break;
@ -2520,7 +2532,7 @@ void term_out(Terminal *term)
} }
term->osc_string[term->osc_strlen++] = val; term->osc_string[term->osc_strlen++] = val;
if (term->osc_strlen >= 7) { if (term->osc_strlen >= 7) {
palette_set(term->osc_string[0], palette_set(term->frontend, term->osc_string[0],
term->osc_string[1] * 16 + term->osc_string[2], term->osc_string[1] * 16 + term->osc_string[2],
term->osc_string[3] * 16 + term->osc_string[4], term->osc_string[3] * 16 + term->osc_string[4],
term->osc_string[5] * 16 + term->osc_string[6]); term->osc_string[5] * 16 + term->osc_string[6]);
@ -3286,7 +3298,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect)
wblen++; wblen++;
*wbptr++ = 0; *wbptr++ = 0;
#endif #endif
write_clip(workbuf, wblen, FALSE); /* transfer to clipboard */ write_clip(term->frontend, workbuf, wblen, FALSE); /* transfer to clipbd */
if (buflen > 0) /* indicates we allocated this buffer */ if (buflen > 0) /* indicates we allocated this buffer */
sfree(workbuf); sfree(workbuf);
} }
@ -3515,7 +3527,7 @@ void term_do_paste(Terminal *term)
wchar_t *data; wchar_t *data;
int len; int len;
get_clip(&data, &len); get_clip(term->frontend, &data, &len);
if (data && len > 0) { if (data && len > 0) {
wchar_t *p, *q; wchar_t *p, *q;
@ -3558,7 +3570,7 @@ void term_do_paste(Terminal *term)
term->paste_pos = term->paste_hold = term->paste_len = 0; term->paste_pos = term->paste_hold = term->paste_len = 0;
} }
} }
get_clip(NULL, NULL); get_clip(term->frontend, NULL, NULL);
} }
void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y, void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y,
@ -3651,7 +3663,7 @@ void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y,
return; return;
} }
b = translate_button(b); b = translate_button(term->frontend, b);
/* /*
* Set the selection type (rectangular or normal) at the start * Set the selection type (rectangular or normal) at the start
@ -3762,7 +3774,7 @@ void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y,
|| a == MA_2CLK || a == MA_3CLK || a == MA_2CLK || a == MA_3CLK
#endif #endif
)) { )) {
request_paste(); request_paste(term->frontend);
} }
term_update(term); term_update(term);
@ -3871,3 +3883,8 @@ int from_backend(void *vterm, int is_stderr, char *data, int len)
*/ */
return 0; return 0;
} }
void term_provide_logctx(Terminal *term, void *logctx)
{
term->logctx = logctx;
}

View File

@ -163,6 +163,10 @@ struct terminal_tag {
void *resize_ctx; void *resize_ctx;
void *ldisc; void *ldisc;
void *frontend;
void *logctx;
}; };
#define in_utf(term) ((term)->utf || line_codepage==CP_UTF8) #define in_utf(term) ((term)->utf || line_codepage==CP_UTF8)

View File

@ -57,10 +57,14 @@ struct gui_data {
Backend *back; Backend *back;
void *backhandle; void *backhandle;
Terminal *term; Terminal *term;
void *logctx;
};
struct draw_ctx {
GdkGC *gc;
struct gui_data *inst;
}; };
static struct gui_data the_inst;
static struct gui_data *inst = &the_inst; /* so we always write `inst->' */
static int send_raw_mouse; static int send_raw_mouse;
void ldisc_update(void *frontend, int echo, int edit) void ldisc_update(void *frontend, int echo, int edit)
@ -73,7 +77,7 @@ void ldisc_update(void *frontend, int echo, int edit)
*/ */
} }
int askappend(char *filename) int askappend(void *frontend, char *filename)
{ {
/* /*
* Logging in an xterm-alike is liable to be something you only * Logging in an xterm-alike is liable to be something you only
@ -84,7 +88,7 @@ int askappend(char *filename)
return 2; return 2;
} }
void logevent(char *string) void logevent(void *frontend, char *string)
{ {
/* /*
* This is not a very helpful function: events are logged * This is not a very helpful function: events are logged
@ -93,8 +97,10 @@ void logevent(char *string)
*/ */
} }
int font_dimension(int which) /* 0 for width, 1 for height */ int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */
{ {
struct gui_data *inst = (struct gui_data *)frontend;
if (which) if (which)
return inst->font_height; return inst->font_height;
else else
@ -110,8 +116,10 @@ int font_dimension(int which) /* 0 for width, 1 for height */
* mouse or a means of faking it, and there is no need to switch * mouse or a means of faking it, and there is no need to switch
* buttons around at all. * buttons around at all.
*/ */
Mouse_Button translate_button(Mouse_Button button) Mouse_Button translate_button(void *frontend, Mouse_Button button)
{ {
/* struct gui_data *inst = (struct gui_data *)frontend; */
if (button == MBT_LEFT) if (button == MBT_LEFT)
return MBT_SELECT; return MBT_SELECT;
if (button == MBT_MIDDLE) if (button == MBT_MIDDLE)
@ -125,12 +133,13 @@ Mouse_Button translate_button(Mouse_Button button)
* Minimise or restore the window in response to a server-side * Minimise or restore the window in response to a server-side
* request. * request.
*/ */
void set_iconic(int iconic) void set_iconic(void *frontend, int iconic)
{ {
/* /*
* GTK 1.2 doesn't know how to do this. * GTK 1.2 doesn't know how to do this.
*/ */
#if GTK_CHECK_VERSION(2,0,0) #if GTK_CHECK_VERSION(2,0,0)
struct gui_data *inst = (struct gui_data *)frontend;
if (iconic) if (iconic)
gtk_window_iconify(GTK_WINDOW(inst->window)); gtk_window_iconify(GTK_WINDOW(inst->window));
else else
@ -141,8 +150,9 @@ void set_iconic(int iconic)
/* /*
* Move the window in response to a server-side request. * Move the window in response to a server-side request.
*/ */
void move_window(int x, int y) void move_window(void *frontend, int x, int y)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
/* /*
* I assume that when the GTK version of this call is available * I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one, * we should use it. Not sure how it differs from the GDK one,
@ -159,8 +169,9 @@ void move_window(int x, int y)
* Move the window to the top or bottom of the z-order in response * Move the window to the top or bottom of the z-order in response
* to a server-side request. * to a server-side request.
*/ */
void set_zorder(int top) void set_zorder(void *frontend, int top)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
if (top) if (top)
gdk_window_raise(inst->window->window); gdk_window_raise(inst->window->window);
else else
@ -170,8 +181,9 @@ void set_zorder(int top)
/* /*
* Refresh the window in response to a server-side request. * Refresh the window in response to a server-side request.
*/ */
void refresh_window(void) void refresh_window(void *frontend)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
term_invalidate(inst->term); term_invalidate(inst->term);
} }
@ -179,12 +191,13 @@ void refresh_window(void)
* Maximise or restore the window in response to a server-side * Maximise or restore the window in response to a server-side
* request. * request.
*/ */
void set_zoomed(int zoomed) void set_zoomed(void *frontend, int zoomed)
{ {
/* /*
* GTK 1.2 doesn't know how to do this. * GTK 1.2 doesn't know how to do this.
*/ */
#if GTK_CHECK_VERSION(2,0,0) #if GTK_CHECK_VERSION(2,0,0)
struct gui_data *inst = (struct gui_data *)frontend;
if (iconic) if (iconic)
gtk_window_maximize(GTK_WINDOW(inst->window)); gtk_window_maximize(GTK_WINDOW(inst->window));
else else
@ -195,16 +208,18 @@ void set_zoomed(int zoomed)
/* /*
* Report whether the window is iconic, for terminal reports. * Report whether the window is iconic, for terminal reports.
*/ */
int is_iconic(void) int is_iconic(void *frontend)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
return !gdk_window_is_viewable(inst->window->window); return !gdk_window_is_viewable(inst->window->window);
} }
/* /*
* Report the window's position, for terminal reports. * Report the window's position, for terminal reports.
*/ */
void get_window_pos(int *x, int *y) void get_window_pos(void *frontend, int *x, int *y)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
/* /*
* I assume that when the GTK version of this call is available * I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one, * we should use it. Not sure how it differs from the GDK one,
@ -220,8 +235,9 @@ void get_window_pos(int *x, int *y)
/* /*
* Report the window's pixel size, for terminal reports. * Report the window's pixel size, for terminal reports.
*/ */
void get_window_pixels(int *x, int *y) void get_window_pixels(void *frontend, int *x, int *y)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
/* /*
* I assume that when the GTK version of this call is available * I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one, * we should use it. Not sure how it differs from the GDK one,
@ -237,8 +253,9 @@ void get_window_pixels(int *x, int *y)
/* /*
* Return the window or icon title. * Return the window or icon title.
*/ */
char *get_window_title(int icon) char *get_window_title(void *frontend, int icon)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
return icon ? inst->wintitle : inst->icontitle; return icon ? inst->wintitle : inst->icontitle;
} }
@ -251,7 +268,7 @@ gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
return FALSE; return FALSE;
} }
void show_mouseptr(int show) static void show_mouseptr(struct gui_data *inst, int show)
{ {
if (!cfg.hide_mouseptr) if (!cfg.hide_mouseptr)
show = 1; show = 1;
@ -305,7 +322,7 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data) gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{ {
/* struct gui_data *inst = (struct gui_data *)data; */ struct gui_data *inst = (struct gui_data *)data;
/* /*
* Pass the exposed rectangle to terminal.c, which will call us * Pass the exposed rectangle to terminal.c, which will call us
@ -327,7 +344,7 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{ {
/* struct gui_data *inst = (struct gui_data *)data; */ struct gui_data *inst = (struct gui_data *)data;
char output[32]; char output[32];
int start, end; int start, end;
@ -433,7 +450,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
* Neither does Shift-Ins. * Neither does Shift-Ins.
*/ */
if (event->keyval == GDK_Insert && (event->state & GDK_SHIFT_MASK)) { if (event->keyval == GDK_Insert && (event->state & GDK_SHIFT_MASK)) {
request_paste(); request_paste(inst);
return TRUE; return TRUE;
} }
@ -797,7 +814,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
#endif #endif
ldisc_send(inst->ldisc, output+start, end-start, 1); ldisc_send(inst->ldisc, output+start, end-start, 1);
show_mouseptr(0); show_mouseptr(inst, 0);
term_seen_key_event(inst->term); term_seen_key_event(inst->term);
term_out(inst->term); term_out(inst->term);
} }
@ -810,7 +827,7 @@ gint button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
struct gui_data *inst = (struct gui_data *)data; struct gui_data *inst = (struct gui_data *)data;
int shift, ctrl, alt, x, y, button, act; int shift, ctrl, alt, x, y, button, act;
show_mouseptr(1); show_mouseptr(inst, 1);
if (event->button == 4 && event->type == GDK_BUTTON_PRESS) { if (event->button == 4 && event->type == GDK_BUTTON_PRESS) {
term_scroll(inst->term, 0, -5); term_scroll(inst->term, 0, -5);
@ -858,7 +875,7 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
struct gui_data *inst = (struct gui_data *)data; struct gui_data *inst = (struct gui_data *)data;
int shift, ctrl, alt, x, y, button; int shift, ctrl, alt, x, y, button;
show_mouseptr(1); show_mouseptr(inst, 1);
shift = event->state & GDK_SHIFT_MASK; shift = event->state & GDK_SHIFT_MASK;
ctrl = event->state & GDK_CONTROL_MASK; ctrl = event->state & GDK_CONTROL_MASK;
@ -993,29 +1010,32 @@ void destroy(GtkWidget *widget, gpointer data)
gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data;
inst->term->has_focus = event->in; inst->term->has_focus = event->in;
term_out(inst->term); term_out(inst->term);
term_update(inst->term); term_update(inst->term);
show_mouseptr(1); show_mouseptr(inst, 1);
return FALSE; return FALSE;
} }
/* /*
* set or clear the "raw mouse message" mode * set or clear the "raw mouse message" mode
*/ */
void set_raw_mouse_mode(int activate) void set_raw_mouse_mode(void *frontend, int activate)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
activate = activate && !cfg.no_mouse_rep; activate = activate && !cfg.no_mouse_rep;
send_raw_mouse = activate; send_raw_mouse = activate;
if (send_raw_mouse) if (send_raw_mouse)
inst->currcursor = inst->rawcursor; inst->currcursor = inst->rawcursor;
else else
inst->currcursor = inst->textcursor; inst->currcursor = inst->textcursor;
show_mouseptr(inst->mouseptr_visible); show_mouseptr(inst, inst->mouseptr_visible);
} }
void request_resize(int w, int h) void request_resize(void *frontend, int w, int h)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
int large_x, large_y; int large_x, large_y;
int offset_x, offset_y; int offset_x, offset_y;
int area_x, area_y; int area_x, area_y;
@ -1041,7 +1061,7 @@ void request_resize(int w, int h)
* bogus size request which guarantees to be bigger than the * bogus size request which guarantees to be bigger than the
* current size of the drawing area. * current size of the drawing area.
*/ */
get_window_pixels(&large_x, &large_y); get_window_pixels(inst, &large_x, &large_y);
large_x += 32; large_x += 32;
large_y += 32; large_y += 32;
@ -1080,7 +1100,7 @@ void request_resize(int w, int h)
#endif #endif
} }
void real_palette_set(int n, int r, int g, int b) static void real_palette_set(struct gui_data *inst, int n, int r, int g, int b)
{ {
gboolean success[1]; gboolean success[1];
@ -1095,7 +1115,7 @@ void real_palette_set(int n, int r, int g, int b)
n, r, g, b); n, r, g, b);
} }
void set_window_background(void) void set_window_background(struct gui_data *inst)
{ {
if (inst->area && inst->area->window) if (inst->area && inst->area->window)
gdk_window_set_background(inst->area->window, &inst->cols[18]); gdk_window_set_background(inst->area->window, &inst->cols[18]);
@ -1103,22 +1123,24 @@ void set_window_background(void)
gdk_window_set_background(inst->window->window, &inst->cols[18]); gdk_window_set_background(inst->window->window, &inst->cols[18]);
} }
void palette_set(int n, int r, int g, int b) void palette_set(void *frontend, int n, int r, int g, int b)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
static const int first[21] = { static const int first[21] = {
0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14,
1, 3, 5, 7, 9, 11, 13, 15, 1, 3, 5, 7, 9, 11, 13, 15,
16, 17, 18, 20, 22 16, 17, 18, 20, 22
}; };
real_palette_set(first[n], r, g, b); real_palette_set(inst, first[n], r, g, b);
if (first[n] >= 18) if (first[n] >= 18)
real_palette_set(first[n] + 1, r, g, b); real_palette_set(inst, first[n] + 1, r, g, b);
if (first[n] == 18) if (first[n] == 18)
set_window_background(); set_window_background(inst);
} }
void palette_reset(void) void palette_reset(void *frontend)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
/* This maps colour indices in cfg to those used in inst->cols. */ /* This maps colour indices in cfg to those used in inst->cols. */
static const int ww[] = { static const int ww[] = {
6, 7, 8, 9, 10, 11, 12, 13, 6, 7, 8, 9, 10, 11, 12, 13,
@ -1150,11 +1172,12 @@ void palette_reset(void)
i, cfg.colours[i][0], cfg.colours[i][1], cfg.colours[i][2]); i, cfg.colours[i][0], cfg.colours[i][1], cfg.colours[i][2]);
} }
set_window_background(); set_window_background(inst);
} }
void write_clip(wchar_t * data, int len, int must_deselect) void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
if (inst->pasteout_data) if (inst->pasteout_data)
sfree(inst->pasteout_data); sfree(inst->pasteout_data);
inst->pasteout_data = smalloc(len); inst->pasteout_data = smalloc(len);
@ -1174,6 +1197,7 @@ void write_clip(wchar_t * data, int len, int must_deselect)
void selection_get(GtkWidget *widget, GtkSelectionData *seldata, void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
guint info, guint time_stamp, gpointer data) guint info, guint time_stamp, gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data;
gtk_selection_data_set(seldata, GDK_SELECTION_TYPE_STRING, 8, gtk_selection_data_set(seldata, GDK_SELECTION_TYPE_STRING, 8,
inst->pasteout_data, inst->pasteout_data_len); inst->pasteout_data, inst->pasteout_data_len);
} }
@ -1181,6 +1205,7 @@ void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata, gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
gpointer data) gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data;
term_deselect(inst->term); term_deselect(inst->term);
if (inst->pasteout_data) if (inst->pasteout_data)
sfree(inst->pasteout_data); sfree(inst->pasteout_data);
@ -1189,8 +1214,9 @@ gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
return TRUE; return TRUE;
} }
void request_paste(void) void request_paste(void *frontend)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
/* /*
* In Unix, pasting is asynchronous: all we can do at the * In Unix, pasting is asynchronous: all we can do at the
* moment is to call gtk_selection_convert(), and when the data * moment is to call gtk_selection_convert(), and when the data
@ -1205,6 +1231,8 @@ gint idle_paste_func(gpointer data); /* forward ref */
void selection_received(GtkWidget *widget, GtkSelectionData *seldata, void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
gpointer data) gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data;
if (seldata->length <= 0 || if (seldata->length <= 0 ||
seldata->type != GDK_SELECTION_TYPE_STRING) seldata->type != GDK_SELECTION_TYPE_STRING)
return; /* Nothing happens. */ return; /* Nothing happens. */
@ -1236,30 +1264,35 @@ gint idle_paste_func(gpointer data)
} }
void get_clip(wchar_t ** p, int *len) void get_clip(void *frontend, wchar_t ** p, int *len)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
if (p) { if (p) {
*p = inst->pastein_data; *p = inst->pastein_data;
*len = inst->pastein_data_len; *len = inst->pastein_data_len;
} }
} }
void set_title(char *title) void set_title(void *frontend, char *title)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
strncpy(inst->wintitle, title, lenof(inst->wintitle)); strncpy(inst->wintitle, title, lenof(inst->wintitle));
inst->wintitle[lenof(inst->wintitle)-1] = '\0'; inst->wintitle[lenof(inst->wintitle)-1] = '\0';
gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle); gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
} }
void set_icon(char *title) void set_icon(void *frontend, char *title)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
strncpy(inst->icontitle, title, lenof(inst->icontitle)); strncpy(inst->icontitle, title, lenof(inst->icontitle));
inst->icontitle[lenof(inst->icontitle)-1] = '\0'; inst->icontitle[lenof(inst->icontitle)-1] = '\0';
gdk_window_set_icon_name(inst->window->window, inst->icontitle); gdk_window_set_icon_name(inst->window->window, inst->icontitle);
} }
void set_sbar(int total, int start, int page) void set_sbar(void *frontend, int total, int start, int page)
{ {
struct gui_data *inst = (struct gui_data *)frontend;
if (!cfg.scrollbar) if (!cfg.scrollbar)
return; return;
inst->sbar_adjust->lower = 0; inst->sbar_adjust->lower = 0;
@ -1275,20 +1308,22 @@ void set_sbar(int total, int start, int page)
void scrollbar_moved(GtkAdjustment *adj, gpointer data) void scrollbar_moved(GtkAdjustment *adj, gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data;
if (!cfg.scrollbar) if (!cfg.scrollbar)
return; return;
if (!inst->ignore_sbar) if (!inst->ignore_sbar)
term_scroll(inst->term, 1, (int)adj->value); term_scroll(inst->term, 1, (int)adj->value);
} }
void sys_cursor(int x, int y) void sys_cursor(void *frontend, int x, int y)
{ {
/* /*
* This is meaningless under X. * This is meaningless under X.
*/ */
} }
void beep(int mode) void beep(void *frontend, int mode)
{ {
gdk_beep(); gdk_beep();
} }
@ -1303,19 +1338,27 @@ int CharWidth(Context ctx, int uc)
return 1; return 1;
} }
Context get_ctx(void) Context get_ctx(void *frontend)
{ {
GdkGC *gc; struct gui_data *inst = (struct gui_data *)frontend;
struct draw_ctx *dctx;
if (!inst->area->window) if (!inst->area->window)
return NULL; return NULL;
gc = gdk_gc_new(inst->area->window);
return gc; dctx = smalloc(sizeof(*dctx));
dctx->inst = inst;
dctx->gc = gdk_gc_new(inst->area->window);
return dctx;
} }
void free_ctx(Context ctx) void free_ctx(Context ctx)
{ {
GdkGC *gc = (GdkGC *)ctx; struct draw_ctx *dctx = (struct draw_ctx *)ctx;
/* struct gui_data *inst = dctx->inst; */
GdkGC *gc = dctx->gc;
gdk_gc_unref(gc); gdk_gc_unref(gc);
sfree(dctx);
} }
/* /*
@ -1327,8 +1370,11 @@ void free_ctx(Context ctx)
void do_text_internal(Context ctx, int x, int y, char *text, int len, void do_text_internal(Context ctx, int x, int y, char *text, int len,
unsigned long attr, int lattr) unsigned long attr, int lattr)
{ {
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
GdkGC *gc = dctx->gc;
int nfg, nbg, t, fontid, shadow; int nfg, nbg, t, fontid, shadow;
GdkGC *gc = (GdkGC *)ctx;
/* /*
* NYI: * NYI:
@ -1437,7 +1483,9 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
void do_text(Context ctx, int x, int y, char *text, int len, void do_text(Context ctx, int x, int y, char *text, int len,
unsigned long attr, int lattr) unsigned long attr, int lattr)
{ {
GdkGC *gc = (GdkGC *)ctx; struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
GdkGC *gc = dctx->gc;
do_text_internal(ctx, x, y, text, len, attr, lattr); do_text_internal(ctx, x, y, text, len, attr, lattr);
@ -1461,8 +1509,11 @@ void do_text(Context ctx, int x, int y, char *text, int len,
void do_cursor(Context ctx, int x, int y, char *text, int len, void do_cursor(Context ctx, int x, int y, char *text, int len,
unsigned long attr, int lattr) unsigned long attr, int lattr)
{ {
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
GdkGC *gc = dctx->gc;
int passive; int passive;
GdkGC *gc = (GdkGC *)ctx;
if (attr & TATTR_PASCURS) { if (attr & TATTR_PASCURS) {
attr &= ~TATTR_PASCURS; attr &= ~TATTR_PASCURS;
@ -1551,7 +1602,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
len*inst->font_width, inst->font_height); len*inst->font_width, inst->font_height);
} }
GdkCursor *make_mouse_ptr(int cursor_val) GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
{ {
/* /*
* Truly hideous hack: GTK doesn't allow us to set the mouse * Truly hideous hack: GTK doesn't allow us to set the mouse
@ -1654,7 +1705,7 @@ void modalfatalbox(char *p, ...)
exit(1); exit(1);
} }
char *get_x_display(void) char *get_x_display(void *frontend)
{ {
return gdk_get_display(); return gdk_get_display();
} }
@ -1827,6 +1878,7 @@ int main(int argc, char **argv)
{ {
extern int pty_master_fd; /* declared in pty.c */ extern int pty_master_fd; /* declared in pty.c */
extern void pty_pre_init(void); /* declared in pty.c */ extern void pty_pre_init(void); /* declared in pty.c */
struct gui_data *inst;
pty_pre_init(); pty_pre_init();
@ -1839,8 +1891,9 @@ int main(int argc, char **argv)
exit(1); exit(1);
/* /*
* Initialise the whole instance structure to zeroes * Create an instance structure and initialise to zeroes
*/ */
inst = smalloc(sizeof(*inst));
memset(inst, 0, sizeof(*inst)); memset(inst, 0, sizeof(*inst));
inst->fonts[0] = gdk_font_load(cfg.font); inst->fonts[0] = gdk_font_load(cfg.font);
@ -1868,14 +1921,14 @@ int main(int argc, char **argv)
inst->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); inst->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
if (cfg.wintitle[0]) if (cfg.wintitle[0])
set_title(cfg.wintitle); set_title(inst, cfg.wintitle);
else else
set_title("pterm"); set_title(inst, "pterm");
/* /*
* Set up the colour map. * Set up the colour map.
*/ */
palette_reset(); palette_reset(inst);
inst->area = gtk_drawing_area_new(); inst->area = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area),
@ -1954,19 +2007,22 @@ int main(int argc, char **argv)
gtk_widget_show(GTK_WIDGET(inst->hbox)); gtk_widget_show(GTK_WIDGET(inst->hbox));
gtk_widget_show(inst->window); gtk_widget_show(inst->window);
set_window_background(); set_window_background(inst);
inst->textcursor = make_mouse_ptr(GDK_XTERM); inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
inst->rawcursor = make_mouse_ptr(GDK_LEFT_PTR); inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
inst->blankcursor = make_mouse_ptr(-1); inst->blankcursor = make_mouse_ptr(inst, -1);
make_mouse_ptr(-2); /* clean up cursor font */ make_mouse_ptr(inst, -2); /* clean up cursor font */
inst->currcursor = inst->textcursor; inst->currcursor = inst->textcursor;
show_mouseptr(1); show_mouseptr(inst, 1);
inst->term = term_init(); inst->term = term_init(inst);
inst->logctx = log_init(inst);
term_provide_logctx(inst->term, inst->logctx);
inst->back = &pty_backend; inst->back = &pty_backend;
inst->back->init((void *)inst->term, &inst->backhandle, NULL, 0, NULL, 0); inst->back->init((void *)inst->term, &inst->backhandle, NULL, 0, NULL, 0);
inst->back->provide_logctx(inst->backhandle, inst->logctx);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle); term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);

View File

@ -68,6 +68,7 @@
#endif #endif
int pty_master_fd; int pty_master_fd;
static void *pty_frontend;
static char pty_name[FILENAME_MAX]; static char pty_name[FILENAME_MAX];
static int pty_stamped_utmp = 0; static int pty_stamped_utmp = 0;
static int pty_child_pid; static int pty_child_pid;
@ -388,6 +389,7 @@ static char *pty_init(void *frontend, void **backend_handle,
int slavefd; int slavefd;
pid_t pid, pgrp; pid_t pid, pgrp;
pty_frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */ *backend_handle = NULL; /* we can't sensibly use this, sadly */
pty_term_width = cfg.width; pty_term_width = cfg.width;
@ -414,7 +416,7 @@ static char *pty_init(void *frontend, void **backend_handle,
if (!cfg.stamp_utmp) if (!cfg.stamp_utmp)
close(pty_utmp_helper_pipe); /* just let the child process die */ close(pty_utmp_helper_pipe); /* just let the child process die */
else { else {
char *location = get_x_display(); char *location = get_x_display(pty_frontend);
int len = strlen(location)+1, pos = 0; /* +1 to include NUL */ int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
while (pos < len) { while (pos < len) {
int ret = write(pty_utmp_helper_pipe, location+pos, len - pos); int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
@ -554,8 +556,10 @@ static void pty_size(void *handle, int width, int height)
size.ws_row = (unsigned short)pty_term_height; size.ws_row = (unsigned short)pty_term_height;
size.ws_col = (unsigned short)pty_term_width; size.ws_col = (unsigned short)pty_term_width;
size.ws_xpixel = (unsigned short) pty_term_width * font_dimension(0); size.ws_xpixel = (unsigned short) pty_term_width *
size.ws_ypixel = (unsigned short) pty_term_height * font_dimension(1); font_dimension(pty_frontend, 0);
size.ws_ypixel = (unsigned short) pty_term_height *
font_dimension(pty_frontend, 1);
ioctl(pty_master_fd, TIOCSWINSZ, (void *)&size); ioctl(pty_master_fd, TIOCSWINSZ, (void *)&size);
return; return;
} }
@ -594,6 +598,11 @@ static void pty_provide_ldisc(void *handle, void *ldisc)
/* This is a stub. */ /* This is a stub. */
} }
static void pty_provide_logctx(void *handle, void *logctx)
{
/* This is a stub. */
}
static int pty_exitcode(void *handle) static int pty_exitcode(void *handle)
{ {
if (!pty_child_dead) if (!pty_child_dead)
@ -613,6 +622,7 @@ Backend pty_backend = {
pty_sendok, pty_sendok,
pty_ldisc, pty_ldisc,
pty_provide_ldisc, pty_provide_ldisc,
pty_provide_logctx,
pty_unthrottle, pty_unthrottle,
1 1
}; };

View File

@ -31,8 +31,8 @@ unsigned long getticks(void); /* based on gettimeofday(2) */
#define BYTE unsigned char #define BYTE unsigned char
/* Things pty.c needs from pterm.c */ /* Things pty.c needs from pterm.c */
char *get_x_display(void); char *get_x_display(void *frontend);
int font_dimension(int which); /* 0 for width, 1 for height */ int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */
/* Things uxstore.c needs from pterm.c */ /* Things uxstore.c needs from pterm.c */
char *app_name; /* for doing resource lookups */ char *app_name; /* for doing resource lookups */

View File

@ -140,7 +140,7 @@ static int CALLBACK LogProc(HWND hwnd, UINT msg,
memcpy(p, sel_nl, sizeof(sel_nl)); memcpy(p, sel_nl, sizeof(sel_nl));
p += sizeof(sel_nl); p += sizeof(sel_nl);
} }
write_aclip(clipdata, size, TRUE); write_aclip(NULL, clipdata, size, TRUE);
sfree(clipdata); sfree(clipdata);
} }
sfree(selitems); sfree(selitems);
@ -3749,12 +3749,12 @@ int do_reconfig(HWND hwnd)
return ret; return ret;
} }
void logevent(char *string) void logevent(void *frontend, char *string)
{ {
char timebuf[40]; char timebuf[40];
time_t t; time_t t;
log_eventlog(string); log_eventlog(logctx, string);
if (nevents >= negsize) { if (nevents >= negsize) {
negsize += 64; negsize += 64;
@ -3793,7 +3793,7 @@ void showabout(HWND hwnd)
DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc); DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
} }
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
char *keystr, char *fingerprint) char *keystr, char *fingerprint)
{ {
int ret; int ret;
@ -3869,7 +3869,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
* below the configured 'warn' threshold). * below the configured 'warn' threshold).
* cs: 0 = both ways, 1 = client->server, 2 = server->client * cs: 0 = both ways, 1 = client->server, 2 = server->client
*/ */
void askcipher(char *ciphername, int cs) void askcipher(void *frontend, char *ciphername, int cs)
{ {
static const char mbtitle[] = "PuTTY Security Alert"; static const char mbtitle[] = "PuTTY Security Alert";
static const char msg[] = static const char msg[] =
@ -3898,7 +3898,7 @@ void askcipher(char *ciphername, int cs)
* Ask whether to wipe a session log file before writing to it. * Ask whether to wipe a session log file before writing to it.
* Returns 2 for wipe, 1 for append, 0 for cancel (don't log). * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
*/ */
int askappend(char *filename) int askappend(void *frontend, char *filename)
{ {
static const char mbtitle[] = "PuTTY Log to File"; static const char mbtitle[] = "PuTTY Log to File";
static const char msgtemplate[] = static const char msgtemplate[] =
@ -3927,6 +3927,13 @@ int askappend(char *filename)
/* /*
* Warn about the obsolescent key file format. * Warn about the obsolescent key file format.
*
* Uniquely among these functions, this one does _not_ expect a
* frontend handle. This means that if PuTTY is ported to a
* platform which requires frontend handles, this function will be
* an anomaly. Fortunately, the problem it addresses will not have
* been present on that platform, so it can plausibly be
* implemented as an empty function.
*/ */
void old_keyfile_warning(void) void old_keyfile_warning(void)
{ {

View File

@ -118,7 +118,6 @@ static int caret_x = -1, caret_y = -1;
static void *ldisc; static void *ldisc;
static Backend *back; static Backend *back;
static void *backhandle; static void *backhandle;
static Terminal *term;
#define FONT_NORMAL 0 #define FONT_NORMAL 0
#define FONT_BOLD 1 #define FONT_BOLD 1
@ -499,7 +498,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
hwnd = NULL; hwnd = NULL;
term = term_init(); term = term_init(NULL);
logctx = log_init(NULL);
term_provide_logctx(term, logctx);
cfgtopalette(); cfgtopalette();
@ -608,6 +609,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
error = back->init((void *)term, &backhandle, error = back->init((void *)term, &backhandle,
cfg.host, cfg.port, &realhost, cfg.tcp_nodelay); cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
back->provide_logctx(backhandle, logctx);
if (error) { if (error) {
sprintf(msg, "Unable to open connection to\n" sprintf(msg, "Unable to open connection to\n"
"%.800s\n" "%s", cfg.host, error); "%.800s\n" "%s", cfg.host, error);
@ -622,8 +624,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
title = msg; title = msg;
} }
sfree(realhost); sfree(realhost);
set_title(title); set_title(NULL, title);
set_icon(title); set_icon(NULL, title);
} }
/* /*
@ -708,7 +710,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
/* /*
* Open the initial log file if there is one. * Open the initial log file if there is one.
*/ */
logfopen(); logfopen(logctx);
/* /*
* Finally show the window! * Finally show the window!
@ -866,7 +868,7 @@ char *do_select(SOCKET skt, int startup)
/* /*
* set or clear the "raw mouse message" mode * set or clear the "raw mouse message" mode
*/ */
void set_raw_mouse_mode(int activate) void set_raw_mouse_mode(void *frontend, int activate)
{ {
activate = activate && !cfg.no_mouse_rep; activate = activate && !cfg.no_mouse_rep;
send_raw_mouse = activate; send_raw_mouse = activate;
@ -876,7 +878,7 @@ void set_raw_mouse_mode(int activate)
/* /*
* Print a message box and close the connection. * Print a message box and close the connection.
*/ */
void connection_fatal(char *fmt, ...) void connection_fatal(void *frontend, char *fmt, ...)
{ {
va_list ap; va_list ap;
char stuff[200]; char stuff[200];
@ -1257,7 +1259,7 @@ static void deinit_fonts(void)
} }
} }
void request_resize(int w, int h) void request_resize(void *frontend, int w, int h)
{ {
int width, height; int width, height;
@ -1554,7 +1556,7 @@ static void click(Mouse_Button b, int x, int y, int shift, int ctrl, int alt)
* Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT) * Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
* into a cooked one (SELECT, EXTEND, PASTE). * into a cooked one (SELECT, EXTEND, PASTE).
*/ */
Mouse_Button translate_button(Mouse_Button button) Mouse_Button translate_button(void *frontend, Mouse_Button button)
{ {
if (button == MBT_LEFT) if (button == MBT_LEFT)
return MBT_SELECT; return MBT_SELECT;
@ -1750,8 +1752,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
if (strcmp(prev_cfg.logfilename, cfg.logfilename) || if (strcmp(prev_cfg.logfilename, cfg.logfilename) ||
prev_cfg.logtype != cfg.logtype) { prev_cfg.logtype != cfg.logtype) {
logfclose(); /* reset logging */ logfclose(logctx); /* reset logging */
logfopen(); logfopen(logctx);
} }
sfree(logpal); sfree(logpal);
@ -1841,7 +1843,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
init_lvl = 2; init_lvl = 2;
} }
set_title(cfg.wintitle); set_title(NULL, cfg.wintitle);
if (IsIconic(hwnd)) { if (IsIconic(hwnd)) {
SetWindowText(hwnd, SetWindowText(hwnd,
cfg.win_name_always ? window_name : cfg.win_name_always ? window_name :
@ -2391,7 +2393,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
break; break;
case WM_PALETTECHANGED: case WM_PALETTECHANGED:
if ((HWND) wParam != hwnd && pal != NULL) { if ((HWND) wParam != hwnd && pal != NULL) {
HDC hdc = get_ctx(); HDC hdc = get_ctx(NULL);
if (hdc) { if (hdc) {
if (RealizePalette(hdc) > 0) if (RealizePalette(hdc) > 0)
UpdateColors(hdc); UpdateColors(hdc);
@ -2401,7 +2403,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
break; break;
case WM_QUERYNEWPALETTE: case WM_QUERYNEWPALETTE:
if (pal != NULL) { if (pal != NULL) {
HDC hdc = get_ctx(); HDC hdc = get_ctx(NULL);
if (hdc) { if (hdc) {
if (RealizePalette(hdc) > 0) if (RealizePalette(hdc) > 0)
UpdateColors(hdc); UpdateColors(hdc);
@ -2612,7 +2614,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
* helper software tracks the system caret, so we should arrange to * helper software tracks the system caret, so we should arrange to
* have one.) * have one.)
*/ */
void sys_cursor(int x, int y) void sys_cursor(void *frontend, int x, int y)
{ {
int cx, cy; int cx, cy;
@ -3866,7 +3868,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
return -1; return -1;
} }
void request_paste(void) void request_paste(void *frontend)
{ {
/* /*
* In Windows, pasting is synchronous: we can read the * In Windows, pasting is synchronous: we can read the
@ -3876,7 +3878,7 @@ void request_paste(void)
term_do_paste(term); term_do_paste(term);
} }
void set_title(char *title) void set_title(void *frontend, char *title)
{ {
sfree(window_name); sfree(window_name);
window_name = smalloc(1 + strlen(title)); window_name = smalloc(1 + strlen(title));
@ -3885,7 +3887,7 @@ void set_title(char *title)
SetWindowText(hwnd, title); SetWindowText(hwnd, title);
} }
void set_icon(char *title) void set_icon(void *frontend, char *title)
{ {
sfree(icon_name); sfree(icon_name);
icon_name = smalloc(1 + strlen(title)); icon_name = smalloc(1 + strlen(title));
@ -3894,7 +3896,7 @@ void set_icon(char *title)
SetWindowText(hwnd, title); SetWindowText(hwnd, title);
} }
void set_sbar(int total, int start, int page) void set_sbar(void *frontend, int total, int start, int page)
{ {
SCROLLINFO si; SCROLLINFO si;
@ -3911,7 +3913,7 @@ void set_sbar(int total, int start, int page)
SetScrollInfo(hwnd, SB_VERT, &si, TRUE); SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
} }
Context get_ctx(void) Context get_ctx(void *frontend)
{ {
HDC hdc; HDC hdc;
if (hwnd) { if (hwnd) {
@ -3942,7 +3944,7 @@ static void real_palette_set(int n, int r, int g, int b)
colours[n] = RGB(r, g, b); colours[n] = RGB(r, g, b);
} }
void palette_set(int n, int r, int g, int b) void palette_set(void *frontend, int n, int r, int g, int b)
{ {
static const int first[21] = { static const int first[21] = {
0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14,
@ -3953,14 +3955,14 @@ void palette_set(int n, int r, int g, int b)
if (first[n] >= 18) if (first[n] >= 18)
real_palette_set(first[n] + 1, r, g, b); real_palette_set(first[n] + 1, r, g, b);
if (pal) { if (pal) {
HDC hdc = get_ctx(); HDC hdc = get_ctx(frontend);
UnrealizeObject(pal); UnrealizeObject(pal);
RealizePalette(hdc); RealizePalette(hdc);
free_ctx(hdc); free_ctx(hdc);
} }
} }
void palette_reset(void) void palette_reset(void *frontend)
{ {
int i; int i;
@ -3981,13 +3983,13 @@ void palette_reset(void)
if (pal) { if (pal) {
HDC hdc; HDC hdc;
SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry); SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry);
hdc = get_ctx(); hdc = get_ctx(frontend);
RealizePalette(hdc); RealizePalette(hdc);
free_ctx(hdc); free_ctx(hdc);
} }
} }
void write_aclip(char *data, int len, int must_deselect) void write_aclip(void *frontend, char *data, int len, int must_deselect)
{ {
HGLOBAL clipdata; HGLOBAL clipdata;
void *lock; void *lock;
@ -4019,7 +4021,7 @@ void write_aclip(char *data, int len, int must_deselect)
/* /*
* Note: unlike write_aclip() this will not append a nul. * Note: unlike write_aclip() this will not append a nul.
*/ */
void write_clip(wchar_t * data, int len, int must_deselect) void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
{ {
HGLOBAL clipdata, clipdata2, clipdata3; HGLOBAL clipdata, clipdata2, clipdata3;
int len2; int len2;
@ -4182,7 +4184,7 @@ void write_clip(wchar_t * data, int len, int must_deselect)
SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0); SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0);
} }
void get_clip(wchar_t ** p, int *len) void get_clip(void *frontend, wchar_t ** p, int *len)
{ {
static HGLOBAL clipdata = NULL; static HGLOBAL clipdata = NULL;
static wchar_t *converted = 0; static wchar_t *converted = 0;
@ -4229,7 +4231,7 @@ void get_clip(wchar_t ** p, int *len)
* Move `lines' lines from position `from' to position `to' in the * Move `lines' lines from position `from' to position `to' in the
* window. * window.
*/ */
void optimised_move(int to, int from, int lines) void optimised_move(void *frontend, int to, int from, int lines)
{ {
RECT r; RECT r;
int min, max; int min, max;
@ -4315,7 +4317,7 @@ static void flash_window(int mode)
/* /*
* Beep. * Beep.
*/ */
void beep(int mode) void beep(void *frontend, int mode)
{ {
if (mode == BELL_DEFAULT) { if (mode == BELL_DEFAULT) {
/* /*
@ -4356,7 +4358,7 @@ void beep(int mode)
* Minimise or restore the window in response to a server-side * Minimise or restore the window in response to a server-side
* request. * request.
*/ */
void set_iconic(int iconic) void set_iconic(void *frontend, int iconic)
{ {
if (IsIconic(hwnd)) { if (IsIconic(hwnd)) {
if (!iconic) if (!iconic)
@ -4370,7 +4372,7 @@ void set_iconic(int iconic)
/* /*
* Move the window in response to a server-side request. * Move the window in response to a server-side request.
*/ */
void move_window(int x, int y) void move_window(void *frontend, int x, int y)
{ {
if (cfg.resize_action == RESIZE_DISABLED || if (cfg.resize_action == RESIZE_DISABLED ||
cfg.resize_action == RESIZE_FONT || cfg.resize_action == RESIZE_FONT ||
@ -4384,7 +4386,7 @@ void move_window(int x, int y)
* Move the window to the top or bottom of the z-order in response * Move the window to the top or bottom of the z-order in response
* to a server-side request. * to a server-side request.
*/ */
void set_zorder(int top) void set_zorder(void *frontend, int top)
{ {
if (cfg.alwaysontop) if (cfg.alwaysontop)
return; /* ignore */ return; /* ignore */
@ -4395,7 +4397,7 @@ void set_zorder(int top)
/* /*
* Refresh the window in response to a server-side request. * Refresh the window in response to a server-side request.
*/ */
void refresh_window(void) void refresh_window(void *frontend)
{ {
InvalidateRect(hwnd, NULL, TRUE); InvalidateRect(hwnd, NULL, TRUE);
} }
@ -4404,7 +4406,7 @@ void refresh_window(void)
* Maximise or restore the window in response to a server-side * Maximise or restore the window in response to a server-side
* request. * request.
*/ */
void set_zoomed(int zoomed) void set_zoomed(void *frontend, int zoomed)
{ {
if (IsZoomed(hwnd)) { if (IsZoomed(hwnd)) {
if (!zoomed) if (!zoomed)
@ -4418,7 +4420,7 @@ void set_zoomed(int zoomed)
/* /*
* Report whether the window is iconic, for terminal reports. * Report whether the window is iconic, for terminal reports.
*/ */
int is_iconic(void) int is_iconic(void *frontend)
{ {
return IsIconic(hwnd); return IsIconic(hwnd);
} }
@ -4426,7 +4428,7 @@ int is_iconic(void)
/* /*
* Report the window's position, for terminal reports. * Report the window's position, for terminal reports.
*/ */
void get_window_pos(int *x, int *y) void get_window_pos(void *frontend, int *x, int *y)
{ {
RECT r; RECT r;
GetWindowRect(hwnd, &r); GetWindowRect(hwnd, &r);
@ -4437,7 +4439,7 @@ void get_window_pos(int *x, int *y)
/* /*
* Report the window's pixel size, for terminal reports. * Report the window's pixel size, for terminal reports.
*/ */
void get_window_pixels(int *x, int *y) void get_window_pixels(void *frontend, int *x, int *y)
{ {
RECT r; RECT r;
GetWindowRect(hwnd, &r); GetWindowRect(hwnd, &r);
@ -4448,7 +4450,7 @@ void get_window_pixels(int *x, int *y)
/* /*
* Return the window or icon title. * Return the window or icon title.
*/ */
char *get_window_title(int icon) char *get_window_title(void *frontend, int icon)
{ {
return icon ? icon_name : window_name; return icon ? icon_name : window_name;
} }

View File

@ -833,7 +833,9 @@ void try_send(Actual_Socket s)
s->pending_error = err; s->pending_error = err;
return; return;
} else { } else {
logevent(winsock_error_string(err)); /* We're inside the Windows frontend here, so we know
* that the frontend handle is unnecessary. */
logevent(NULL, winsock_error_string(err));
fatalbox("%s", winsock_error_string(err)); fatalbox("%s", winsock_error_string(err));
} }
} else { } else {
@ -972,7 +974,9 @@ int select_result(WPARAM wParam, LPARAM lParam)
if (ret <= 0) { if (ret <= 0) {
char *str = (ret == 0 ? "Internal networking trouble" : char *str = (ret == 0 ? "Internal networking trouble" :
winsock_error_string(WSAGetLastError())); winsock_error_string(WSAGetLastError()));
logevent(str); /* We're inside the Windows frontend here, so we know
* that the frontend handle is unnecessary. */
logevent(NULL, str);
fatalbox("%s", str); fatalbox("%s", str);
} else { } else {
return plug_receive(s->plug, 2, buf, ret); return plug_receive(s->plug, 2, buf, ret);

View File

@ -18,6 +18,13 @@
#endif #endif
#endif #endif
#ifndef DONE_TYPEDEFS
#define DONE_TYPEDEFS
typedef struct config_tag Config;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal;
#endif
#define PUTTY_REG_POS "Software\\SimonTatham\\PuTTY" #define PUTTY_REG_POS "Software\\SimonTatham\\PuTTY"
#define PUTTY_REG_PARENT "Software\\SimonTatham" #define PUTTY_REG_PARENT "Software\\SimonTatham"
#define PUTTY_REG_PARENT_CHILD "PuTTY" #define PUTTY_REG_PARENT_CHILD "PuTTY"
@ -49,6 +56,14 @@ GLOBAL HINSTANCE hinst;
GLOBAL char *help_path; GLOBAL char *help_path;
GLOBAL int help_has_contents; GLOBAL int help_has_contents;
/*
* The terminal and logging context are notionally local to the
* Windows front end, but they must be shared between window.c and
* windlg.c.
*/
GLOBAL Terminal *term;
GLOBAL void *logctx;
/* /*
* I've just looked in the windows standard headr files for WM_USER, there * I've just looked in the windows standard headr files for WM_USER, there
* are hundreds of flags defined using the form WM_USER+123 so I've * are hundreds of flags defined using the form WM_USER+123 so I've