Allow strip escape sequence characters from log file

The log without escape key stripped is like:

^M[12:47:17] ACRN:\>
^M[12:47:17] ACRN:\>lasdfjklsdjf
^M
^M[12:47:18] Error: Invalid command.
^M[12:47:19] ACRN:\>
^M[12:47:26] ACRN:\>
^M[12:47:26] ACRN:\>sdafkljsdkaljfklsadjflksdjafjsda^H ^H^H...
^M
^M[12:47:31] Error: Invalid command.

After strip escape key, the log is like:

[12:49:18] ACRN:\>
[12:49:19] ACRN:\>
[12:49:19] ACRN:\>ls

[12:49:19] Error: Invalid command.
[12:49:19] ACRN:\>
[12:49:19] ACRN:\>dfaslhj

[12:49:24] Error: Invalid command.

Beside escape key, it also handle backspace key as well.
This commit is contained in:
Yin Fengwei 2021-01-21 10:35:33 +08:00
parent 1079991608
commit c0c21b1814
5 changed files with 101 additions and 18 deletions

View file

@ -24,6 +24,7 @@
void log_open(const char *filename);
void log_write(char c);
void log_writeline(char *l, int max_line_size, bool esc_strip);
void log_close(void);
void log_exit(void);

View file

@ -42,6 +42,7 @@ struct option_t
bool local_echo;
bool timestamp;
const char *log_filename;
bool strip_esc;
const char *map;
};

View file

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "tio/options.h"
#include "tio/print.h"
#include "tio/error.h"
@ -40,7 +41,7 @@ void log_open(const char *filename)
log_error = true;
exit(EXIT_FAILURE);
}
setvbuf(fp, NULL, _IONBF, 0);
setvbuf(fp, NULL, _IOLBF, 0);
}
void log_write(char c)
@ -49,6 +50,75 @@ void log_write(char c)
fputc(c, fp);
}
#define IS_ESC_INTERMEDIATE_CHAR(c) ((c <= 0x2F) && (c >= 0x20))
#define IS_ESC_END_CHAR(c) ((c <= 0x7E) && (c >= 0x30))
#define IS_CSI_END_CHAR(c) ((c <= 0x7E) && (c >= 0x40))
static void scan_ctrl_char(char *buf, int length)
{
int i, j;
size_t len = strnlen(buf, length);
char c;
i = j = 0;
while (i < len) {
c = buf[i++];
if (iscntrl(c)) {
switch (c)
{
case 8: /* backspace */
j--;
break;
case 13: /* \r */
break;
case 27: /* ESC */
c = buf[i++];
if (c == 0x5B) { /* CSI */
c = buf[i++];
while (!IS_CSI_END_CHAR(c)) {
c = buf[i++];
}
} else {
while (!IS_ESC_END_CHAR(c)) {
c = buf[i++];
}
}
break;
default:
buf[j++] = c;
break;
}
} else {
buf[j++] = c;
}
}
buf[j] = '\0';
}
void log_writeline(char *l, int max_line_size, bool esc_strip)
{
char *buf = NULL;
if (fp == NULL)
return;
if (esc_strip) {
buf = strdup(l);
scan_ctrl_char(buf, max_line_size);
fputs(buf, fp);
free(buf);
} else {
buf = l;
fputs(buf, fp);
}
fflush(fp);
}
void log_close(void)
{
if (fp != NULL)

View file

@ -48,6 +48,7 @@ struct option_t option =
false, // No local echo
false, // No timestamp
"", // Log filename
false, // Strip esc charaters from log file
"" // Map string
};
@ -67,6 +68,7 @@ void print_help(char *argv[])
printf(" -t, --timestamp Prefix each new line with a timestamp\n");
printf(" -l, --log <filename> Log to file\n");
printf(" -m, --map <flags> Map special characters\n");
printf(" -S, --strip-esc Strip esc characters from log file\n");
printf(" -v, --version Display version\n");
printf(" -h, --help Display help\n");
printf("\n");
@ -117,6 +119,7 @@ void parse_options(int argc, char *argv[])
{"timestamp", no_argument, 0, 't'},
{"log", required_argument, 0, 'l'},
{"map", required_argument, 0, 'm'},
{"strip-esc", no_argument, 0, 'S'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0 }
@ -126,7 +129,7 @@ void parse_options(int argc, char *argv[])
int option_index = 0;
/* Parse argument using getopt_long */
c = getopt_long(argc, argv, "b:d:f:s:p:o:netl:m:vh", long_options, &option_index);
c = getopt_long(argc, argv, "b:d:f:s:p:o:netl:m:Svh", long_options, &option_index);
/* Detect the end of the options */
if (c == -1)
@ -189,6 +192,10 @@ void parse_options(int argc, char *argv[])
option.map = optarg;
break;
case 'S':
option.strip_esc = true;
break;
case 'v':
printf("tio v%s\n", VERSION);
printf("Copyright (c) 2014-2018 Martin Lund\n");

View file

@ -44,6 +44,8 @@
#include "tio/log.h"
#include "tio/error.h"
#define BUFFER_LEN 4096
#ifdef HAVE_TERMIOS2
extern int setspeed2(int fd, int baudrate);
#endif
@ -60,6 +62,7 @@ static bool map_i_nl_crnl = false;
static bool map_o_cr_nl = false;
static bool map_o_nl_crnl = false;
static bool map_o_del_bs = false;
static char line_buf[BUFFER_LEN];
#define tio_printf(format, args...) \
{ \
@ -616,6 +619,7 @@ int tty_connect(void)
int status;
time_t next_timestamp = 0;
char* now = NULL;
int line_cur = 0;
/* Open tty device */
#ifdef __APPLE__
@ -711,17 +715,7 @@ int tty_connect(void)
{
now = current_time();
fprintf(stdout, ANSI_COLOR_GRAY "[%s] " ANSI_COLOR_RESET, now);
if (option.log)
{
log_write('[');
while (*now != '\0')
{
log_write(*now);
++now;
}
log_write(']');
log_write(' ');
}
line_cur = snprintf(line_buf, BUFFER_LEN, "[%s] " ANSI_COLOR_RESET, now);
next_timestamp = 0;
}
@ -736,17 +730,27 @@ int tty_connect(void)
{
/* Print received tty character to stdout */
print(input_char);
/* Avoid out bound access of line_buf */
if (line_cur < BUFFER_LEN - 1)
line_buf[line_cur++] = input_char;
}
fflush(stdout);
/* Write to log */
if (option.log)
log_write(input_char);
tainted = true;
if (input_char == '\n' && option.timestamp)
if (input_char == '\n' && option.timestamp) {
/* No risk out bound access of line_buf */
line_buf[line_cur] = '\0';
if (option.log && (strlen(line_buf) > 0)) {
bool esc_strip = (option.strip_esc == true);
log_writeline(line_buf, BUFFER_LEN, esc_strip);
}
line_cur = 0;
next_timestamp = time(NULL);
}
} else
{
/* Error reading - device is likely unplugged */