/* log session to file stuff ... */
static FILE *lgfp = NULL;
static void logtraffic(unsigned char c, int logmode);
+static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm);
/*
* Resize a line to make it `cols' columns wide.
{
int c, inbuf_reap;
+ /*
+ * Optionally log the session traffic to a file. Useful for
+ * debugging and possibly also useful for actual logging.
+ */
+ if (cfg.logtype == LGTYP_DEBUG)
+ for (inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) {
+ logtraffic((unsigned char) inbuf[inbuf_reap], LGTYP_DEBUG);
+ }
+
for (inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) {
c = inbuf[inbuf_reap];
- /*
- * Optionally log the session traffic to a file. Useful for
- * debugging and possibly also useful for actual logging.
- */
- 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.
case 4:
case 5:
if ((c & 0xC0) != 0x80) {
- inbuf_reap--; /* This causes the faulting character */
- c = UCSERR; /* to be logged twice - not really a */
- utf_state = 0; /* serious problem. */
+ inbuf_reap--;
+ c = UCSERR;
+ utf_state = 0;
break;
}
utf_char = (utf_char << 6) | (c & 0x3f);
}
}
break;
+ case 'Z': /* BackTab for xterm */
+ compatibility(OTHER);
+ {
+ int i = def(esc_args[0], 1);
+ pos old_curs = curs;
+
+ for(;i>0 && curs.x>0; i--) {
+ do {
+ curs.x--;
+ } while (curs.x >0 && !tabs[curs.x]);
+ }
+ fix_cpos;
+ check_selection(old_curs, curs);
+ }
+ break;
case ANSI('L', '='):
compatibility(OTHER);
use_bce = (esc_args[0] <= 0);
{
pos selpoint;
unsigned long *ldata;
+ int raw_mouse = xterm_mouse && !(cfg.mouse_override && shift);
- if (y < 0)
+ if (y < 0) {
y = 0;
- if (y >= rows)
+ if (a == MA_DRAG && !raw_mouse)
+ term_scroll(0, -1);
+ }
+ if (y >= rows) {
y = rows - 1;
+ if (a == MA_DRAG && !raw_mouse)
+ term_scroll(0, +1);
+ }
if (x < 0) {
if (y > 0) {
x = cols - 1;
if ((ldata[cols] & LATTR_MODE) != LATTR_NORM)
selpoint.x /= 2;
- if (xterm_mouse) {
+ if (raw_mouse) {
int encstate = 0, r, c;
char abuf[16];
static int is_down = 0;
/*
* from_backend(), to get data from the backend for the terminal.
*/
-void from_backend(int is_stderr, char *data, int len)
+int from_backend(int is_stderr, char *data, int len)
{
while (len--) {
if (inbuf_head >= INBUF_SIZE)
term_out();
inbuf[inbuf_head++] = *data++;
}
+
+ /*
+ * We process all stdout/stderr data immediately we receive it,
+ * and don't return until it's all gone. Therefore, there's no
+ * reason at all to return anything other than zero from this
+ * function.
+ *
+ * This is a slightly suboptimal way to deal with SSH2 - in
+ * principle, the window mechanism would allow us to continue
+ * to accept data on forwarded ports and X connections even
+ * while the terminal processing was going slowly - but we
+ * can't do the 100% right thing without moving the terminal
+ * processing into a separate thread, and that might hurt
+ * portability. So we manage stdout buffering the old SSH1 way:
+ * if the terminal processing goes slowly, the whole SSH
+ * connection stops accepting data until it's ready.
+ *
+ * In practice, I can't imagine this causing serious trouble.
+ */
+ return 0;
}
/*
}
}
+void settimstr(char *ta, int no_sec);
+char *subslfcode(char *dest, char *src, char *dstrt);
+char *stpncpy(char *dst, const char *src, size_t maxlen);
+char timdatbuf[20];
+char currlogfilename[FILENAME_MAX];
+
/* open log file append/overwrite mode */
void logfopen(void)
{
char buf[256];
time_t t;
- struct tm *tm;
+ struct tm tm;
char writemod[4];
if (!cfg.logtype)
return;
sprintf(writemod, "wb"); /* default to rewrite */
- lgfp = fopen(cfg.logfilename, "r"); /* file already present? */
+
+ time(&t);
+ tm = *localtime(&t);
+
+ /* substitute special codes in file name */
+ xlatlognam(currlogfilename,cfg.logfilename,cfg.host, &tm);
+
+ lgfp = fopen(currlogfilename, "r"); /* file already present? */
if (lgfp) {
int i;
fclose(lgfp);
- i = askappend(cfg.logfilename);
+ i = askappend(currlogfilename);
if (i == 1)
writemod[0] = 'a'; /* set append mode */
else if (i == 0) { /* cancelled */
}
}
- lgfp = fopen(cfg.logfilename, writemod);
+ lgfp = fopen(currlogfilename, 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);
+ strncat(buf, currlogfilename, 128);
buf[strlen(buf)] = '\0';
logevent(buf);
- /* --- write header line iinto log file */
+ /* --- write header line into log file */
fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp);
- time(&t);
- tm = localtime(&t);
- strftime(buf, 24, "%Y.%m.%d %H:%M:%S", tm);
+ strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
fputs(buf, lgfp);
fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp);
}
lgfp = NULL;
}
}
+
+/*
+ * translate format codes into time/date strings
+ * and insert them into log file name
+ *
+ * "&Y":YYYY "&m":MM "&d":DD "&T":hhmm "&h":<hostname> "&&":&
+ */
+static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) {
+ char buf[10], *bufp;
+ int size;
+ char *ds = d; /* save start pos. */
+ int len = FILENAME_MAX-1;
+
+ while (*s) {
+ /* Let (bufp, len) be the string to append. */
+ bufp = buf; /* don't usually override this */
+ if (*s == '&') {
+ char c;
+ s++;
+ if (*s) switch (c = *s++, tolower(c)) {
+ case 'y':
+ size = strftime(buf, sizeof(buf), "%Y", tm);
+ break;
+ case 'm':
+ size = strftime(buf, sizeof(buf), "%m", tm);
+ break;
+ case 'd':
+ size = strftime(buf, sizeof(buf), "%d", tm);
+ break;
+ case 't':
+ size = strftime(buf, sizeof(buf), "%H%M%S", tm);
+ break;
+ case 'h':
+ bufp = hostname;
+ size = strlen(bufp);
+ break;
+ default:
+ buf[0] = '&';
+ size = 1;
+ if (c != '&')
+ buf[size++] = c;
+ }
+ } else {
+ buf[0] = *s++;
+ size = 1;
+ }
+ if (size > len)
+ size = len;
+ memcpy(d, bufp, size);
+ d += size;
+ len -= size;
+ }
+ *d = '\0';
+}