X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/88693305e606f8fedfad64bccf545fee16eda6f0..3d88e64dfcf5dc0fd361ce0c504c67a9196ce44c:/logging.c diff --git a/logging.c b/logging.c index 76dcb950..d526474e 100644 --- a/logging.c +++ b/logging.c @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -10,46 +8,76 @@ #include "putty.h" /* log session to file stuff ... */ -static FILE *lgfp = NULL; -static char timdatbuf[20]; -static char currlogfilename[FILENAME_MAX]; +struct LogContext { + FILE *lgfp; + Filename currlogfilename; + void *frontend; + Config cfg; +}; -static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm); +static void xlatlognam(Filename *d, Filename 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) { - if (cfg.logtype > 0) { - if (cfg.logtype == logmode) { + struct LogContext *ctx = (struct LogContext *)handle; + if (ctx->cfg.logtype > 0) { + if (ctx->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); } } } /* + * Log an Event Log entry. Used in SSH packet logging mode; this is + * also as convenient a place as any to put the output of Event Log + * entries to stderr when a command-line tool is in verbose mode. + * (In particular, this is a better place to put it than in the + * front ends, because it only has to be done once for all + * platforms. Platforms which don't have a meaningful stderr can + * just avoid defining FLAG_STDERR. + */ +void log_eventlog(void *handle, char *event) +{ + struct LogContext *ctx = (struct LogContext *)handle; + if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { + fprintf(stderr, "%s\n", event); + fflush(stderr); + } + if (ctx->cfg.logtype != LGTYP_PACKETS) + return; + if (!ctx->lgfp) + logfopen(ctx); + if (ctx->lgfp) + fprintf(ctx->lgfp, "Event Log: %s\r\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) { - int i, j, c; + struct LogContext *ctx = (struct LogContext *)handle; + int i, j; char dumpdata[80], smalldata[5]; - if (cfg.logtype != LGTYP_PACKETS) + if (ctx->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)\r\n", direction == PKT_INCOMING ? "Incoming" : "Outgoing", type, type, texttype); for (i = 0; i < len; i += 16) { - sprintf(dumpdata, " %08x%*s\n", i, 1+3*16+2+16, ""); + sprintf(dumpdata, " %08x%*s\r\n", i, 1+3*16+2+16, ""); for (j = 0; j < 16 && i+j < len; j++) { int c = ((unsigned char *)data)[i+j]; sprintf(smalldata, "%02x", c); @@ -57,22 +85,27 @@ void log_packet(int direction, int type, char *texttype, void *data, int len) dumpdata[10+2+3*j+1] = smalldata[1]; dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.'); } - strcpy(dumpdata + 10+1+3*16+2+j, "\n"); - fputs(dumpdata, lgfp); + strcpy(dumpdata + 10+1+3*16+2+j, "\r\n"); + 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]; - if (!cfg.logtype) + /* Prevent repeat calls */ + if (ctx->lgfp) + return; + + if (!ctx->cfg.logtype) return; sprintf(writemod, "wb"); /* default to rewrite */ @@ -80,60 +113,108 @@ void logfopen(void) tm = *localtime(&t); /* substitute special codes in file name */ - xlatlognam(currlogfilename,cfg.logfilename,cfg.host, &tm); + xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm); - lgfp = fopen(currlogfilename, "r"); /* file already present? */ - if (lgfp) { + ctx->lgfp = f_open(ctx->currlogfilename, "r"); /* file already present? */ + if (ctx->lgfp) { int i; - fclose(lgfp); - i = askappend(currlogfilename); + fclose(ctx->lgfp); + if (ctx->cfg.logxfovr != LGXF_ASK) { + i = ((ctx->cfg.logxfovr == LGXF_OVR) ? 2 : 1); + } else + i = askappend(ctx->frontend, ctx->currlogfilename); if (i == 1) writemod[0] = 'a'; /* set append mode */ else if (i == 0) { /* cancelled */ - lgfp = NULL; - cfg.logtype = 0; /* disable logging */ + ctx->lgfp = NULL; + ctx->cfg.logtype = 0; /* disable logging */ return; } } - lgfp = fopen(currlogfilename, writemod); - if (lgfp) { /* enter into event log */ - sprintf(buf, "%s session log (%s mode) to file : ", + ctx->lgfp = f_open(ctx->currlogfilename, writemod); + if (ctx->lgfp) { /* enter into event log */ + /* --- write header line into log file */ + fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", ctx->lgfp); + strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); + fputs(buf, ctx->lgfp); + fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", ctx->lgfp); + + sprintf(buf, "%s session log (%s mode) to file: ", (writemod[0] == 'a') ? "Appending" : "Writing new", - (cfg.logtype == LGTYP_ASCII ? "ASCII" : - cfg.logtype == LGTYP_DEBUG ? "raw" : "")); + (ctx->cfg.logtype == LGTYP_ASCII ? "ASCII" : + ctx->cfg.logtype == LGTYP_DEBUG ? "raw" : + ctx->cfg.logtype == LGTYP_PACKETS ? "SSH packets" : "")); /* Make sure we do not exceed the output buffer size */ - strncat(buf, currlogfilename, 128); + strncat(buf, filename_to_str(&ctx->currlogfilename), 128); buf[strlen(buf)] = '\0'; - logevent(buf); - - /* --- write header line into log file */ - fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp); - strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); - fputs(buf, lgfp); - fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp); + 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, Config *cfg) +{ + struct LogContext *ctx = snew(struct LogContext); + ctx->lgfp = NULL; + ctx->frontend = frontend; + ctx->cfg = *cfg; /* STRUCTURE COPY */ + return ctx; +} + +void log_free(void *handle) +{ + struct LogContext *ctx = (struct LogContext *)handle; + + logfclose(ctx); + sfree(ctx); +} + +void log_reconfig(void *handle, Config *cfg) +{ + struct LogContext *ctx = (struct LogContext *)handle; + int reset_logging; + + if (!filename_equal(ctx->cfg.logfilename, cfg->logfilename) || + ctx->cfg.logtype != cfg->logtype) + reset_logging = TRUE; + else + reset_logging = FALSE; + + if (reset_logging) + logfclose(ctx); + + ctx->cfg = *cfg; /* STRUCTURE COPY */ + + if (reset_logging) + logfopen(ctx); +} + /* * translate format codes into time/date strings * and insert them into log file name * * "&Y":YYYY "&m":MM "&d":DD "&T":hhmm "&h": "&&":& */ -static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { +static void xlatlognam(Filename *dest, Filename src, + char *hostname, struct tm *tm) { char buf[10], *bufp; int size; - char *ds = d; /* save start pos. */ - int len = FILENAME_MAX-1; + char buffer[FILENAME_MAX]; + int len = sizeof(buffer)-1; + char *d; + const char *s; + + d = buffer; + s = filename_to_str(&src); while (*s) { /* Let (bufp, len) be the string to append. */ @@ -141,6 +222,7 @@ static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { if (*s == '&') { char c; s++; + size = 0; if (*s) switch (c = *s++, tolower(c)) { case 'y': size = strftime(buf, sizeof(buf), "%Y", tm); @@ -175,4 +257,6 @@ static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { len -= size; } *d = '\0'; + + *dest = filename_from_str(buffer); }