X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/fabd1805a8f429ca83b4271aabd1206ac3537ebb..aca589d972c5c12706d57322e89f9dec2b2a3a00:/logging.c diff --git a/logging.c b/logging.c index 652eb9df..f1c42cde 100644 --- a/logging.c +++ b/logging.c @@ -10,12 +10,12 @@ /* log session to file stuff ... */ struct LogContext { FILE *lgfp; - char currlogfilename[FILENAME_MAX]; + 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. @@ -35,6 +35,16 @@ void logtraffic(void *handle, unsigned char c, int logmode) } /* + * Flush any open log file. + */ +void logflush(void *handle) { + struct LogContext *ctx = (struct LogContext *)handle; + if (ctx->cfg.logtype > 0) + if (ctx->lgfp) + fflush(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. @@ -43,7 +53,7 @@ void logtraffic(void *handle, unsigned char c, int logmode) * platforms. Platforms which don't have a meaningful stderr can * just avoid defining FLAG_STDERR. */ -void log_eventlog(void *handle, char *event) +void log_eventlog(void *handle, const char *event) { struct LogContext *ctx = (struct LogContext *)handle; if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { @@ -60,12 +70,14 @@ void log_eventlog(void *handle, char *event) /* * Log an SSH packet. + * If n_blanks != 0, blank or omit some parts. + * Set of blanking areas must be in increasing order. */ void log_packet(void *handle, int direction, int type, - char *texttype, void *data, int len) + char *texttype, void *data, int len, + int n_blanks, const struct logblank_t *blanks) { struct LogContext *ctx = (struct LogContext *)handle; - int i, j; char dumpdata[80], smalldata[5]; if (ctx->cfg.logtype != LGTYP_PACKETS) @@ -73,21 +85,81 @@ void log_packet(void *handle, int direction, int type, if (!ctx->lgfp) logfopen(ctx); if (ctx->lgfp) { + int p = 0, b = 0, omitted = 0; + int output_pos = 0; /* NZ if pending output in dumpdata */ + + /* Packet header. */ 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\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); - dumpdata[10+2+3*j] = smalldata[0]; - dumpdata[10+2+3*j+1] = smalldata[1]; - dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.'); + + /* + * Output a hex/ASCII dump of the packet body, blanking/omitting + * parts as specified. + */ + while (p < len) { + int blktype; + + /* Move to a current entry in the blanking array. */ + while ((b < n_blanks) && + (p >= blanks[b].offset + blanks[b].len)) + b++; + /* Work out what type of blanking to apply to + * this byte. */ + blktype = PKTLOG_EMIT; /* default */ + if ((b < n_blanks) && + (p >= blanks[b].offset) && + (p < blanks[b].offset + blanks[b].len)) + blktype = blanks[b].type; + + /* If we're about to stop omitting, it's time to say how + * much we omitted. */ + if ((blktype != PKTLOG_OMIT) && omitted) { + fprintf(ctx->lgfp, " (%d byte%s omitted)\r\n", + omitted, (omitted==1?"":"s")); + omitted = 0; } - strcpy(dumpdata + 10+1+3*16+2+j, "\r\n"); - fputs(dumpdata, ctx->lgfp); + + /* (Re-)initialise dumpdata as necessary + * (start of row, or if we've just stopped omitting) */ + if (!output_pos && !omitted) + sprintf(dumpdata, " %08x%*s\r\n", p-(p%16), 1+3*16+2+16, ""); + + /* Deal with the current byte. */ + if (blktype == PKTLOG_OMIT) { + omitted++; + } else { + int c; + if (blktype == PKTLOG_BLANK) { + c = 'X'; + sprintf(smalldata, "XX"); + } else { /* PKTLOG_EMIT */ + c = ((unsigned char *)data)[p]; + sprintf(smalldata, "%02x", c); + } + dumpdata[10+2+3*(p%16)] = smalldata[0]; + dumpdata[10+2+3*(p%16)+1] = smalldata[1]; + dumpdata[10+1+3*16+2+(p%16)] = (isprint(c) ? c : '.'); + output_pos = (p%16) + 1; + } + + p++; + + /* Flush row if necessary */ + if (((p % 16) == 0) || (p == len) || omitted) { + if (output_pos) { + strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n"); + fputs(dumpdata, ctx->lgfp); + output_pos = 0; + } + } + } + + /* Tidy up */ + if (omitted) + fprintf(ctx->lgfp, " (%d byte%s omitted)\r\n", + omitted, (omitted==1?"":"s")); fflush(ctx->lgfp); } } @@ -97,7 +169,6 @@ void logfopen(void *handle) { struct LogContext *ctx = (struct LogContext *)handle; char buf[256]; - time_t t; struct tm tm; char writemod[4]; @@ -109,13 +180,12 @@ void logfopen(void *handle) return; sprintf(writemod, "wb"); /* default to rewrite */ - time(&t); - tm = *localtime(&t); + tm = ltime(); /* substitute special codes in file name */ - xlatlognam(ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm); + xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm); - ctx->lgfp = fopen(ctx->currlogfilename, "r"); /* file already present? */ + ctx->lgfp = f_open(ctx->currlogfilename, "r"); /* file already present? */ if (ctx->lgfp) { int i; fclose(ctx->lgfp); @@ -132,7 +202,7 @@ void logfopen(void *handle) } } - ctx->lgfp = fopen(ctx->currlogfilename, writemod); + 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); @@ -146,7 +216,7 @@ void logfopen(void *handle) 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, ctx->currlogfilename, 128); + strncat(buf, filename_to_str(&ctx->currlogfilename), 128); buf[strlen(buf)] = '\0'; logevent(ctx->frontend, buf); } @@ -163,7 +233,7 @@ void logfclose(void *handle) void *log_init(void *frontend, Config *cfg) { - struct LogContext *ctx = smalloc(sizeof(struct LogContext)); + struct LogContext *ctx = snew(struct LogContext); ctx->lgfp = NULL; ctx->frontend = frontend; ctx->cfg = *cfg; /* STRUCTURE COPY */ @@ -183,7 +253,7 @@ void log_reconfig(void *handle, Config *cfg) struct LogContext *ctx = (struct LogContext *)handle; int reset_logging; - if (strcmp(ctx->cfg.logfilename, cfg->logfilename) || + if (!filename_equal(ctx->cfg.logfilename, cfg->logfilename) || ctx->cfg.logtype != cfg->logtype) reset_logging = TRUE; else @@ -204,10 +274,17 @@ void log_reconfig(void *handle, Config *cfg) * * "&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; - 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. */ @@ -250,4 +327,6 @@ static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { len -= size; } *d = '\0'; + + *dest = filename_from_str(buffer); }