Improved session logging courtesy of Roman Pompejus
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 7 Jan 2001 18:24:59 +0000 (18:24 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 7 Jan 2001 18:24:59 +0000 (18:24 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@846 cda61777-01e9-0310-a592-d414129be87e

putty.h
settings.c
terminal.c
windlg.c
window.c

diff --git a/putty.h b/putty.h
index 033b581..263c045 100644 (file)
--- a/putty.h
+++ b/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);
 
 /*
index b1ada59..5b2b521 100644 (file)
@@ -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;
index 96472d3..e52db03 100644 (file)
@@ -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; }
+}
index 9dab862..b916585 100644 (file)
--- a/windlg.c
+++ b/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;
+}
index f810eba..14ab3d6 100644 (file)
--- a/window.c
+++ b/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' &&
@@ -537,6 +533,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.
      */
     pal = NULL;
@@ -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;