mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Improved session logging courtesy of Roman Pompejus
[originally from svn r846]
This commit is contained in:
parent
947c03869e
commit
3a2a06b1fc
8
putty.h
8
putty.h
@ -78,6 +78,9 @@ GLOBAL int seen_disp_event;
|
||||
|
||||
GLOBAL int session_closed;
|
||||
|
||||
#define LGTYP_NONE 0 /* logmode: no logging */
|
||||
#define LGTYP_ASCII 1 /* logmode: pure ascii */
|
||||
#define LGTYP_DEBUG 2 /* logmode: all chars of taffic */
|
||||
GLOBAL char *logfile;
|
||||
|
||||
/*
|
||||
@ -188,6 +191,8 @@ typedef struct {
|
||||
int fontisbold;
|
||||
int fontheight;
|
||||
int fontcharset;
|
||||
char logfilename[FILENAME_MAX];
|
||||
int logtype;
|
||||
/* Colour options */
|
||||
int try_palette;
|
||||
int bold_colour;
|
||||
@ -283,6 +288,7 @@ void showeventlog (HWND);
|
||||
void showabout (HWND);
|
||||
void verify_ssh_host_key(char *host, int port, char *keytype,
|
||||
char *keystr, char *fingerprint);
|
||||
int askappend(char *filename);
|
||||
void registry_cleanup(void);
|
||||
void force_normal(HWND hwnd);
|
||||
|
||||
@ -315,6 +321,8 @@ void term_blink(int set_cursor);
|
||||
void term_paste(void);
|
||||
void term_nopaste(void);
|
||||
void from_backend(int is_stderr, char *data, int len);
|
||||
void logfopen (void);
|
||||
void logfclose (void);
|
||||
void term_copyall(void);
|
||||
|
||||
/*
|
||||
|
@ -32,6 +32,8 @@ void save_settings (char *section, int do_host, Config *cfg) {
|
||||
if (do_host) {
|
||||
write_setting_s (sesskey, "HostName", cfg->host);
|
||||
write_setting_i (sesskey, "PortNumber", cfg->port);
|
||||
write_setting_s (sesskey, "LogFileName", cfg->logfilename);
|
||||
write_setting_i (sesskey, "LogType", cfg->logtype);
|
||||
p = "raw";
|
||||
for (i = 0; backends[i].name != NULL; i++)
|
||||
if (backends[i].protocol == cfg->protocol) {
|
||||
@ -150,6 +152,9 @@ void load_settings (char *section, int do_host, Config *cfg) {
|
||||
|
||||
gpps (sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
|
||||
gppi (sesskey, "PortNumber", default_port, &cfg->port);
|
||||
gpps (sesskey, "LogFileName", "putty.log",
|
||||
cfg->logfilename, sizeof(cfg->logfilename));
|
||||
gppi (sesskey, "LogType", 0, &cfg->logtype);
|
||||
|
||||
gpps (sesskey, "Protocol", "default", prot, 10);
|
||||
cfg->protocol = default_protocol;
|
||||
|
78
terminal.c
78
terminal.c
@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include "putty.h"
|
||||
|
||||
#define CL_ANSIMIN 0x0001 /* Codes in all ANSI like terminals. */
|
||||
@ -155,6 +156,9 @@ static void erase_lots (int, int, int);
|
||||
static void swap_screen (int);
|
||||
static void update_sbar (void);
|
||||
static void deselect (void);
|
||||
/* log session to file stuff ... */
|
||||
static FILE *lgfp = NULL;
|
||||
static void logtraffic(unsigned char c, int logmode);
|
||||
|
||||
/*
|
||||
* Set up power-on settings for the terminal.
|
||||
@ -780,11 +784,8 @@ static int beep_overload = 0;
|
||||
* Optionally log the session traffic to a file. Useful for
|
||||
* debugging and possibly also useful for actual logging.
|
||||
*/
|
||||
if (logfile) {
|
||||
static FILE *fp = NULL;
|
||||
if (!fp) fp = fopen(logfile, "wb");
|
||||
if (fp) fputc (c, fp);
|
||||
}
|
||||
logtraffic((unsigned char)c, LGTYP_DEBUG);
|
||||
|
||||
/* Note only VT220+ are 8-bit VT102 is seven bit, it shouldn't even
|
||||
* be able to display 8-bit characters, but I'll let that go 'cause
|
||||
* of i18n.
|
||||
@ -856,6 +857,7 @@ static int beep_overload = 0;
|
||||
fix_cpos;
|
||||
seen_disp_event = TRUE;
|
||||
paste_hold = 0;
|
||||
logtraffic((unsigned char)c,LGTYP_ASCII);
|
||||
break;
|
||||
case '\013':
|
||||
case '\014':
|
||||
@ -871,6 +873,7 @@ static int beep_overload = 0;
|
||||
wrapnext = FALSE;
|
||||
seen_disp_event = 1;
|
||||
paste_hold = 0;
|
||||
logtraffic((unsigned char)c,LGTYP_ASCII);
|
||||
break;
|
||||
case '\t':
|
||||
{
|
||||
@ -946,8 +949,10 @@ static int beep_overload = 0;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
*cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr |
|
||||
*cpos = xlat_tty2scr((unsigned char)c) | curr_attr |
|
||||
(c <= 0x7F ? cset_attr[cset] : ATTR_ASCII);
|
||||
logtraffic((unsigned char)c, LGTYP_ASCII);
|
||||
cpos++;
|
||||
break;
|
||||
}
|
||||
curs_x++;
|
||||
@ -2230,3 +2235,64 @@ void from_backend(int is_stderr, char *data, int len) {
|
||||
inbuf[inbuf_head++] = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Log session traffic.
|
||||
*/
|
||||
void logtraffic(unsigned char c, int logmode) {
|
||||
if (cfg.logtype > 0) {
|
||||
if (cfg.logtype == logmode) {
|
||||
/* deferred open file from pgm start? */
|
||||
if (!lgfp) logfopen();
|
||||
if (lgfp) fputc (c, lgfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* open log file append/overwrite mode */
|
||||
void logfopen(void) {
|
||||
char buf[256];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
char writemod[4];
|
||||
|
||||
if (!cfg.logtype)
|
||||
return;
|
||||
sprintf (writemod, "wb"); /* default to rewrite */
|
||||
lgfp = fopen(cfg.logfilename, "r"); /* file already present? */
|
||||
if (lgfp) {
|
||||
int i;
|
||||
fclose(lgfp);
|
||||
i = askappend(cfg.logfilename);
|
||||
if (i == 1)
|
||||
writemod[0] = 'a'; /* set append mode */
|
||||
else if (i == 0) { /* cancelled */
|
||||
lgfp = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lgfp = fopen(cfg.logfilename, writemod);
|
||||
if (lgfp) { /* enter into event log */
|
||||
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" : "<ukwn>") );
|
||||
/* Make sure we do not exceed the output buffer size */
|
||||
strncat (buf, cfg.logfilename, 128);
|
||||
buf[strlen(buf)] = '\0';
|
||||
logevent(buf);
|
||||
|
||||
/* --- write header line iinto log file */
|
||||
fputs ("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp);
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", tm);
|
||||
fputs (buf, lgfp);
|
||||
fputs (" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp);
|
||||
}
|
||||
}
|
||||
|
||||
void logfclose (void) {
|
||||
if (lgfp) { fclose(lgfp); lgfp = NULL; }
|
||||
}
|
||||
|
91
windlg.c
91
windlg.c
@ -230,6 +230,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
|
||||
terminalpanelstart,
|
||||
IDC_TITLE_TERMINAL,
|
||||
IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
|
||||
IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
|
||||
IDC_WRAPMODE,
|
||||
IDC_DECOM,
|
||||
IDC_LFHASCR,
|
||||
@ -237,6 +238,13 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
|
||||
IDC_BCE,
|
||||
IDC_BLINKTEXT,
|
||||
IDC_LDISCTERM,
|
||||
IDC_LSTATSTATIC,
|
||||
IDC_LSTATOFF,
|
||||
IDC_LSTATASCII,
|
||||
IDC_LSTATRAW,
|
||||
IDC_LGFSTATIC,
|
||||
IDC_LGFEDIT,
|
||||
IDC_LGFBUTTON,
|
||||
terminalpanelend,
|
||||
|
||||
windowpanelstart,
|
||||
@ -473,6 +481,11 @@ static void init_dlg_ctrls(HWND hwnd) {
|
||||
SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
|
||||
SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
|
||||
SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
|
||||
SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
|
||||
CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
|
||||
cfg.logtype == 0 ? IDC_LSTATOFF :
|
||||
cfg.logtype == 1 ? IDC_LSTATASCII :
|
||||
IDC_LSTATRAW);
|
||||
{
|
||||
char *p = cfg.environmt;
|
||||
while (*p) {
|
||||
@ -704,7 +717,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
hsession = treeview_insert(&tvfaff, 0, "Session");
|
||||
}
|
||||
|
||||
/* The Terminal panel. Accelerators used: [acgo] &dlbenu */
|
||||
/* The Terminal panel. Accelerators used: [acgo] &dflbenuw */
|
||||
{
|
||||
struct ctlpos cp;
|
||||
ctlposinit(&cp, hwnd, 80, 3, 13);
|
||||
@ -721,6 +734,18 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
|
||||
endbox(&cp);
|
||||
|
||||
beginbox(&cp, "Control session logging",
|
||||
IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
|
||||
radiobig(&cp,
|
||||
"Session logging:", IDC_LSTATSTATIC,
|
||||
"Logging turned &off completely", IDC_LSTATOFF,
|
||||
"Log printable output only", IDC_LSTATASCII,
|
||||
"Log all session output", IDC_LSTATRAW, NULL);
|
||||
editbutton(&cp, "Log &file name:",
|
||||
IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
|
||||
IDC_LGFBUTTON);
|
||||
endbox(&cp);
|
||||
|
||||
treeview_insert(&tvfaff, 0, "Terminal");
|
||||
}
|
||||
|
||||
@ -1428,6 +1453,43 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
|
||||
sizeof(cfg.termtype)-1);
|
||||
break;
|
||||
case IDC_LGFEDIT:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
|
||||
sizeof(cfg.logfilename)-1);
|
||||
break;
|
||||
case IDC_LGFBUTTON:
|
||||
memset(&of, 0, sizeof(of));
|
||||
#ifdef OPENFILENAME_SIZE_VERSION_400
|
||||
of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
|
||||
#else
|
||||
of.lStructSize = sizeof(of);
|
||||
#endif
|
||||
of.hwndOwner = hwnd;
|
||||
of.lpstrFilter = "All Files\0*\0\0\0";
|
||||
of.lpstrCustomFilter = NULL;
|
||||
of.nFilterIndex = 1;
|
||||
of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
|
||||
of.nMaxFile = sizeof(filename);
|
||||
of.lpstrFileTitle = NULL;
|
||||
of.lpstrInitialDir = NULL;
|
||||
of.lpstrTitle = "Select session log file";
|
||||
of.Flags = 0;
|
||||
if (GetSaveFileName(&of)) {
|
||||
strcpy(cfg.keyfile, filename);
|
||||
SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
|
||||
}
|
||||
break;
|
||||
case IDC_LSTATOFF:
|
||||
case IDC_LSTATASCII:
|
||||
case IDC_LSTATRAW:
|
||||
if (HIWORD(wParam) == BN_CLICKED ||
|
||||
HIWORD(wParam) == BN_DOUBLECLICKED) {
|
||||
if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
|
||||
if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
|
||||
if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
|
||||
}
|
||||
break;
|
||||
case IDC_TSEDIT:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
|
||||
@ -1891,3 +1953,30 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
|
||||
store_host_key(host, port, keytype, keystr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
static const char mbtitle[] = "PuTTY Log to File";
|
||||
static const char msgtemplate[] =
|
||||
"The session log file \"%.*s\" already exists.\n"
|
||||
"You can overwrite it with a new session log,\n"
|
||||
"append your session log to the end of it,\n"
|
||||
"or disable session logging for this session.\n"
|
||||
"Hit Yes to wipe the file, No to append to it,\n"
|
||||
"or Cancel to disable logging.";
|
||||
char message[sizeof(msgtemplate) + FILENAME_MAX];
|
||||
int mbret;
|
||||
sprintf(message, msgtemplate, FILENAME_MAX, filename);
|
||||
|
||||
mbret = MessageBox(NULL, message, mbtitle,
|
||||
MB_ICONQUESTION | MB_YESNOCANCEL);
|
||||
if (mbret == IDYES)
|
||||
return 2;
|
||||
else if (mbret == IDNO)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
24
window.c
24
window.c
@ -149,6 +149,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
|
||||
|
||||
default_protocol = DEFAULT_PROTOCOL;
|
||||
default_port = DEFAULT_PORT;
|
||||
cfg.logtype = LGTYP_NONE;
|
||||
|
||||
do_defaults(NULL, &cfg);
|
||||
|
||||
@ -169,11 +170,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
|
||||
tolower(p[2]) == 'h') {
|
||||
default_protocol = cfg.protocol = PROT_SSH;
|
||||
default_port = cfg.port = 22;
|
||||
} else if (q == p + 3 &&
|
||||
tolower(p[0]) == 'l' &&
|
||||
tolower(p[1]) == 'o' &&
|
||||
tolower(p[2]) == 'g') {
|
||||
logfile = "putty.log";
|
||||
} else if (q == p + 7 &&
|
||||
tolower(p[0]) == 'c' &&
|
||||
tolower(p[1]) == 'l' &&
|
||||
@ -536,6 +532,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
|
||||
*/
|
||||
ShowWindow (hwnd, show);
|
||||
|
||||
/*
|
||||
* Open the initial log file if there is one.
|
||||
*/
|
||||
logfopen();
|
||||
|
||||
/*
|
||||
* Set the palette up.
|
||||
*/
|
||||
@ -1171,14 +1172,27 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
|
||||
case IDM_RECONF:
|
||||
{
|
||||
int prev_alwaysontop = cfg.alwaysontop;
|
||||
char oldlogfile[FILENAME_MAX];
|
||||
int oldlogtype;
|
||||
int need_setwpos = FALSE;
|
||||
int old_fwidth, old_fheight;
|
||||
|
||||
strcpy(oldlogfile, cfg.logfilename);
|
||||
oldlogtype = cfg.logtype;
|
||||
cfg.width = cols;
|
||||
cfg.height = rows;
|
||||
old_fwidth = font_width;
|
||||
old_fheight = font_height;
|
||||
|
||||
if (!do_reconfig(hwnd))
|
||||
break;
|
||||
|
||||
if (strcmp(oldlogfile, cfg.logfilename) ||
|
||||
oldlogtype != cfg.logtype) {
|
||||
logfclose(); /* reset logging */
|
||||
logfopen();
|
||||
}
|
||||
|
||||
just_reconfigged = TRUE;
|
||||
{
|
||||
int i;
|
||||
|
Loading…
Reference in New Issue
Block a user