X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/919baedb34e9f6e351d70820529398181d8d0ea6..2ff340bdd3941537211af374feaa6023a20529be:/logging.c diff --git a/logging.c b/logging.c index a54b167f..7c9b1287 100644 --- a/logging.c +++ b/logging.c @@ -1,3 +1,7 @@ +/* + * Session logging. + */ + #include #include #include @@ -10,7 +14,7 @@ /* log session to file stuff ... */ struct LogContext { FILE *lgfp; - enum { CLOSED, OPENING, OPEN, ERROR } state; + enum { L_CLOSED, L_OPENING, L_OPEN, L_ERROR } state; bufchain queue; Filename currlogfilename; void *frontend; @@ -28,19 +32,25 @@ static void xlatlognam(Filename *d, Filename s, char *hostname, struct tm *tm); static void logwrite(struct LogContext *ctx, void *data, int len) { /* - * In state CLOSED, we call logfopen, which will set the state - * to one of OPENING, OPEN or ERROR. Hence we process all of - * those three _after_ processing CLOSED. + * In state L_CLOSED, we call logfopen, which will set the state + * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of + * those three _after_ processing L_CLOSED. */ - if (ctx->state == CLOSED) + if (ctx->state == L_CLOSED) logfopen(ctx); - if (ctx->state == OPENING) { + if (ctx->state == L_OPENING) { bufchain_add(&ctx->queue, data, len); - } else if (ctx->state == OPEN) { + } else if (ctx->state == L_OPEN) { assert(ctx->lgfp); - fwrite(data, 1, len, ctx->lgfp); - } /* else ERROR, so ignore the write */ + if (fwrite(data, 1, len, ctx->lgfp) < len) { + logfclose(ctx); + ctx->state = L_ERROR; + /* Log state is L_ERROR so this won't cause a loop */ + logevent(ctx->frontend, + "Disabled writing session log due to error while writing"); + } + } /* else L_ERROR, so ignore the write */ } /* @@ -66,7 +76,7 @@ static void logprintf(struct LogContext *ctx, const char *fmt, ...) void logflush(void *handle) { struct LogContext *ctx = (struct LogContext *)handle; if (ctx->cfg.logtype > 0) - if (ctx->state == OPEN) + if (ctx->state == L_OPEN) fflush(ctx->lgfp); } @@ -78,17 +88,17 @@ static void logfopen_callback(void *handle, int mode) const char *fmode; if (mode == 0) { - ctx->state = ERROR; /* disable logging */ + ctx->state = L_ERROR; /* disable logging */ } else { - fmode = (mode == 1 ? "a" : "w"); - ctx->lgfp = f_open(ctx->currlogfilename, fmode); + fmode = (mode == 1 ? "ab" : "wb"); + ctx->lgfp = f_open(ctx->currlogfilename, fmode, FALSE); if (ctx->lgfp) - ctx->state = OPEN; + ctx->state = L_OPEN; else - ctx->state = ERROR; + ctx->state = L_ERROR; } - if (ctx->state == OPEN) { + if (ctx->state == L_OPEN) { /* Write header line into log file. */ tm = ltime(); strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); @@ -97,11 +107,13 @@ static void logfopen_callback(void *handle, int mode) } event = dupprintf("%s session log (%s mode) to file: %s", - (mode == 0 ? "Disabled writing" : - mode == 1 ? "Appending" : "Writing new"), + ctx->state == L_ERROR ? + (mode == 0 ? "Disabled writing" : "Error writing") : + (mode == 1 ? "Appending" : "Writing new"), (ctx->cfg.logtype == LGTYP_ASCII ? "ASCII" : ctx->cfg.logtype == LGTYP_DEBUG ? "raw" : ctx->cfg.logtype == LGTYP_PACKETS ? "SSH packets" : + ctx->cfg.logtype == LGTYP_SSHRAW ? "SSH raw data" : "unknown"), filename_to_str(&ctx->currlogfilename)); logevent(ctx->frontend, event); @@ -111,7 +123,7 @@ static void logfopen_callback(void *handle, int mode) * Having either succeeded or failed in opening the log file, * we should write any queued data out. */ - assert(ctx->state != OPENING); /* make _sure_ it won't be requeued */ + assert(ctx->state != L_OPENING); /* make _sure_ it won't be requeued */ while (bufchain_size(&ctx->queue)) { void *data; int len; @@ -133,7 +145,7 @@ void logfopen(void *handle) int mode; /* Prevent repeat calls */ - if (ctx->state != CLOSED) + if (ctx->state != L_CLOSED) return; if (!ctx->cfg.logtype) @@ -144,7 +156,7 @@ void logfopen(void *handle) /* substitute special codes in file name */ xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm); - ctx->lgfp = f_open(ctx->currlogfilename, "r"); /* file already present? */ + ctx->lgfp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */ if (ctx->lgfp) { fclose(ctx->lgfp); if (ctx->cfg.logxfovr != LGXF_ASK) { @@ -156,7 +168,7 @@ void logfopen(void *handle) mode = 2; /* create == overwrite */ if (mode < 0) - ctx->state = OPENING; + ctx->state = L_OPENING; else logfopen_callback(ctx, mode); /* open the file */ } @@ -168,7 +180,7 @@ void logfclose(void *handle) fclose(ctx->lgfp); ctx->lgfp = NULL; } - ctx->state = CLOSED; + ctx->state = L_CLOSED; } /* @@ -199,9 +211,14 @@ void log_eventlog(void *handle, const char *event) fprintf(stderr, "%s\n", event); fflush(stderr); } - if (ctx->cfg.logtype != LGTYP_PACKETS) + /* If we don't have a context yet (eg winnet.c init) then skip entirely */ + if (!ctx) + return; + if (ctx->cfg.logtype != LGTYP_PACKETS && + ctx->cfg.logtype != LGTYP_SSHRAW) return; logprintf(ctx, "Event Log: %s\r\n", event); + logflush(ctx); } /* @@ -210,21 +227,34 @@ void log_eventlog(void *handle, const char *event) * Set of blanking areas must be in increasing order. */ void log_packet(void *handle, int direction, int type, - char *texttype, void *data, int len, - int n_blanks, const struct logblank_t *blanks) + char *texttype, const void *data, int len, + int n_blanks, const struct logblank_t *blanks, + const unsigned long *seq) { struct LogContext *ctx = (struct LogContext *)handle; char dumpdata[80], smalldata[5]; int p = 0, b = 0, omitted = 0; int output_pos = 0; /* NZ if pending output in dumpdata */ - if (ctx->cfg.logtype != LGTYP_PACKETS) + if (!(ctx->cfg.logtype == LGTYP_SSHRAW || + (ctx->cfg.logtype == LGTYP_PACKETS && texttype))) return; /* Packet header. */ - logprintf(ctx, "%s packet type %d / 0x%02x (%s)\r\n", - direction == PKT_INCOMING ? "Incoming" : "Outgoing", - type, type, texttype); + if (texttype) { + if (seq) { + logprintf(ctx, "%s packet #0x%lx, type %d / 0x%02x (%s)\r\n", + direction == PKT_INCOMING ? "Incoming" : "Outgoing", + *seq, type, type, texttype); + } else { + logprintf(ctx, "%s packet type %d / 0x%02x (%s)\r\n", + direction == PKT_INCOMING ? "Incoming" : "Outgoing", + type, type, texttype); + } + } else { + logprintf(ctx, "%s raw data\r\n", + direction == PKT_INCOMING ? "Incoming" : "Outgoing"); + } /* * Output a hex/ASCII dump of the packet body, blanking/omitting @@ -300,7 +330,7 @@ void *log_init(void *frontend, Config *cfg) { struct LogContext *ctx = snew(struct LogContext); ctx->lgfp = NULL; - ctx->state = CLOSED; + ctx->state = L_CLOSED; ctx->frontend = frontend; ctx->cfg = *cfg; /* STRUCTURE COPY */ bufchain_init(&ctx->queue); @@ -340,7 +370,7 @@ void log_reconfig(void *handle, Config *cfg) * translate format codes into time/date strings * and insert them into log file name * - * "&Y":YYYY "&m":MM "&d":DD "&T":hhmm "&h": "&&":& + * "&Y":YYYY "&m":MM "&d":DD "&T":hhmmss "&h": "&&":& */ static void xlatlognam(Filename *dest, Filename src, char *hostname, struct tm *tm) { @@ -361,7 +391,7 @@ static void xlatlognam(Filename *dest, Filename src, char c; s++; size = 0; - if (*s) switch (c = *s++, tolower(c)) { + if (*s) switch (c = *s++, tolower((unsigned char)c)) { case 'y': size = strftime(buf, sizeof(buf), "%Y", tm); break;