From 97537853a89c6d2b39aa79058b14b523afa03adb Mon Sep 17 00:00:00 2001 From: Martin Lund Date: Sat, 13 Apr 2024 23:16:31 +0200 Subject: [PATCH] Remove options --response-wait, --response-timeout Remove options and rework input handling so it is possible to do the same thing but via script which is much more flexible. These options were always a bit of a hardcoded solution. With the new script expect feature we can wait for any type of response. For example, pipe command to serial device and wait for line response within 1 second: $ echo "*IDN?" | tio /dev/ttyACM0 --script "expect('\r\n', 1000)" --mute --- README.md | 9 ++-- example/config | 1 - man/tio.1.in | 24 +---------- src/bash-completion/tio.in | 10 ----- src/configfile.c | 8 ---- src/main.c | 6 --- src/options.c | 15 ------- src/options.h | 2 - src/tty.c | 87 ++++++++++++++++++-------------------- 9 files changed, 46 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index fc6d3c1..ac04486 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,6 @@ when used in combination with [tmux](https://tmux.github.io). * Activate sub-configurations by name or pattern * Redirect I/O to UNIX socket or IPv4/v6 network socket for scripting or TTY sharing * Pipe input and/or output - * Support for simple line request/response handling * Bash completion on options, serial device names, and sub-configuration names * Configurable text color * Visual or audible alert on connect/disconnect @@ -104,8 +103,6 @@ Options: -m, --map Map characters -c, --color 0..255|bold|none|list Colorize tio text (default: bold) -S, --socket Redirect I/O to socket - -r, --response-wait Wait for line response then quit - --response-timeout Response timeout (default: 100) --rs-485 Enable RS-485 mode --rs-485-config Set RS-485 configuration --alert bell|blink|none Alert on connect/disconnect (default: none) @@ -171,14 +168,14 @@ Redirect I/O to IPv4 network socket on port 4242: $ tio --socket inet:4242 /dev/ttyUSB0 ``` -Inject data to the serial device: +Pipe data to the serial device: ``` $ cat data.bin | tio /dev/ttyUSB0 ``` -Send command to serial device and wait for line response: +Pipe command to serial device and wait for line response within 1 second: ``` -$ echo "*IDN?" | tio /dev/ttyACM0 --response-wait +$ echo "*IDN?" | tio /dev/ttyACM0 --script "expect('\r\n', 1000)" --mute KORAD KD3305P V4.2 SN:32475045 ``` diff --git a/example/config b/example/config index 2c01505..5f72f2a 100644 --- a/example/config +++ b/example/config @@ -27,7 +27,6 @@ log-strip = disable local-echo = disable color = bold rs-485 = disable -response-wait = disable alert = none script-run = always diff --git a/man/tio.1.in b/man/tio.1.in index 45ee188..18d4cbf 100644 --- a/man/tio.1.in +++ b/man/tio.1.in @@ -245,21 +245,6 @@ If port is 0 or no port is provided default port 3333 is used. At present there is a hardcoded limit of 16 clients connected at one time. .RE -.TP -.BR \-r ", " \-\-response\-wait - -Wait for line response then quit. A line is considered any string terminated -with a NL character. If no line is received tio will quit after response -timeout. - -Any tio text is automatically muted when piping a string to tio while in -response mode to make it easy to parse the response. - -.TP -.BR " \-\-response\-timeout " \fI - -Set timeout [ms] of line response (default: 100). - .TP .BR " \-\-rs\-485" @@ -494,10 +479,6 @@ Set output mode. Set socket to redirect I/O to .IP "\fBprefix-ctrl-key" Set prefix ctrl key (a..z or 'none', default: t) -.IP "\fBresponse-wait" -Enable wait for line response -.IP "\fBresponse-timeout" -Set line response timeout .IP "\fBrs-485" Enable RS-485 mode .IP "\fBrs-485-config" @@ -648,11 +629,10 @@ Pipe command to the serial device: $ echo "ls -la" | tio /dev/serial/by\-id/usb\-FTDI_TTL232R-3V3_FTGQVXBL\-if00\-port0 .TP -Pipe command to the serial device and wait for line response (string ending with CR or NL): +Pipe command to serial device and wait for line response within 1 second: -$ echo "*IDN?" | tio /dev/ttyACM0 --response-wait +$ echo "*IDN?" | tio /dev/ttyACM0 --script "expect('\\r\\n', 1000)" --mute .TP -In this mode, only the response will be printed. .TP Likewise, to pipe data from file to the serial device: diff --git a/src/bash-completion/tio.in b/src/bash-completion/tio.in index c94c0cb..10bf6ef 100644 --- a/src/bash-completion/tio.in +++ b/src/bash-completion/tio.in @@ -33,8 +33,6 @@ _tio() -S --socket \ --input-mode \ --output-mode \ - -r --response-wait \ - --response-timeout \ --rs-485 \ --rs-485-config \ --alert \ @@ -140,14 +138,6 @@ _tio() COMPREPLY=( $(compgen -W "normal hex" -- ${cur}) ) return 0 ;; - -r | --response-wait) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - ;; - --response-timeout) - COMPREPLY=( $(compgen -W "1 10 100" -- ${cur}) ) - return 0 - ;; --rs-485) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 diff --git a/src/configfile.c b/src/configfile.c index 193f7fe..b1ef72c 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -276,14 +276,6 @@ static int data_handler(void *user, const char *section, const char *name, option.prefix_key = value[0]; } } - else if (!strcmp(name, "response-wait")) - { - option.response_wait = read_boolean(value, name); - } - else if (!strcmp(name, "response-timeout")) - { - option.response_timeout = read_integer(value, name, 0, LONG_MAX); - } else if (!strcmp(name, "rs-485")) { option.rs485 = read_boolean(value, name); diff --git a/src/main.c b/src/main.c index 4b6d91e..eb9aa60 100644 --- a/src/main.c +++ b/src/main.c @@ -69,12 +69,6 @@ int main(int argc, char *argv[]) { // Enter non interactive mode interactive_mode = false; - - // Mute tio text in response mode - if (option.response_wait) - { - option.mute = true; - } } /* Configure output terminal */ diff --git a/src/options.c b/src/options.c index 44fc47f..427e4e8 100644 --- a/src/options.c +++ b/src/options.c @@ -50,7 +50,6 @@ enum opt_t OPT_LOG_STRIP, OPT_LOG_APPEND, OPT_LINE_PULSE_DURATION, - OPT_RESPONSE_TIMEOUT, OPT_RS485, OPT_RS485_CONFIG, OPT_ALERT, @@ -96,8 +95,6 @@ struct option_t option = .prefix_code = 20, // ctrl-t .prefix_key = 't', .prefix_enabled = true, - .response_wait = false, - .response_timeout = 100, .mute = false, .rs485 = false, .rs485_config_flags = 0, @@ -142,8 +139,6 @@ void print_help(char *argv[]) printf(" -m, --map Map characters\n"); printf(" -c, --color 0..255|bold|none|list Colorize tio text (default: bold)\n"); printf(" -S, --socket Redirect I/O to socket\n"); - printf(" -r, --response-wait Wait for line response then quit\n"); - printf(" --response-timeout Response timeout (default: 100)\n"); printf(" --rs-485 Enable RS-485 mode\n"); printf(" --rs-485-config Set RS-485 configuration\n"); printf(" --alert bell|blink|none Alert on connect/disconnect (default: none)\n"); @@ -375,8 +370,6 @@ void options_parse(int argc, char *argv[]) {"color", required_argument, 0, 'c' }, {"input-mode", required_argument, 0, OPT_INPUT_MODE }, {"output-mode", required_argument, 0, OPT_OUTPUT_MODE }, - {"response-wait", no_argument, 0, 'r' }, - {"response-timeout", required_argument, 0, OPT_RESPONSE_TIMEOUT }, {"rs-485", no_argument, 0, OPT_RS485 }, {"rs-485-config", required_argument, 0, OPT_RS485_CONFIG }, {"alert", required_argument, 0, OPT_ALERT }, @@ -531,14 +524,6 @@ void options_parse(int argc, char *argv[]) option.output_mode = output_mode_option_parse(optarg); break; - case 'r': - option.response_wait = true; - break; - - case OPT_RESPONSE_TIMEOUT: - option.response_timeout = string_to_long(optarg); - break; - case OPT_RS485: option.rs485 = true; break; diff --git a/src/options.h b/src/options.h index b5b5c7b..7a6b627 100644 --- a/src/options.h +++ b/src/options.h @@ -77,8 +77,6 @@ struct option_t unsigned char prefix_code; unsigned char prefix_key; bool prefix_enabled; - bool response_wait; - int response_timeout; bool mute; bool rs485; uint32_t rs485_config_flags; diff --git a/src/tty.c b/src/tty.c index af79f3f..b85cbb7 100644 --- a/src/tty.c +++ b/src/tty.c @@ -1536,9 +1536,6 @@ int tty_connect(void) int status; bool next_timestamp = false; char* now = NULL; - struct timeval tv; - struct timeval *tv_p = &tv; - bool ignore_stdin = false; /* Open tty device */ fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK); @@ -1629,6 +1626,35 @@ int tty_connect(void) } } + /* If stdin is a pipe forward all input to tty device */ + if (interactive_mode == false) + { + while (true) + { + int ret = read(pipefd[0], &input_char, 1); + if (ret < 0) + { + tio_error_printf("Could not read from pipe (%s)", strerror(errno)); + exit(EXIT_FAILURE); + } + else if (ret > 0) + { + // Forward to tty device + ret = write(fd, &input_char, 1); + if (ret < 0) + { + tio_error_printf("Could not write to serial device (%s)", strerror(errno)); + exit(EXIT_FAILURE); + } + } + else + { + // EOF - finished forwarding + break; + } + } + } + /* Manage script activation */ if (option.script_run != SCRIPT_RUN_NEVER) { @@ -1640,33 +1666,24 @@ int tty_connect(void) } } + // Exit if piped input + if (interactive_mode == false) + { + exit(EXIT_SUCCESS); + } + /* Input loop */ while (true) { FD_ZERO(&rdfs); FD_SET(fd, &rdfs); - if (!ignore_stdin) - { - FD_SET(pipefd[0], &rdfs); - } + FD_SET(pipefd[0], &rdfs); + maxfd = MAX(fd, pipefd[0]); maxfd = MAX(maxfd, socket_add_fds(&rdfs, true)); - /* Manage timeout */ - if ((option.response_wait) && (option.response_timeout != 0)) - { - // Set response timeout - tv_p->tv_sec = 0; - tv_p->tv_usec = option.response_timeout * 1000; - } - else - { - // No timeout - tv_p = NULL; - } - /* Block until input becomes available */ - status = select(maxfd + 1, &rdfs, NULL, NULL, tv_p); + status = select(maxfd + 1, &rdfs, NULL, NULL, NULL); if (status > 0) { bool forward = false; @@ -1750,15 +1767,6 @@ int tty_connect(void) { next_timestamp = true; } - - if (option.response_wait) - { - if (input_char == '\n') - { - tty_sync(fd); - exit(EXIT_SUCCESS); - } - } } } else if (FD_ISSET(pipefd[0], &rdfs)) @@ -1772,22 +1780,9 @@ int tty_connect(void) } else if (bytes_read == 0) { - /* Reached EOF (when piping to stdin) */ - if (option.response_wait) - { - /* Stdin pipe closed but not blocking so stop listening - * to stdin in response mode. - * - * Note: select() really indicates not if data is ready - * but if file descriptor is non-blocking for I/O - * operation. */ - ignore_stdin = true; - } - else - { - tty_sync(fd); - exit(EXIT_SUCCESS); - } + /* Reached EOF (when piping to stdin, never reached) */ + tty_sync(fd); + exit(EXIT_SUCCESS); } /* Process input byte by byte */