Add special character map feature

Add a --map option which allows to map special characters, in particular CR and
NL characters which are used in various combinations on varios platforms.
This commit is contained in:
Martin Lund 2017-11-05 20:52:12 +01:00
parent 078bb6213d
commit b2aafd696b
6 changed files with 77 additions and 2 deletions

1
README
View file

@ -30,6 +30,7 @@
-o, --output-delay <ms> Output delay (default: 0) -o, --output-delay <ms> Output delay (default: 0)
-n, --no-autoconnect Disable automatic connect -n, --no-autoconnect Disable automatic connect
-l, --log <filename> Log to file -l, --log <filename> Log to file
-m, --map <flags> Map special characters
-v, --version Display version -v, --version Display version
-h, --help Display help -h, --help Display help

View file

@ -55,6 +55,28 @@ option is provided, tio will exit if the device is not present or an established
.BR \-l ", " "\-\-log " \fI<filename> .BR \-l ", " "\-\-log " \fI<filename>
Log to file. Log to file.
.TP
.BR \-m ", " "\-\-map " \fI<flags>
Map (replace, translate) special characters on input or output. The following mapping flags are supported:
.RS
.TP 8n
.IP "\fBINLCR"
Translate NL to CR on input.
.IP "\fBIGNCR"
Ignore carriage return on input.
.IP "\fBICRNL"
Translate carriage return to newline on input (unless IGNCR is set).
.IP "\fBONLCR"
Map NL to CR-NL on output.
.IP "\fBOCRNL"
Map CR to NL on output.
.P
If defining more than one flag, the flags must be comma separated.
.RE
.TP .TP
.BR \-v ", " \-\-version .BR \-v ", " \-\-version

View file

@ -18,6 +18,7 @@ _tio()
-o --output-delay \ -o --output-delay \
-n --no-autoconnect \ -n --no-autoconnect \
-l --log \ -l --log \
-m --map \
-v --version \ -v --version \
-h --help" -h --help"
@ -56,6 +57,10 @@ _tio()
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0 return 0
;; ;;
-m | --map)
COMPREPLY=( $(compgen -W "INLCR IGNCR ICRNL ONLCR OCRNL" -- ${cur}) )
return 0
;;
-v | --version) -v | --version)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0 return 0

View file

@ -40,6 +40,7 @@ struct option_t
bool no_autoconnect; bool no_autoconnect;
bool log; bool log;
const char *log_filename; const char *log_filename;
const char *map;
}; };
extern struct option_t option; extern struct option_t option;

View file

@ -25,6 +25,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <getopt.h> #include <getopt.h>
#include <termios.h> #include <termios.h>
@ -44,7 +45,8 @@ struct option_t option =
0, // No output delay 0, // No output delay
false, // No autoconnect false, // No autoconnect
false, // No log false, // No log
"" // Log filename "", // Log filename
"" // Map string
}; };
void print_help(char *argv[]) void print_help(char *argv[])
@ -60,6 +62,7 @@ void print_help(char *argv[])
printf(" -o, --output-delay <ms> Output delay (default: 0)\n"); printf(" -o, --output-delay <ms> Output delay (default: 0)\n");
printf(" -n, --no-autoconnect Disable automatic connect\n"); printf(" -n, --no-autoconnect Disable automatic connect\n");
printf(" -l, --log <filename> Log to file\n"); printf(" -l, --log <filename> Log to file\n");
printf(" -m, --map <flags> Map special characters\n");
printf(" -v, --version Display version\n"); printf(" -v, --version Display version\n");
printf(" -h, --help Display help\n"); printf(" -h, --help Display help\n");
printf("\n"); printf("\n");
@ -105,6 +108,7 @@ void parse_options(int argc, char *argv[])
{"output-delay", required_argument, 0, 'o'}, {"output-delay", required_argument, 0, 'o'},
{"no-autoconnect", no_argument, 0, 'n'}, {"no-autoconnect", no_argument, 0, 'n'},
{"log", required_argument, 0, 'l'}, {"log", required_argument, 0, 'l'},
{"map", required_argument, 0, 'm'},
{"version", no_argument, 0, 'v'}, {"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{0, 0, 0, 0 } {0, 0, 0, 0 }
@ -114,7 +118,7 @@ void parse_options(int argc, char *argv[])
int option_index = 0; int option_index = 0;
/* Parse argument using getopt_long */ /* Parse argument using getopt_long */
c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:vh", long_options, &option_index); c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:m:vh", long_options, &option_index);
/* Detect the end of the options */ /* Detect the end of the options */
if (c == -1) if (c == -1)
@ -165,6 +169,10 @@ void parse_options(int argc, char *argv[])
option.log_filename = optarg; option.log_filename = optarg;
break; break;
case 'm':
option.map = optarg;
break;
case 'v': case 'v':
printf("tio v%s\n", VERSION); printf("tio v%s\n", VERSION);
printf("Copyright (c) 2014-2017 Martin Lund\n"); printf("Copyright (c) 2014-2017 Martin Lund\n");

View file

@ -112,6 +112,8 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
tio_printf(" Stopbits: %d", option.stopbits); tio_printf(" Stopbits: %d", option.stopbits);
tio_printf(" Parity: %s", option.parity); tio_printf(" Parity: %s", option.parity);
tio_printf(" Output delay: %d", option.output_delay); tio_printf(" Output delay: %d", option.output_delay);
if (option.map[0] != 0)
tio_printf(" Map flags: %s", option.map);
if (option.log) if (option.log)
tio_printf(" Log file: %s", option.log_filename); tio_printf(" Log file: %s", option.log_filename);
break; break;
@ -209,6 +211,9 @@ void stdout_restore(void)
void tty_configure(void) void tty_configure(void)
{ {
bool token_found = true;
char *token = NULL;
char *buffer;
int status; int status;
speed_t baudrate; speed_t baudrate;
@ -335,6 +340,39 @@ void tty_configure(void)
/* Control characters */ /* Control characters */
tio.c_cc[VTIME] = 0; // Inter-character timer unused tio.c_cc[VTIME] = 0; // Inter-character timer unused
tio.c_cc[VMIN] = 1; // Blocking read until 1 character received tio.c_cc[VMIN] = 1; // Blocking read until 1 character received
/* Configure any specified input or output mappings */
buffer = strdup(option.map);
while (token_found == true)
{
if (token == NULL)
token = strtok(buffer,",");
else
token = strtok(NULL, ",");
if (token != NULL)
{
if (strcmp(token,"INLCR") == 0)
tio.c_iflag |= INLCR;
else if (strcmp(token,"IGNCR") == 0)
tio.c_iflag |= IGNCR;
else if (strcmp(token,"ICRNL") == 0)
tio.c_iflag |= ICRNL;
else if (strcmp(token,"ONLCR") == 0)
tio.c_oflag |= ONLCR;
else if (strcmp(token,"OCRNL") == 0)
tio.c_oflag |= OCRNL;
else
{
printf("Error: Unknown mapping flag %s\n", token);
exit(EXIT_FAILURE);
}
}
else
token_found = false;
}
free(buffer);
} }
void tty_wait_for_device(void) void tty_wait_for_device(void)