Yet more global-removal. The static variables in logging.c are now
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 26 Oct 2002 12:58:13 +0000 (12:58 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 26 Oct 2002 12:58:13 +0000 (12:58 +0000)
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.

git-svn-id: svn://svn.tartarus.org/sgt/putty@2147 cda61777-01e9-0310-a592-d414129be87e

24 files changed:
console.c
logging.c
pageant.c
plink.c
psftp.c
putty.h
puttygen.c
raw.c
rlogin.c
scp.c
sftp.c
ssh.c
ssh.h
sshzlib.c
telnet.c
terminal.c
terminal.h
unix/pterm.c
unix/pty.c
unix/unix.h
windlg.c
window.c
winnet.c
winstuff.h

index 85f99dc..703e683 100644 (file)
--- a/console.c
+++ b/console.c
@@ -36,7 +36,7 @@ void cleanup_exit(int 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)
 {
     int ret;
@@ -142,7 +142,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
  * below the configured 'warn' threshold).
  * 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;
     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.
  * 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;
     DWORD savemode, i;
@@ -240,6 +240,13 @@ int askappend(char *filename)
 
 /*
  * 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)
 {
@@ -257,7 +264,7 @@ void old_keyfile_warning(void)
     fputs(message, stderr);
 }
 
-void logevent(char *string)
+void logevent(void *frontend, char *string)
 {
 }
 
index c843118..6eaa3e9 100644 (file)
--- a/logging.c
+++ b/logging.c
@@ -8,23 +8,27 @@
 #include "putty.h"
 
 /* log session to file stuff ... */
-static FILE *lgfp = NULL;
-static char currlogfilename[FILENAME_MAX];
+struct LogContext {
+    FILE *lgfp;
+    char currlogfilename[FILENAME_MAX];
+    void *frontend;
+};
 
 static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm);
 
 /*
  * 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 == logmode) {
            /* deferred open file from pgm start? */
-           if (!lgfp)
-               logfopen();
-           if (lgfp)
-               fputc(c, lgfp);
+           if (!ctx->lgfp)
+               logfopen(ctx);
+           if (ctx->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).
  */
-void log_eventlog(char *event)
+void log_eventlog(void *handle, char *event)
 {
+    struct LogContext *ctx = (struct LogContext *)handle;
     if (cfg.logtype != LGTYP_PACKETS)
        return;
-    if (!lgfp)
-       logfopen();
-    if (lgfp)
-       fprintf(lgfp, "Event Log: %s\n", event);
+    if (!ctx->lgfp)
+       logfopen(ctx);
+    if (ctx->lgfp)
+       fprintf(ctx->lgfp, "Event Log: %s\n", event);
 }
 
 /*
  * 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;
     char dumpdata[80], smalldata[5];
 
     if (cfg.logtype != LGTYP_PACKETS)
        return;
-    if (!lgfp)
-       logfopen();
-    if (lgfp) {
-       fprintf(lgfp, "%s packet type %d / 0x%02x (%s)\n",
+    if (!ctx->lgfp)
+       logfopen(ctx);
+    if (ctx->lgfp) {
+       fprintf(ctx->lgfp, "%s packet type %d / 0x%02x (%s)\n",
                direction == PKT_INCOMING ? "Incoming" : "Outgoing",
                type, type, texttype);
        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 : '.');
            }
            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 */
-void logfopen(void)
+void logfopen(void *handle)
 {
+    struct LogContext *ctx = (struct LogContext *)handle;
     char buf[256];
     time_t t;
     struct tm tm;
     char writemod[4];
 
     /* Prevent repeat calls */
-    if (lgfp)
+    if (ctx->lgfp)
        return;
 
     if (!cfg.logtype)
@@ -94,29 +102,29 @@ void logfopen(void)
     tm = *localtime(&t);
 
     /* 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? */
-    if (lgfp) {
+    ctx->lgfp = fopen(ctx->currlogfilename, "r");  /* file already present? */
+    if (ctx->lgfp) {
        int i;
-       fclose(lgfp);
-       i = askappend(currlogfilename);
+       fclose(ctx->lgfp);
+       i = askappend(ctx->frontend, ctx->currlogfilename);
        if (i == 1)
            writemod[0] = 'a';         /* set append mode */
        else if (i == 0) {             /* cancelled */
-           lgfp = NULL;
+           ctx->lgfp = NULL;
            cfg.logtype = 0;           /* disable logging */
            return;
        }
     }
 
-    lgfp = fopen(currlogfilename, writemod);
-    if (lgfp) {                               /* enter into event log */
+    ctx->lgfp = fopen(ctx->currlogfilename, writemod);
+    if (ctx->lgfp) {                          /* enter into event log */
        /* --- 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);
-       fputs(buf, lgfp);
-       fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp);
+       fputs(buf, ctx->lgfp);
+       fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", ctx->lgfp);
 
        sprintf(buf, "%s session log (%s mode) to file: ",
                (writemod[0] == 'a') ? "Appending" : "Writing new",
@@ -124,20 +132,29 @@ void logfopen(void)
                 cfg.logtype == LGTYP_DEBUG ? "raw" :
                 cfg.logtype == LGTYP_PACKETS ? "SSH packets" : "<ukwn>"));
        /* Make sure we do not exceed the output buffer size */
-       strncat(buf, currlogfilename, 128);
+       strncat(buf, ctx->currlogfilename, 128);
        buf[strlen(buf)] = '\0';
-       logevent(buf);
+       logevent(ctx->frontend, buf);
     }
 }
 
-void logfclose(void)
+void logfclose(void *handle)
 {
-    if (lgfp) {
-       fclose(lgfp);
-       lgfp = NULL;
+    struct LogContext *ctx = (struct LogContext *)handle;
+    if (ctx->lgfp) {
+       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
  * and insert them into log file name
index 71753c0..b8a4bd8 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -153,14 +153,6 @@ struct blob {
 };
 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) \
     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
     ((unsigned long)(unsigned char)(cp)[1] << 16) | \
diff --git a/plink.c b/plink.c
index 86b3415..528eee6 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -40,7 +40,7 @@ void modalfatalbox(char *p, ...)
     WSACleanup();
     cleanup_exit(1);
 }
-void connection_fatal(char *p, ...)
+void connection_fatal(void *frontend, char *p, ...)
 {
     va_list ap;
     fprintf(stderr, "FATAL ERROR: ");
@@ -538,6 +538,8 @@ int main(int argc, char **argv)
            fprintf(stderr, "Unable to open connection:\n%s", error);
            return 1;
        }
+       logctx = log_init(NULL);
+       back->provide_logctx(backhandle, logctx);
        sfree(realhost);
     }
     connopen = 1;
diff --git a/psftp.c b/psftp.c
index 07045f2..e585732 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -1472,7 +1472,7 @@ void modalfatalbox(char *fmt, ...)
 
     cleanup_exit(1);
 }
-void connection_fatal(char *fmt, ...)
+void connection_fatal(void *frontend, char *fmt, ...)
 {
     char str[0x100];                  /* Make the size big enough */
     va_list ap;
@@ -1829,6 +1829,8 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        fprintf(stderr, "ssh_init: %s\n", err);
        return 1;
     }
+    logctx = log_init(NULL);
+    back->provide_logctx(backhandle, logctx);
     ssh_sftp_init();
     if (verbose && realhost != NULL)
        printf("Connected to %s\n", realhost);
diff --git a/putty.h b/putty.h
index ba99aae..116e2a3 100644 (file)
--- a/putty.h
+++ b/putty.h
 #endif
 #endif
 
+#ifndef DONE_TYPEDEFS
+#define DONE_TYPEDEFS
 typedef struct config_tag Config;
 typedef struct backend_tag Backend;
 typedef struct terminal_tag Terminal;
+#endif
 
 #include "puttyps.h"
 #include "network.h"
@@ -187,6 +190,7 @@ struct backend_tag {
     int (*sendok) (void *handle);
     int (*ldisc) (void *handle, int);
     void (*provide_ldisc) (void *handle, void *ldisc);
+    void (*provide_logctx) (void *handle, void *logctx);
     /*
      * back->unthrottle() tells the back end that the front end
      * buffer is clearing.
@@ -388,43 +392,43 @@ struct RSAKey;                           /* be a little careful of scope */
 /*
  * 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_cursor(Context, int, int, char *, int, unsigned long, int);
 int CharWidth(Context ctx, int uc);
-void set_title(char *);
-void set_icon(char *);
-void set_sbar(int, int, int);
-Context get_ctx(void);
+void set_title(void *frontend, char *);
+void set_icon(void *frontend, char *);
+void set_sbar(void *frontend, int, int, int);
+Context get_ctx(void *frontend);
 void free_ctx(Context);
-void palette_set(int, int, int, int);
-void palette_reset(void);
-void write_aclip(char *, int, int);
-void write_clip(wchar_t *, int, int);
-void get_clip(wchar_t **, int *);
-void optimised_move(int, int, int);
-void set_raw_mouse_mode(int);
-Mouse_Button translate_button(Mouse_Button b);
-void connection_fatal(char *, ...);
+void palette_set(void *frontend, int, int, int, int);
+void palette_reset(void *frontend);
+void write_aclip(void *frontend, char *, int, int);
+void write_clip(void *frontend, wchar_t *, int, int);
+void get_clip(void *frontend, wchar_t **, int *);
+void optimised_move(void *frontend, int, int, int);
+void set_raw_mouse_mode(void *frontend, int);
+Mouse_Button translate_button(void *frontend, Mouse_Button b);
+void connection_fatal(void *frontend, char *, ...);
 void fatalbox(char *, ...);
 void modalfatalbox(char *, ...);
-void beep(int);
-void begin_session(void);
-void sys_cursor(int x, int y);
-void request_paste(void);
+void beep(void *frontend, int);
+void begin_session(void *frontend);
+void sys_cursor(void *frontend, int x, int y);
+void request_paste(void *frontend);
 void frontend_keypress(void *frontend);
 void ldisc_update(void *frontend, int echo, int edit);
 #define OPTIMISE_IS_SCROLL 1
 
-void set_iconic(int iconic);
-void move_window(int x, int y);
-void set_zorder(int top);
-void refresh_window(void);
-void set_zoomed(int zoomed);
-int is_iconic(void);
-void get_window_pos(int *x, int *y);
-void get_window_pixels(int *x, int *y);
-char *get_window_title(int icon);
+void set_iconic(void *frontend, int iconic);
+void move_window(void *frontend, int x, int y);
+void set_zorder(void *frontend, int top);
+void refresh_window(void *frontend);
+void set_zoomed(void *frontend, int zoomed);
+int is_iconic(void *frontend);
+void get_window_pos(void *frontend, int *x, int *y);
+void get_window_pixels(void *frontend, int *x, int *y);
+char *get_window_title(void *frontend, int icon);
 
 void cleanup_exit(int);
 
@@ -451,7 +455,7 @@ void registry_cleanup(void);
  * Exports from terminal.c.
  */
 
-Terminal *term_init(void);
+Terminal *term_init(void *frontend);
 void term_size(Terminal *, int, int, int);
 void term_out(Terminal *);
 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 (*resize_fn)(void *, int, int),
                            void *resize_ctx);
+void term_provide_logctx(Terminal *term, void *logctx);
 
 /*
  * Exports from logging.c.
  */
-void logfopen();
-void logfclose();
-void logtraffic(unsigned char c, int logmode);
+void *log_init(void *frontend);
+void logfopen(void *logctx);
+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 };
-void log_eventlog(char *string);
-void log_packet(int direction, int type, char *texttype, void *data, int len);
+void log_packet(void *logctx, int direction, int type,
+               char *texttype, void *data, int len);
 
 /*
  * Exports from raw.c.
@@ -591,11 +598,11 @@ int wc_unescape(char *output, const char *wildcard);
 /*
  * Exports from windlg.c
  */
-void logevent(char *);
-void verify_ssh_host_key(char *host, int port, char *keytype,
+void logevent(void *frontend, char *);
+void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
                         char *keystr, char *fingerprint);
-void askcipher(char *ciphername, int cs);
-int askappend(char *filename);
+void askcipher(void *frontend, char *ciphername, int cs);
+int askappend(void *frontend, char *filename);
 
 /*
  * Exports from console.c (that aren't equivalents to things in
index 4be822a..956cdaf 100644 (file)
@@ -222,14 +222,6 @@ static int prompt_keyfile(HWND hwnd, char *dlgtitle,
 }
 
 /*
- * 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.
  */
 static int CALLBACK LicenceProc(HWND hwnd, UINT msg,
diff --git a/raw.c b/raw.c
index e269a7d..049b851 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -41,7 +41,7 @@ static int raw_closing(Plug plug, char *error_msg, int error_code,
     }
     if (error_msg) {
        /* A socket error has occurred. */
-       logevent(error_msg);
+       logevent(raw->frontend, error_msg);
        connection_fatal("%s", error_msg);
     }                                 /* Otherwise, the remote side closed the connection normally. */
     return 0;
@@ -93,7 +93,7 @@ static char *raw_init(void *frontend_handle, void **backend_handle,
     {
        char buf[200];
        sprintf(buf, "Looking up host \"%.170s\"", host);
-       logevent(buf);
+       logevent(raw->frontend, buf);
     }
     addr = sk_namelookup(host, realhost);
     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];
        sk_getaddr(addr, addrbuf, 100);
        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);
     if ((err = sk_socket_error(raw->s)))
@@ -191,6 +191,11 @@ static void raw_provide_ldisc(void *handle, void *ldisc)
     /* This is a stub. */
 }
 
+static void raw_provide_logctx(void *handle, void *logctx)
+{
+    /* This is a stub. */
+}
+
 static int raw_exitcode(void *handle)
 {
     /* Exit codes are a meaningless concept in the Raw protocol */
@@ -208,6 +213,7 @@ Backend raw_backend = {
     raw_sendok,
     raw_ldisc,
     raw_provide_ldisc,
+    raw_provide_logctx,
     raw_unthrottle,
     1
 };
index 61f4afb..7b55604 100644 (file)
--- a/rlogin.c
+++ b/rlogin.c
@@ -42,7 +42,7 @@ static int rlogin_closing(Plug plug, char *error_msg, int error_code,
     }
     if (error_msg) {
        /* A socket error has occurred. */
-       logevent(error_msg);
+       logevent(rlogin->frontend, error_msg);
        connection_fatal("%s", error_msg);
     }                                 /* Otherwise, the remote side closed the connection normally. */
     return 0;
@@ -124,7 +124,7 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle,
     {
        char buf[200];
        sprintf(buf, "Looking up host \"%.170s\"", host);
-       logevent(buf);
+       logevent(rlogin->frontend, buf);
     }
     addr = sk_namelookup(host, realhost);
     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];
        sk_getaddr(addr, addrbuf, 100);
        sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
-       logevent(buf);
+       logevent(rlogin->frontend, buf);
     }
     rlogin->s = new_connection(addr, *realhost, port, 1, 0,
                               nodelay, (Plug) rlogin);
@@ -255,6 +255,11 @@ static void rlogin_provide_ldisc(void *handle, void *ldisc)
     /* This is a stub. */
 }
 
+static void rlogin_provide_logctx(void *handle, void *logctx)
+{
+    /* This is a stub. */
+}
+
 static int rlogin_exitcode(void *handle)
 {
     Rlogin rlogin = (Rlogin) handle;
@@ -273,6 +278,7 @@ Backend rlogin_backend = {
     rlogin_sendok,
     rlogin_ldisc,
     rlogin_provide_ldisc,
+    rlogin_provide_logctx,
     rlogin_unthrottle,
     1
 };
diff --git a/scp.c b/scp.c
index 0d100f0..069f7ef 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -260,7 +260,7 @@ void modalfatalbox(char *fmt, ...)
 
     cleanup_exit(1);
 }
-void connection_fatal(char *fmt, ...)
+void connection_fatal(void *frontend, char *fmt, ...)
 {
     char str[0x100];                  /* Make the size big enough */
     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);
     if (err != NULL)
        bump("ssh_init: %s", err);
+    logctx = log_init(NULL);
+    back->provide_logctx(backhandle, logctx);
     ssh_scp_init();
     if (verbose && realhost != NULL)
        tell_user(stderr, "Connected to %s\n", realhost);
diff --git a/sftp.c b/sftp.c
index e1f6017..6d78c2c 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -942,8 +942,6 @@ struct fxp_name *fxp_dup_name(struct fxp_name *name)
  */
 void fxp_free_name(struct fxp_name *name)
 {
-    int i;
-
     sfree(name->filename);
     sfree(name->longname);
     sfree(name);
diff --git a/ssh.c b/ssh.c
index d713ccf..0cfba57 100644 (file)
--- a/ssh.c
+++ b/ssh.c
 #define TRUE 1
 #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_SMSG_PUBLIC_KEY                      2    /* 0x2 */
 #define SSH1_CMSG_SESSION_KEY                     3    /* 0x3 */
@@ -557,6 +537,7 @@ struct ssh_tag {
     Socket s;
 
     void *ldisc;
+    void *logctx;
 
     unsigned char session_key[32];
     int v1_compressing;
@@ -658,6 +639,26 @@ struct ssh_tag {
     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)
 {
     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,
                                     st->biglen, NULL)) {
-        bombout(("Network attack (CRC compensation) detected!"));
+        bombout((ssh,"Network attack (CRC compensation) detected!"));
         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->gotcrc = GET_32BIT(ssh->pktin.data + st->biglen - 4);
     if (st->gotcrc != st->realcrc) {
-       bombout(("Incorrect CRC received on packet"));
+       bombout((ssh,"Incorrect CRC received on packet"));
        crReturn(0);
     }
 
@@ -860,8 +861,11 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
 
     ssh->pktin.type = ssh->pktin.body[-1];
 
-    log_packet(PKT_INCOMING, ssh->pktin.type, ssh1_pkt_type(ssh->pktin.type),
-              ssh->pktin.body, ssh->pktin.length);
+    if (ssh->logctx)
+       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 ||
        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) {
        long stringlen = GET_32BIT(ssh->pktin.body);
        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);
        }
     }
@@ -903,7 +907,7 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
        memcpy(buf + nowlen, ssh->pktin.body + 4, msglen);
        buf[nowlen + msglen] = '\0';
        /* 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);
     }
 
@@ -957,7 +961,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
      * do us any more damage.
      */
     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);
     }
 
@@ -1005,7 +1009,7 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
     if (ssh->scmac
        && !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4,
                               st->incoming_sequence)) {
-       bombout(("Incorrect MAC received on packet"));
+       bombout((ssh,"Incorrect MAC received on packet"));
        crReturn(0);
     }
     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.type = ssh->pktin.data[5];
 
-    log_packet(PKT_INCOMING, ssh->pktin.type,
-              ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),
-              ssh->pktin.data+6, ssh->pktin.length-6);
+    if (ssh->logctx)
+       log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type,
+                  ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),
+                  ssh->pktin.data+6, ssh->pktin.length-6);
 
     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);
             buf[nowlen + msglen] = '\0';
             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 > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
                      ssh2_disconnect_reasons[reason] : "unknown",
@@ -1177,8 +1182,10 @@ static int s_wrpkt_prepare(Ssh ssh)
 
     ssh->pktout.body[-1] = ssh->pktout.type;
 
-    log_packet(PKT_OUTGOING, ssh->pktout.type, ssh1_pkt_type(ssh->pktout.type),
-              ssh->pktout.body, ssh->pktout.length);
+    if (ssh->logctx)
+       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) {
        unsigned char *compblk;
@@ -1459,9 +1466,10 @@ static int ssh2_pkt_construct(Ssh ssh)
 {
     int cipherblk, maclen, padding, i;
 
-    log_packet(PKT_OUTGOING, ssh->pktout.data[5],
-              ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]),
-              ssh->pktout.data + 6, ssh->pktout.length - 6);
+    if (ssh->logctx)
+       log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.data[5],
+                  ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]),
+                  ssh->pktout.data + 6, ssh->pktout.length - 6);
 
     /*
      * Compress packet payload.
@@ -1626,7 +1634,7 @@ static Bignum ssh2_pkt_getmp(Ssh ssh)
     if (!p)
        return NULL;
     if (p[0] & 0x80) {
-       bombout(("internal error: Can't handle negative mpints"));
+       bombout((ssh,"internal error: Can't handle negative mpints"));
        return NULL;
     }
     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;
 
     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);
     }
     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);
     }
 
@@ -1989,7 +1997,7 @@ static int ssh_closing(Plug plug, char *error_msg, int error_code,
     if (error_msg) {
        /* A socket error has occurred. */
        logevent(error_msg);
-       connection_fatal(error_msg);
+       connection_fatal(ssh->frontend, error_msg);
     } else {
        /* 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);
 
     if (ssh->pktin.type != SSH1_SMSG_PUBLIC_KEY) {
-       bombout(("Public key packet not received"));
+       bombout((ssh,"Public key packet not received"));
        crReturn(0);
     }
 
@@ -2299,7 +2307,8 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            fatalbox("Out of memory");
        rsastr_fmt(keystr, &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);
        sfree(keystr);
     }
@@ -2347,17 +2356,17 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        }
        if (!cipher_chosen) {
            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"));
            else
                /* shouldn't happen */
-               bombout(("No supported ciphers found"));
+               bombout((ssh,"No supported ciphers found"));
            crReturn(0);
        }
 
        /* Warn about chosen cipher if necessary. */
        if (warn)
-           askcipher(cipher_string, 0);
+           askcipher(ssh->frontend, cipher_string, 0);
     }
 
     switch (s->cipher_type) {
@@ -2400,7 +2409,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     crWaitUntil(ispkt);
 
     if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
-       bombout(("Encryption not successfully enabled"));
+       bombout((ssh,"Encryption not successfully enabled"));
        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_END);
                logevent("Unable to authenticate");
-               connection_fatal("Unable to authenticate");
+               connection_fatal(ssh->frontend, "Unable to authenticate");
                ssh->state = SSH_STATE_CLOSED;
                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 */
            }
            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);
            }
 
@@ -2786,7 +2795,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                                " our public key.\r\n");
                continue;              /* go and try password */
            } 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);
            }
 
@@ -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");
            logevent("Authentication refused");
        } 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);
        }
     }
@@ -3019,7 +3028,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        } while (!ispkt);
        if (ssh->pktin.type != SSH1_SMSG_SUCCESS
            && ssh->pktin.type != SSH1_SMSG_FAILURE) {
-           bombout(("Protocol confusion"));
+           bombout((ssh,"Protocol confusion"));
            crReturnV;
        } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
            logevent("Agent forwarding refused");
@@ -3047,7 +3056,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        } while (!ispkt);
        if (ssh->pktin.type != SSH1_SMSG_SUCCESS
            && ssh->pktin.type != SSH1_SMSG_FAILURE) {
-           bombout(("Protocol confusion"));
+           bombout((ssh,"Protocol confusion"));
            crReturnV;
        } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
            logevent("X11 forwarding refused");
@@ -3156,7 +3165,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                        } while (!ispkt);
                        if (ssh->pktin.type != SSH1_SMSG_SUCCESS
                            && ssh->pktin.type != SSH1_SMSG_FAILURE) {
-                           bombout(("Protocol confusion"));
+                           bombout((ssh,"Protocol confusion"));
                            crReturnV;
                        } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
                            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);
        if (ssh->pktin.type != SSH1_SMSG_SUCCESS
            && ssh->pktin.type != SSH1_SMSG_FAILURE) {
-           bombout(("Protocol confusion"));
+           bombout((ssh,"Protocol confusion"));
            crReturnV;
        } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
            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);
        if (ssh->pktin.type != SSH1_SMSG_SUCCESS
            && ssh->pktin.type != SSH1_SMSG_FAILURE) {
-           bombout(("Protocol confusion"));
+           bombout((ssh,"Protocol confusion"));
            crReturnV;
        } else if (ssh->pktin.type == SSH1_SMSG_FAILURE) {
            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);
                    }
                } 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 ? "" :
                             "_CONFIRMATION", c ? "half-open" : "nonexistent",
                             i));
@@ -3552,7 +3561,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                 ssh->state = SSH_STATE_CLOSED;
                 crReturnV;
            } else {
-               bombout(("Strange packet received: type %d", ssh->pktin.type));
+               bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));
                crReturnV;
            }
        } else {
@@ -3820,7 +3829,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        int i, j, len;
 
        if (ssh->pktin.type != SSH2_MSG_KEXINIT) {
-           bombout(("expected key exchange packet from server"));
+           bombout((ssh,"expected key exchange packet from server"));
            crReturn(0);
        }
        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->warn)
-                   askcipher(s->cscipher_tobe->name, 1);
+                   askcipher(ssh->frontend, s->cscipher_tobe->name, 1);
                break;
            }
        }
        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);
        }
 
@@ -3890,12 +3899,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            }
            if (s->sccipher_tobe) {
                if (s->warn)
-                   askcipher(s->sccipher_tobe->name, 2);
+                   askcipher(ssh->frontend, s->sccipher_tobe->name, 2);
                break;
            }
        }
        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);
        }
 
@@ -3968,7 +3977,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
 
        crWaitUntil(ispkt);
        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);
        }
        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);
     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);
     }
     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 ||
        !ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,
                                 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);
     }
 
@@ -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->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);
     if (s->first_kex) {                       /* don't bother logging this in rekeys */
        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);
     if (ssh->pktin.type != SSH2_MSG_NEWKEYS) {
-       bombout(("expected new-keys packet from server"));
+       bombout((ssh,"expected new-keys packet from server"));
        crReturn(0);
     }
 
@@ -4281,7 +4291,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     ssh2_pkt_send(ssh);
     crWaitUntilV(ispkt);
     if (ssh->pktin.type != SSH2_MSG_SERVICE_ACCEPT) {
-       bombout(("Server refused user authentication protocol"));
+       bombout((ssh,"Server refused user authentication protocol"));
        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 */
        if (*cfg.keyfile) {
            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);
            if (keytype == SSH_KEYTYPE_SSH2) {
                s->publickey_blob =
@@ -4389,8 +4400,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                                         &s->publickey_bloblen);
            } else {
                char msgbuf[256];
-               logeventf("Unable to use this key file (%s)",
-                       key_type_to_str(keytype));
+               logeventf(ssh->frontend,
+                         "Unable to use this key file (%s)",
+                         key_type_to_str(keytype));
                sprintf(msgbuf, "Unable to use key file \"%.150s\" (%s)\r\n",
                        cfg.keyfile, key_type_to_str(keytype));
                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)
                    s->curr_prompt = 0;
            } 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));
                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_send(ssh);
                        logevent("Unable to authenticate");
-                       connection_fatal("Unable to authenticate");
+                       connection_fatal(ssh->frontend,
+                                        "Unable to authenticate");
                        ssh->state = SSH_STATE_CLOSED;
                        crReturnV;
                    }
@@ -5038,12 +5051,12 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     ssh2_pkt_send(ssh);
     crWaitUntilV(ispkt);
     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;
        /* FIXME: error data comes back in FAILURE packet */
     }
     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;
     }
     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_FAILURE) {
-               bombout(("Unexpected response to X11 forwarding request:"
+               bombout((ssh,"Unexpected response to X11 forwarding request:"
                         " packet type %d", ssh->pktin.type));
                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_FAILURE) {
-                               bombout(("Unexpected response to port "
+                               bombout((ssh,"Unexpected response to port "
                                         "forwarding request: packet type %d",
                                         ssh->pktin.type));
                                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_FAILURE) {
-               bombout(("Unexpected response to agent forwarding request:"
+               bombout((ssh,"Unexpected response to agent forwarding request:"
                         " packet type %d", ssh->pktin.type));
                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_FAILURE) {
-               bombout(("Unexpected response to pty request:"
+               bombout((ssh,"Unexpected response to pty request:"
                         " packet type %d", ssh->pktin.type));
                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);
        if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
            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));
                crReturnV;
            }
@@ -5371,7 +5384,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                ssh->fallback_cmd = TRUE;
                continue;
            }
-           bombout(("Server refused to start a shell/command"));
+           bombout((ssh,"Server refused to start a shell/command"));
            crReturnV;
        } else {
            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);
                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));
                }
                /* 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);
                }
            } else {
-               bombout(("Strange packet received: type %d", ssh->pktin.type));
+               bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));
                crReturnV;
            }
        } else {
@@ -5851,7 +5864,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->sccipher = NULL;
     ssh->sc_cipher_ctx = NULL;
     ssh->csmac = NULL;
-    ssh->sc_mac_ctx = NULL;
+    ssh->cs_mac_ctx = NULL;
     ssh->scmac = NULL;
     ssh->sc_mac_ctx = NULL;
     ssh->cscomp = NULL;
@@ -5865,6 +5878,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->size_needed = FALSE;
     ssh->eof_needed = FALSE;
     ssh->ldisc = NULL;
+    ssh->logctx = NULL;
     {
        static const struct Packet empty = { 0, 0, NULL, NULL, 0 };
        ssh->pktin = ssh->pktout = empty;
@@ -6148,6 +6162,12 @@ static void ssh_provide_ldisc(void *handle, void *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)
 {
     Ssh ssh = (Ssh) handle;
@@ -6176,6 +6196,7 @@ Backend ssh_backend = {
     ssh_sendok,
     ssh_ldisc,
     ssh_provide_ldisc,
+    ssh_provide_logctx,
     ssh_unthrottle,
     22
 };
diff --git a/ssh.h b/ssh.h
index 2d2d0df..e3423cc 100644 (file)
--- a/ssh.h
+++ b/ssh.h
@@ -248,7 +248,7 @@ int random_byte(void);
 void random_add_noise(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 */
 void *new_sock_channel(void *handle, Socket s);
index ae60bb1..58069b6 100644 (file)
--- a/sshzlib.c
+++ b/sshzlib.c
@@ -956,6 +956,7 @@ void *zlib_decompress_init(void)
     dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL;
     dctx->bits = 0;
     dctx->nbits = 0;
+    dctx->winpos = 0;
 
     return dctx;
 }
index 6fcde71..1f1a89e 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -224,14 +224,14 @@ static void c_write1(Telnet telnet, int c)
     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];
     sprintf(buf, "%s:\t%s %s", sender,
            (cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
             cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
            telopt(option));
-    logevent(buf);
+    logevent(telnet->frontend, buf);
 }
 
 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[2] = option;
     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)
@@ -314,7 +314,7 @@ static void proc_rec_opt(Telnet telnet, int cmd, int option)
 {
     const struct Opt *const *o;
 
-    log_option("server", cmd, option);
+    log_option(telnet, "server", cmd, option);
     for (o = opts; *o; o++) {
        if ((*o)->option == option && (*o)->ack == cmd) {
            switch (telnet->opt_states[(*o)->index]) {
@@ -378,11 +378,11 @@ static void process_subneg(Telnet telnet)
            b[n] = IAC;
            b[n + 1] = SE;
            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);
-           logevent(logbuf);
+           logevent(telnet->frontend, logbuf);
        } else
-           logevent("server:\tSB TSPEED <something weird>");
+           logevent(telnet->frontend, "server:\tSB TSPEED <something weird>");
        break;
       case TELOPT_TTYPE:
        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;
            telnet->bufsize = sk_write(telnet->s, b, n + 6);
            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);
-           logevent(logbuf);
+           logevent(telnet->frontend, logbuf);
        } else
-           logevent("server:\tSB TTYPE <something weird>\r\n");
+           logevent(telnet->frontend, "server:\tSB TTYPE <something weird>\r\n");
        break;
       case TELOPT_OLD_ENVIRON:
       case TELOPT_NEW_ENVIRON:
@@ -414,7 +414,7 @@ static void process_subneg(Telnet telnet)
            char logbuf[50];
            p++;
            sprintf(logbuf, "server:\tSB %s SEND", telopt(telnet->sb_opt));
-           logevent(logbuf);
+           logevent(telnet->frontend, logbuf);
            if (telnet->sb_opt == TELOPT_OLD_ENVIRON) {
                if (cfg.rfc_environ) {
                    value = RFC_VALUE;
@@ -477,7 +477,7 @@ static void process_subneg(Telnet telnet)
            telnet->bufsize = sk_write(telnet->s, b, n);
            sprintf(logbuf, "client:\tSB %s IS %s", telopt(telnet->sb_opt),
                    n == 6 ? "<nothing>" : "<stuff>");
-           logevent(logbuf);
+           logevent(telnet->frontend, logbuf);
        }
        break;
     }
@@ -605,7 +605,7 @@ static int telnet_closing(Plug plug, char *error_msg, int error_code,
     }
     if (error_msg) {
        /* A socket error has occurred. */
-       logevent(error_msg);
+       logevent(telnet->frontend, error_msg);
        connection_fatal("%s", error_msg);
     }                                 /* Otherwise, the remote side closed the connection normally. */
     return 0;
@@ -666,7 +666,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle,
     {
        char buf[200];
        sprintf(buf, "Looking up host \"%.170s\"", host);
-       logevent(buf);
+       logevent(telnet->frontend, buf);
     }
     addr = sk_namelookup(host, realhost);
     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];
        sk_getaddr(addr, addrbuf, 100);
        sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
-       logevent(buf);
+       logevent(telnet->frontend, buf);
     }
     telnet->s = new_connection(addr, *realhost, port, 0, 1,
                               nodelay, (Plug) telnet);
@@ -788,7 +788,7 @@ static void telnet_size(void *handle, int width, int height)
     sprintf(logbuf, "client:\tSB NAWS %d,%d",
            ((unsigned char) b[3] << 8) + (unsigned char) b[4],
            ((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;
 }
 
+static void telnet_provide_logctx(void *handle, void *logctx)
+{
+    /* This is a stub. */
+}
+
 static int telnet_exitcode(void *handle)
 {
     Telnet telnet = (Telnet) handle;
@@ -934,6 +939,7 @@ Backend telnet_backend = {
     telnet_sendok,
     telnet_ldisc,
     telnet_provide_ldisc,
+    telnet_provide_logctx,
     telnet_unthrottle,
     23
 };
index 0cbf918..738c754 100644 (file)
@@ -188,7 +188,7 @@ static void power_on(Terminal *term)
 void term_update(Terminal *term)
 {
     Context ctx;
-    ctx = get_ctx();
+    ctx = get_ctx(term->frontend);
     if (ctx) {
        int need_sbar_update = term->seen_disp_event;
        if (term->seen_disp_event && cfg.scroll_on_disp) {
@@ -199,7 +199,7 @@ void term_update(Terminal *term)
        if (need_sbar_update)
            update_sbar(term);
        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);
     }
 }
@@ -261,7 +261,7 @@ void term_reconfig(Terminal *term)
        swap_screen(term, 0, FALSE, FALSE);
     if (cfg.no_mouse_rep) {
        term->xterm_mouse = 0;
-       set_raw_mouse_mode(0);
+       set_raw_mouse_mode(term->frontend, 0);
     }
     if (cfg.no_remote_charset) {
        term->cset_attr[0] = term->cset_attr[1] = ATTR_ASCII;
@@ -289,7 +289,7 @@ void term_clrsb(Terminal *term)
 /*
  * Initialise the terminal.
  */
-Terminal *term_init(void)
+Terminal *term_init(void *frontend)
 {
     Terminal *term;
 
@@ -298,6 +298,8 @@ Terminal *term_init(void)
      * that need it.
      */
     term = smalloc(sizeof(Terminal));
+    term->frontend = frontend;
+    term->logctx = NULL;
     term->compatibility_level = TM_PUTTY;
     strcpy(term->id_string, "\033[?6c");
     term->last_blink = term->last_tblink = 0;
@@ -558,7 +560,8 @@ static void update_sbar(Terminal *term)
 
     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 */
            deselect(term);
            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;
            break;
          case 5:                      /* reverse video */
@@ -932,11 +935,11 @@ static void toggle_mode(Terminal *term, int mode, int query, int state)
            break;
          case 1000:                   /* xterm mouse 1 */
            term->xterm_mouse = state ? 1 : 0;
-           set_raw_mouse_mode(state);
+           set_raw_mouse_mode(term->frontend, state);
            break;
          case 1002:                   /* xterm mouse 2 */
            term->xterm_mouse = state ? 2 : 0;
-           set_raw_mouse_mode(state);
+           set_raw_mouse_mode(term->frontend, state);
            break;
          case 1047:                   /* alternate screen */
            compatibility(OTHER);
@@ -994,14 +997,14 @@ static void do_osc(Terminal *term)
          case 0:
          case 1:
            if (!cfg.no_remote_wintitle)
-               set_icon(term->osc_string);
+               set_icon(term->frontend, term->osc_string);
            if (term->esc_args[0] == 1)
                break;
            /* fall through: parameter 0 means set both */
          case 2:
          case 21:
            if (!cfg.no_remote_wintitle)
-               set_title(term->osc_string);
+               set_title(term->frontend, term->osc_string);
            break;
        }
     }
@@ -1087,8 +1090,8 @@ void term_out(Terminal *term)
             * Optionally log the session traffic to a file. Useful for
             * debugging and possibly also useful for actual logging.
             */
-           if (cfg.logtype == LGTYP_DEBUG)
-               logtraffic((unsigned char) c, LGTYP_DEBUG);
+           if (cfg.logtype == LGTYP_DEBUG && term->logctx)
+               logtraffic(term->logctx, (unsigned char) c, LGTYP_DEBUG);
        } else {
            c = unget;
            unget = -1;
@@ -1374,7 +1377,7 @@ void term_out(Terminal *term)
                            term->vbell_startpoint = ticks;
                            term_update(term);
                        } else
-                           beep(cfg.beep);
+                           beep(term->frontend, cfg.beep);
                    }
                    term->disptop = 0;
                }
@@ -1415,7 +1418,8 @@ void term_out(Terminal *term)
                fix_cpos;
                term->seen_disp_event = TRUE;
                term->paste_hold = 0;
-               logtraffic((unsigned char) c, LGTYP_ASCII);
+               if (term->logctx)
+                   logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
                break;
              case '\014':
                if (has_compat(SCOANSI)) {
@@ -1439,7 +1443,8 @@ void term_out(Terminal *term)
                term->wrapnext = FALSE;
                term->seen_disp_event = 1;
                term->paste_hold = 0;
-               logtraffic((unsigned char) c, LGTYP_ASCII);
+               if (term->logctx)
+                   logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
                break;
              case '\t':
                {
@@ -1487,8 +1492,9 @@ void term_out(Terminal *term)
                    incpos(cursplus);
                    check_selection(term, term->curs, cursplus);
                }
-               if ((c & CSET_MASK) == ATTR_ASCII || (c & CSET_MASK) == 0)
-                   logtraffic((unsigned char) c, LGTYP_ASCII);
+               if (((c & CSET_MASK) == ATTR_ASCII || (c & CSET_MASK) == 0) &&
+                   term->logctx)
+                   logtraffic(term->logctx, (unsigned char) c, LGTYP_ASCII);
                {
                    extern int wcwidth(wchar_t ucs);
                    int width = 0;
@@ -1632,7 +1638,7 @@ void term_out(Terminal *term)
                        ldisc_send(term->ldisc, NULL, 0, 0);
                    if (term->reset_132) {
                        if (!cfg.no_remote_resize)
-                           request_resize(80, term->rows);
+                           request_resize(term->frontend, 80, term->rows);
                        term->reset_132 = 0;
                    }
                    fix_cpos;
@@ -2134,7 +2140,7 @@ void term_out(Terminal *term)
                                term->esc_args[0] >= 24)) {
                            compatibility(VT340TEXT);
                            if (!cfg.no_remote_resize)
-                               request_resize(term->cols,
+                               request_resize(term->frontend, term->cols,
                                               def(term->esc_args[0], 24));
                            deselect(term);
                        } else if (term->esc_nargs >= 1 &&
@@ -2146,15 +2152,16 @@ void term_out(Terminal *term)
                                int x, y, len;
                                char buf[80], *p;
                              case 1:
-                               set_iconic(FALSE);
+                               set_iconic(term->frontend, FALSE);
                                break;
                              case 2:
-                               set_iconic(TRUE);
+                               set_iconic(term->frontend, TRUE);
                                break;
                              case 3:
                                if (term->esc_nargs >= 3) {
                                    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));
                                }
                                break;
@@ -2165,42 +2172,46 @@ void term_out(Terminal *term)
                                 * manage it. */
                                break;
                              case 5:
-                               set_zorder(TRUE);   /* move to top */
+                               /* move to top */
+                               set_zorder(term->frontend, TRUE);
                                break;
                              case 6:
-                               set_zorder(FALSE);  /* move to bottom */
+                               /* move to bottom */
+                               set_zorder(term->frontend, FALSE);
                                break;
                              case 7:
-                               refresh_window();
+                               refresh_window(term->frontend);
                                break;
                              case 8:
                                if (term->esc_nargs >= 3) {
                                    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));
                                }
                                break;
                              case 9:
                                if (term->esc_nargs >= 2)
-                                   set_zoomed(term->esc_args[1] ?
+                                   set_zoomed(term->frontend,
+                                              term->esc_args[1] ?
                                               TRUE : FALSE);
                                break;
                              case 11:
                                if (term->ldisc)
                                    ldisc_send(term->ldisc,
-                                              is_iconic() ? "\033[1t" :
-                                              "\033[2t", 4, 0);
+                                              is_iconic(term->frontend) ?
+                                              "\033[1t" : "\033[2t", 4, 0);
                                break;
                              case 13:
                                if (term->ldisc) {
-                                   get_window_pos(&x, &y);
+                                   get_window_pos(term->frontend, &x, &y);
                                    len = sprintf(buf, "\033[3;%d;%dt", x, y);
                                    ldisc_send(term->ldisc, buf, len, 0);
                                }
                                break;
                              case 14:
                                if (term->ldisc) {
-                                   get_window_pixels(&x, &y);
+                                   get_window_pixels(term->frontend, &x, &y);
                                    len = sprintf(buf, "\033[4;%d;%dt", x, y);
                                    ldisc_send(term->ldisc, buf, len, 0);
                                }
@@ -2231,7 +2242,7 @@ void term_out(Terminal *term)
                                break;
                              case 20:
                                if (term->ldisc) {
-                                   p = get_window_title(TRUE);
+                                   p = get_window_title(term->frontend, TRUE);
                                    len = strlen(p);
                                    ldisc_send(term->ldisc, "\033]L", 3, 0);
                                    ldisc_send(term->ldisc, p, len, 0);
@@ -2240,7 +2251,7 @@ void term_out(Terminal *term)
                                break;
                              case 21:
                                if (term->ldisc) {
-                                   p = get_window_title(FALSE);
+                                   p = get_window_title(term->frontend,FALSE);
                                    len = strlen(p);
                                    ldisc_send(term->ldisc, "\033]l", 3, 0);
                                    ldisc_send(term->ldisc, p, len, 0);
@@ -2275,7 +2286,7 @@ void term_out(Terminal *term)
                        compatibility(VT420);
                        if (term->esc_nargs == 1 && term->esc_args[0] > 0) {
                            if (!cfg.no_remote_resize)
-                               request_resize(term->cols,
+                               request_resize(term->frontend, term->cols,
                                               def(term->esc_args[0],
                                                   cfg.height));
                            deselect(term);
@@ -2289,7 +2300,8 @@ void term_out(Terminal *term)
                        compatibility(VT340TEXT);
                        if (term->esc_nargs <= 1) {
                            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);
                            deselect(term);
                        }
@@ -2441,7 +2453,7 @@ void term_out(Terminal *term)
                    term->osc_strlen = 0;
                    break;
                  case 'R':            /* Linux palette reset */
-                   palette_reset();
+                   palette_reset(term->frontend);
                    term_invalidate(term);
                    term->termstate = TOPLEVEL;
                    break;
@@ -2520,7 +2532,7 @@ void term_out(Terminal *term)
                    }
                    term->osc_string[term->osc_strlen++] = val;
                    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[3] * 16 + term->osc_string[4],
                                    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++;
     *wbptr++ = 0;
 #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 */
        sfree(workbuf);
 }
@@ -3515,7 +3527,7 @@ void term_do_paste(Terminal *term)
     wchar_t *data;
     int len;
 
-    get_clip(&data, &len);
+    get_clip(term->frontend, &data, &len);
     if (data && len > 0) {
         wchar_t *p, *q;
 
@@ -3558,7 +3570,7 @@ void term_do_paste(Terminal *term)
             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,
@@ -3651,7 +3663,7 @@ void term_mouse(Terminal *term, Mouse_Button b, Mouse_Action a, int x, int y,
        return;
     }
 
-    b = translate_button(b);
+    b = translate_button(term->frontend, b);
 
     /*
      * 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
 #endif
                   )) {
-       request_paste();
+       request_paste(term->frontend);
     }
 
     term_update(term);
@@ -3871,3 +3883,8 @@ int from_backend(void *vterm, int is_stderr, char *data, int len)
      */
     return 0;
 }
+
+void term_provide_logctx(Terminal *term, void *logctx)
+{
+    term->logctx = logctx;
+}
index 9628e07..4f6b6e7 100644 (file)
@@ -163,6 +163,10 @@ struct terminal_tag {
     void *resize_ctx;
 
     void *ldisc;
+
+    void *frontend;
+
+    void *logctx;
 };
 
 #define in_utf(term) ((term)->utf || line_codepage==CP_UTF8)
index 2346176..0d18a7c 100644 (file)
@@ -57,10 +57,14 @@ struct gui_data {
     Backend *back;
     void *backhandle;
     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;
 
 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
@@ -84,7 +88,7 @@ int askappend(char *filename)
     return 2;
 }
 
-void logevent(char *string)
+void logevent(void *frontend, char *string)
 {
     /*
      * 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)
        return inst->font_height;
     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
  * 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)
        return MBT_SELECT;
     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
  * request.
  */
-void set_iconic(int iconic)
+void set_iconic(void *frontend, int iconic)
 {
     /*
      * GTK 1.2 doesn't know how to do this.
      */
 #if GTK_CHECK_VERSION(2,0,0)
+    struct gui_data *inst = (struct gui_data *)frontend;
     if (iconic)
        gtk_window_iconify(GTK_WINDOW(inst->window));
     else
@@ -141,8 +150,9 @@ void set_iconic(int iconic)
 /*
  * 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
      * 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
  * 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)
        gdk_window_raise(inst->window->window);
     else
@@ -170,8 +181,9 @@ void set_zorder(int top)
 /*
  * 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);
 }
 
@@ -179,12 +191,13 @@ void refresh_window(void)
  * Maximise or restore the window in response to a server-side
  * request.
  */
-void set_zoomed(int zoomed)
+void set_zoomed(void *frontend, int zoomed)
 {
     /*
      * GTK 1.2 doesn't know how to do this.
      */
 #if GTK_CHECK_VERSION(2,0,0)
+    struct gui_data *inst = (struct gui_data *)frontend;
     if (iconic)
        gtk_window_maximize(GTK_WINDOW(inst->window));
     else
@@ -195,16 +208,18 @@ void set_zoomed(int zoomed)
 /*
  * 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);
 }
 
 /*
  * 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
      * 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.
  */
-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
      * 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.
  */
-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;
 }
 
@@ -251,7 +268,7 @@ gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
     return FALSE;
 }
 
-void show_mouseptr(int show)
+static void show_mouseptr(struct gui_data *inst, int show)
 {
     if (!cfg.hide_mouseptr)
        show = 1;
@@ -305,7 +322,7 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *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
@@ -327,7 +344,7 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *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];
     int start, end;
 
@@ -433,7 +450,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
         * Neither does Shift-Ins.
         */
        if (event->keyval == GDK_Insert && (event->state & GDK_SHIFT_MASK)) {
-           request_paste();
+           request_paste(inst);
            return TRUE;
        }
 
@@ -797,7 +814,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 #endif
 
        ldisc_send(inst->ldisc, output+start, end-start, 1);
-       show_mouseptr(0);
+       show_mouseptr(inst, 0);
        term_seen_key_event(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;
     int shift, ctrl, alt, x, y, button, act;
 
-    show_mouseptr(1);
+    show_mouseptr(inst, 1);
 
     if (event->button == 4 && event->type == GDK_BUTTON_PRESS) {
        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;
     int shift, ctrl, alt, x, y, button;
 
-    show_mouseptr(1);
+    show_mouseptr(inst, 1);
 
     shift = event->state & GDK_SHIFT_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)
 {
+    struct gui_data *inst = (struct gui_data *)data;
     inst->term->has_focus = event->in;
     term_out(inst->term);
     term_update(inst->term);
-    show_mouseptr(1);
+    show_mouseptr(inst, 1);
     return FALSE;
 }
 
 /*
  * 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;
     send_raw_mouse = activate;
     if (send_raw_mouse)
        inst->currcursor = inst->rawcursor;
     else
        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 offset_x, offset_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
      * 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_y += 32;
 
@@ -1080,7 +1100,7 @@ void request_resize(int w, int h)
 #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];
 
@@ -1095,7 +1115,7 @@ void real_palette_set(int n, int r, int g, int b)
                n, r, g, b);
 }
 
-void set_window_background(void)
+void set_window_background(struct gui_data *inst)
 {
     if (inst->area && inst->area->window)
        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]);
 }
 
-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] = {
        0, 2, 4, 6, 8, 10, 12, 14,
        1, 3, 5, 7, 9, 11, 13, 15,
        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)
-       real_palette_set(first[n] + 1, r, g, b);
+       real_palette_set(inst, first[n] + 1, r, g, b);
     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. */
     static const int ww[] = {
        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]);
     }
 
-    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)
        sfree(inst->pasteout_data);
     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,
                   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,
                           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,
                     gpointer data)
 {
+    struct gui_data *inst = (struct gui_data *)data;
     term_deselect(inst->term);
     if (inst->pasteout_data)
        sfree(inst->pasteout_data);
@@ -1189,8 +1214,9 @@ gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
     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
      * 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,
                        gpointer data)
 {
+    struct gui_data *inst = (struct gui_data *)data;
+
     if (seldata->length <= 0 ||
        seldata->type != GDK_SELECTION_TYPE_STRING)
        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) {
        *p = inst->pastein_data;
        *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));
     inst->wintitle[lenof(inst->wintitle)-1] = '\0';
     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));
     inst->icontitle[lenof(inst->icontitle)-1] = '\0';
     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)
        return;
     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)
 {
+    struct gui_data *inst = (struct gui_data *)data;
+
     if (!cfg.scrollbar)
        return;
     if (!inst->ignore_sbar)
        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.
      */
 }
 
-void beep(int mode)
+void beep(void *frontend, int mode)
 {
     gdk_beep();
 }
@@ -1303,19 +1338,27 @@ int CharWidth(Context ctx, int uc)
     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)
        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)
 {
-    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);
+    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,
                      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;
-    GdkGC *gc = (GdkGC *)ctx;
 
     /*
      * 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,
             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);
 
@@ -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,
               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;
-    GdkGC *gc = (GdkGC *)ctx;
 
     if (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);
 }
 
-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
@@ -1654,7 +1705,7 @@ void modalfatalbox(char *p, ...)
     exit(1);
 }
 
-char *get_x_display(void)
+char *get_x_display(void *frontend)
 {
     return gdk_get_display();
 }
@@ -1827,6 +1878,7 @@ int main(int argc, char **argv)
 {
     extern int pty_master_fd;         /* declared in pty.c */
     extern void pty_pre_init(void);    /* declared in pty.c */
+    struct gui_data *inst;
 
     pty_pre_init();
 
@@ -1839,8 +1891,9 @@ int main(int argc, char **argv)
        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));
 
     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);
 
     if (cfg.wintitle[0])
-       set_title(cfg.wintitle);
+       set_title(inst, cfg.wintitle);
     else
-       set_title("pterm");
+       set_title(inst, "pterm");
 
     /*
      * Set up the colour map.
      */
-    palette_reset();
+    palette_reset(inst);
 
     inst->area = gtk_drawing_area_new();
     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(inst->window);
 
-    set_window_background();
+    set_window_background(inst);
 
-    inst->textcursor = make_mouse_ptr(GDK_XTERM);
-    inst->rawcursor = make_mouse_ptr(GDK_LEFT_PTR);
-    inst->blankcursor = make_mouse_ptr(-1);
-    make_mouse_ptr(-2);                       /* clean up cursor font */
+    inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
+    inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
+    inst->blankcursor = make_mouse_ptr(inst, -1);
+    make_mouse_ptr(inst, -2);         /* clean up cursor font */
     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->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);
 
index 67addce..fd7a93c 100644 (file)
@@ -68,6 +68,7 @@
 #endif
 
 int pty_master_fd;
+static void *pty_frontend;
 static char pty_name[FILENAME_MAX];
 static int pty_stamped_utmp = 0;
 static int pty_child_pid;
@@ -388,6 +389,7 @@ static char *pty_init(void *frontend, void **backend_handle,
     int slavefd;
     pid_t pid, pgrp;
 
+    pty_frontend = frontend;
     *backend_handle = NULL;           /* we can't sensibly use this, sadly */
 
     pty_term_width = cfg.width;
@@ -414,7 +416,7 @@ static char *pty_init(void *frontend, void **backend_handle,
     if (!cfg.stamp_utmp)
        close(pty_utmp_helper_pipe);   /* just let the child process die */
     else {
-       char *location = get_x_display();
+       char *location = get_x_display(pty_frontend);
        int len = strlen(location)+1, pos = 0;   /* +1 to include NUL */
        while (pos < len) {
            int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
@@ -554,8 +556,10 @@ static void pty_size(void *handle, int width, int height)
 
     size.ws_row = (unsigned short)pty_term_height;
     size.ws_col = (unsigned short)pty_term_width;
-    size.ws_xpixel = (unsigned short) pty_term_width * font_dimension(0);
-    size.ws_ypixel = (unsigned short) pty_term_height * font_dimension(1);
+    size.ws_xpixel = (unsigned short) pty_term_width *
+       font_dimension(pty_frontend, 0);
+    size.ws_ypixel = (unsigned short) pty_term_height *
+       font_dimension(pty_frontend, 1);
     ioctl(pty_master_fd, TIOCSWINSZ, (void *)&size);
     return;
 }
@@ -594,6 +598,11 @@ static void pty_provide_ldisc(void *handle, void *ldisc)
     /* This is a stub. */
 }
 
+static void pty_provide_logctx(void *handle, void *logctx)
+{
+    /* This is a stub. */
+}
+
 static int pty_exitcode(void *handle)
 {
     if (!pty_child_dead)
@@ -613,6 +622,7 @@ Backend pty_backend = {
     pty_sendok,
     pty_ldisc,
     pty_provide_ldisc,
+    pty_provide_logctx,
     pty_unthrottle,
     1
 };
index 0355c94..7b0bb4b 100644 (file)
@@ -31,8 +31,8 @@ unsigned long getticks(void);        /* based on gettimeofday(2) */
 #define BYTE unsigned char
 
 /* Things pty.c needs from pterm.c */
-char *get_x_display(void);
-int font_dimension(int which);        /* 0 for width, 1 for height */
+char *get_x_display(void *frontend);
+int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */
 
 /* Things uxstore.c needs from pterm.c */
 char *app_name;                               /* for doing resource lookups */
index fe3a1ad..5040a24 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -140,7 +140,7 @@ static int CALLBACK LogProc(HWND hwnd, UINT msg,
                            memcpy(p, sel_nl, sizeof(sel_nl));
                            p += sizeof(sel_nl);
                        }
-                       write_aclip(clipdata, size, TRUE);
+                       write_aclip(NULL, clipdata, size, TRUE);
                        sfree(clipdata);
                    }
                    sfree(selitems);
@@ -3749,12 +3749,12 @@ int do_reconfig(HWND hwnd)
     return ret;
 }
 
-void logevent(char *string)
+void logevent(void *frontend, char *string)
 {
     char timebuf[40];
     time_t t;
 
-    log_eventlog(string);
+    log_eventlog(logctx, string);
 
     if (nevents >= negsize) {
        negsize += 64;
@@ -3793,7 +3793,7 @@ void showabout(HWND hwnd)
     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)
 {
     int ret;
@@ -3869,7 +3869,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
  * below the configured 'warn' threshold).
  * 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 msg[] =
@@ -3898,7 +3898,7 @@ void askcipher(char *ciphername, int cs)
  * 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).
  */
-int askappend(char *filename)
+int askappend(void *frontend, char *filename)
 {
     static const char mbtitle[] = "PuTTY Log to File";
     static const char msgtemplate[] =
@@ -3927,6 +3927,13 @@ int askappend(char *filename)
 
 /*
  * 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)
 {
index cda2d1d..e5f2280 100644 (file)
--- a/window.c
+++ b/window.c
@@ -118,7 +118,6 @@ static int caret_x = -1, caret_y = -1;
 static void *ldisc;
 static Backend *back;
 static void *backhandle;
-static Terminal *term;
 
 #define FONT_NORMAL 0
 #define FONT_BOLD 1
@@ -499,7 +498,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
     hwnd = NULL;
 
-    term = term_init();
+    term = term_init(NULL);
+    logctx = log_init(NULL);
+    term_provide_logctx(term, logctx);
 
     cfgtopalette();
 
@@ -608,6 +609,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
        error = back->init((void *)term, &backhandle,
                           cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
+       back->provide_logctx(backhandle, logctx);
        if (error) {
            sprintf(msg, "Unable to open connection to\n"
                    "%.800s\n" "%s", cfg.host, error);
@@ -622,8 +624,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
            title = msg;
        }
        sfree(realhost);
-       set_title(title);
-       set_icon(title);
+       set_title(NULL, 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.
      */
-    logfopen();
+    logfopen(logctx);
 
     /*
      * Finally show the window!
@@ -866,7 +868,7 @@ char *do_select(SOCKET skt, int startup)
 /*
  * 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;
     send_raw_mouse = activate;
@@ -876,7 +878,7 @@ void set_raw_mouse_mode(int activate)
 /*
  * Print a message box and close the connection.
  */
-void connection_fatal(char *fmt, ...)
+void connection_fatal(void *frontend, char *fmt, ...)
 {
     va_list ap;
     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;
 
@@ -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)
  * 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)
        return MBT_SELECT;
@@ -1750,8 +1752,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
 
                if (strcmp(prev_cfg.logfilename, cfg.logfilename) ||
                    prev_cfg.logtype != cfg.logtype) {
-                   logfclose();       /* reset logging */
-                   logfopen();
+                   logfclose(logctx); /* reset logging */
+                   logfopen(logctx);
                }
 
                sfree(logpal);
@@ -1841,7 +1843,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                    init_lvl = 2;
                }
 
-               set_title(cfg.wintitle);
+               set_title(NULL, cfg.wintitle);
                if (IsIconic(hwnd)) {
                    SetWindowText(hwnd,
                                  cfg.win_name_always ? window_name :
@@ -2391,7 +2393,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        break;
       case WM_PALETTECHANGED:
        if ((HWND) wParam != hwnd && pal != NULL) {
-           HDC hdc = get_ctx();
+           HDC hdc = get_ctx(NULL);
            if (hdc) {
                if (RealizePalette(hdc) > 0)
                    UpdateColors(hdc);
@@ -2401,7 +2403,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        break;
       case WM_QUERYNEWPALETTE:
        if (pal != NULL) {
-           HDC hdc = get_ctx();
+           HDC hdc = get_ctx(NULL);
            if (hdc) {
                if (RealizePalette(hdc) > 0)
                    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
  * have one.)
  */
-void sys_cursor(int x, int y)
+void sys_cursor(void *frontend, int x, int y)
 {
     int cx, cy;
 
@@ -3866,7 +3868,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
     return -1;
 }
 
-void request_paste(void)
+void request_paste(void *frontend)
 {
     /*
      * In Windows, pasting is synchronous: we can read the
@@ -3876,7 +3878,7 @@ void request_paste(void)
     term_do_paste(term);
 }
 
-void set_title(char *title)
+void set_title(void *frontend, char *title)
 {
     sfree(window_name);
     window_name = smalloc(1 + strlen(title));
@@ -3885,7 +3887,7 @@ void set_title(char *title)
        SetWindowText(hwnd, title);
 }
 
-void set_icon(char *title)
+void set_icon(void *frontend, char *title)
 {
     sfree(icon_name);
     icon_name = smalloc(1 + strlen(title));
@@ -3894,7 +3896,7 @@ void set_icon(char *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;
 
@@ -3911,7 +3913,7 @@ void set_sbar(int total, int start, int page)
        SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
 }
 
-Context get_ctx(void)
+Context get_ctx(void *frontend)
 {
     HDC hdc;
     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);
 }
 
-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] = {
        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)
        real_palette_set(first[n] + 1, r, g, b);
     if (pal) {
-       HDC hdc = get_ctx();
+       HDC hdc = get_ctx(frontend);
        UnrealizeObject(pal);
        RealizePalette(hdc);
        free_ctx(hdc);
     }
 }
 
-void palette_reset(void)
+void palette_reset(void *frontend)
 {
     int i;
 
@@ -3981,13 +3983,13 @@ void palette_reset(void)
     if (pal) {
        HDC hdc;
        SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry);
-       hdc = get_ctx();
+       hdc = get_ctx(frontend);
        RealizePalette(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;
     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.
  */
-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;
     int len2;
@@ -4182,7 +4184,7 @@ void write_clip(wchar_t * data, int len, int must_deselect)
        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 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
  * window.
  */
-void optimised_move(int to, int from, int lines)
+void optimised_move(void *frontend, int to, int from, int lines)
 {
     RECT r;
     int min, max;
@@ -4315,7 +4317,7 @@ static void flash_window(int mode)
 /*
  * Beep.
  */
-void beep(int mode)
+void beep(void *frontend, int mode)
 {
     if (mode == BELL_DEFAULT) {
        /*
@@ -4356,7 +4358,7 @@ void beep(int mode)
  * Minimise or restore the window in response to a server-side
  * request.
  */
-void set_iconic(int iconic)
+void set_iconic(void *frontend, int iconic)
 {
     if (IsIconic(hwnd)) {
        if (!iconic)
@@ -4370,7 +4372,7 @@ void set_iconic(int iconic)
 /*
  * 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 || 
         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
  * to a server-side request.
  */
-void set_zorder(int top)
+void set_zorder(void *frontend, int top)
 {
     if (cfg.alwaysontop)
        return;                        /* ignore */
@@ -4395,7 +4397,7 @@ void set_zorder(int top)
 /*
  * Refresh the window in response to a server-side request.
  */
-void refresh_window(void)
+void refresh_window(void *frontend)
 {
     InvalidateRect(hwnd, NULL, TRUE);
 }
@@ -4404,7 +4406,7 @@ void refresh_window(void)
  * Maximise or restore the window in response to a server-side
  * request.
  */
-void set_zoomed(int zoomed)
+void set_zoomed(void *frontend, int zoomed)
 {
     if (IsZoomed(hwnd)) {
         if (!zoomed)
@@ -4418,7 +4420,7 @@ void set_zoomed(int zoomed)
 /*
  * Report whether the window is iconic, for terminal reports.
  */
-int is_iconic(void)
+int is_iconic(void *frontend)
 {
     return IsIconic(hwnd);
 }
@@ -4426,7 +4428,7 @@ int is_iconic(void)
 /*
  * 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;
     GetWindowRect(hwnd, &r);
@@ -4437,7 +4439,7 @@ void get_window_pos(int *x, int *y)
 /*
  * 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;
     GetWindowRect(hwnd, &r);
@@ -4448,7 +4450,7 @@ void get_window_pixels(int *x, int *y)
 /*
  * 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;
 }
index 7cadf86..4ea2903 100644 (file)
--- a/winnet.c
+++ b/winnet.c
@@ -833,7 +833,9 @@ void try_send(Actual_Socket s)
                s->pending_error = err;
                return;
            } 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));
            }
        } else {
@@ -972,7 +974,9 @@ int select_result(WPARAM wParam, LPARAM lParam)
        if (ret <= 0) {
            char *str = (ret == 0 ? "Internal networking trouble" :
                         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);
        } else {
            return plug_receive(s->plug, 2, buf, ret);
index 9dcfded..90c0348 100644 (file)
 #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_PARENT "Software\\SimonTatham"
 #define PUTTY_REG_PARENT_CHILD "PuTTY"
@@ -50,6 +57,14 @@ GLOBAL char *help_path;
 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
  * are hundreds of flags defined using the form WM_USER+123 so I've 
  * renumbered this NETEVENT value and the two in window.c