]> git.sur5r.net Git - tio/commitdiff
New upstream version 2.4 upstream/2.4
authorJakob Haufe <sur5r@debian.org>
Fri, 16 Dec 2022 20:44:01 +0000 (21:44 +0100)
committerJakob Haufe <sur5r@debian.org>
Fri, 16 Dec 2022 20:44:01 +0000 (21:44 +0100)
16 files changed:
NEWS
README.md
TODO
example/tiorc
man/tio.1.in
man/tio.1.txt
meson.build
src/bash-completion/tio.in
src/configfile.c
src/log.c
src/log.h
src/main.c
src/meson.build
src/options.c
src/tty.c
src/tty.h

diff --git a/NEWS b/NEWS
index 1a1cc4dbb151e0eaf923a66ad27e15e35670a80c..1de122c085fc6618ccb27084326ca719910b288c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,48 @@
 
-=== tio v2.2 ===
+=== tio v2.4 ===
+
+
+
+Changes since tio v2.3:
+
+ * Add threaded input handling
+
+   To make tio more responsive to quit and I/O flush key command when main I/O
+   thread is blocked on output.
+
+ * Fix so that is it possible to quit tio in tio etc.
+
+   Fix regression so that it is possible to send the prefix key code to the
+   remote tio session without local tio session reacting to same key code
+   (quitting etc.).
+
+ * Add key command to toggle log on/off
+
+    Add key command 'ctrl-t f' which will toggle log on/off.
+
+    If no log filename has been specified via the 'log-filename' option then
+    tio will automatically generate a new log filename every time the log
+    feature is toggled on. Meaning, when toggled multiple times, multiple
+    log files will be generated.
+
+    However, if a log filename has been specified, tio will only write and
+    append to that same file.
+
+
+
+Changes since tio v2.2:
+
+ * Add mute feature
+
+   This will make tio go fully silent and not print anything.
+
+ * Rename config variable 'tty' to 'device'
+
+ * Deprecate tty config keyword but keep it around for now
+
+ * Update show config
+
+ * Update example tiorc
 
 
 
index 1c87aa0c75e133c161b9e9dd37f1963848611892..c58d4b47adde6d8c9c35ac6de6b0196a5a89978d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
 
 [![](https://img.shields.io/circleci/build/gh/tio/tio?token=da7e7fd0d0ee99b9f986f8877dcdbe28f73d9e06)](https://circleci.com/gh/tio/tio/tree/master)
 [![](https://img.shields.io/github/v/release/tio/tio?sort=semver)](https://github.com/tio/tio/releases)
-[![](https://img.shields.io/tokei/lines/github/tio/tio)](https://github.com/tio/tio)
 [![](https://img.shields.io/repology/repositories/tio)](https://repology.org/project/tio/versions)
+[![](https://img.shields.io/tokei/lines/github/tio/tio)](https://github.com/tio/tio)
 
 ## 1. Introduction
 
@@ -69,7 +69,7 @@ The command-line interface is straightforward as reflected in the output from
 ```
  Usage: tio [<options>] <tty-device|sub-config>
 
- Connect to tty device directly or via sub-configuration.
+ Connect to TTY device directly or via sub-configuration.
 
  Options:
    -b, --baudrate <bps>                   Baud rate (default: 115200)
@@ -127,7 +127,7 @@ Which corresponds to the commonly used default options:
 $ tio -b 115200 -d 8 -f none -s 1 -p none /dev/ttyUSB0
 ```
 
-It is recommended to connect serial tty devices by ID:
+It is recommended to connect serial TTY devices by ID:
 ```
 $ tio /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 ```
@@ -139,7 +139,7 @@ List available serial devices by ID:
 $ tio --list-devices
 ```
 Note: One can also use tio shell completion on /dev which will automatically
-list all available serial tty devices.
+list all available serial TTY devices.
 
 Log to file with autogenerated filename:
 ```
@@ -178,6 +178,7 @@ ctrl-t ? to list the available key commands.
 [20:19:12.040]  ctrl-t b       Send break
 [20:19:12.040]  ctrl-t c       Show configuration
 [20:19:12.040]  ctrl-t e       Toggle local echo mode
+[20:19:12.040]  ctrl-t f       Toggle log to file
 [20:19:12.040]  ctrl-t g       Toggle serial port line
 [20:19:12.040]  ctrl-t h       Toggle hexadecimal mode
 [20:19:12.040]  ctrl-t l       Clear screen
@@ -203,7 +204,7 @@ following locations in the order listed:
 
 The configuration file supports sub-configurations using named sections which can
 be activated via the command-line by name or pattern. A sub-configuration
-specifies which tty to connect to and other options.
+specifies which TTY device to connect to and other options.
 
 Example configuration file:
 
@@ -216,7 +217,7 @@ stopbits = 1
 color = 10
 
 [rpi3]
-tty = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
+device = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 baudrate = 115200
 no-autoconnect = enable
 log = enable
@@ -226,7 +227,7 @@ color = 12
 
 [usb devices]
 pattern = usb([0-9]*)
-tty = /dev/ttyUSB%s
+device = /dev/ttyUSB%s
 color = 13
 ```
 
diff --git a/TODO b/TODO
index 14d80254653c4786cb4901dcbf17890980672493..ce251732ca8c00583b814b5a556c6f6da661dc0c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,33 @@
 
+ * Allow tio to connect to socket
+
+   After some more consideration I think it makes sense to support connecting to a
+   socket as that will make tio be able to both serve a serial port via a socket
+   and connect to it - it will be an end to end solution. In short we will be able
+   to do the following:
+
+   Host serial port on socket (existing feature):
+    $ tio --socket unix:/tmp/tio-socket-0 /dev/ttyUSB0
+
+   Connect to same socket (new feature):
+    $ tio unix:/tmp/tio-socket-0
+
+   Besides a bit of refactoring the following required changes spring to mind:
+
+    * Socket mode and type of socket should be activated via device name prefix. For example:
+      * UNIX socket: tio unix:<filename>
+      * TCPv4 socket: tio inet:<ip>:<port>
+      * TCPv6 socket: tio inet6:<ip>:<port>
+    * If no port number defined default to 3333
+    * Mapping flags INLCR, IGNCR, ICRNL needs implementation for socket mode
+    * Error messages should just say "device" instead of "tty device" etc.
+    * Remove other tty'isms (tty_write() should be device_write() etc.)
+    * In session key commands that do not work in socket mode should either not be listed or print an error messages if used.
+    * All non-tty features should continue work (auto-connect etc.)
+    * Shell completion script update
+    * Man page update
+
+
  * Split I/O feature
 
    Allow to split input and output so that it is possible to manage these
index 525a982eb60260a7c433e5b4046c5022f96e037d..78a197b8048c7f9708a250ffe5c03be47afc2c6d 100644 (file)
@@ -28,32 +28,32 @@ alert = none
 
 [rpi3]
 baudrate = 115200
-tty = /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A6009HU3-if00-port0
+device = /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A6009HU3-if00-port0
 socket = unix:/tmp/tio-socket-0
 color = 9
 
 [am64-evm]
 baudrate = 115200
-tty = /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_01093176-if01-port0
+device = /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_01093176-if01-port0
 line-pulse-duration = DTR=200,RTS=300,RI=50
 alert = bell
 color = 10
 
 [tincan]
 baudrate = 9600
-tty = /dev/serial/by-id/usb-TinCanTools_Flyswatter2_FS20000-if00-port0
+device = /dev/serial/by-id/usb-TinCanTools_Flyswatter2_FS20000-if00-port0
 log = enable
 log-file = tincan.log
 log-strip = enable
 color = 11
 
-[usb devices]
+[usb]
 pattern = usb([0-9]*)
-tty = /dev/ttyUSB%s
+device = /dev/ttyUSB%s
 color = 12
 
 [rs-485-device]
-tty = /dev/ttyUSB0
+device = /dev/ttyUSB0
 rs-485 = enable
 rs-485-config = RTS_ON_SEND=1,RTS_AFTER_SEND=1,RTS_DELAY_BEFORE_SEND=60,RTS_DELAY_AFTER_SEND=80,RX_DURING_TX
 color = 13
index 936ab5c85e02843c09ea279e23f9b1c232bac223..1ec1355189b5a6a802369b060f91fe2d6a48cbbb 100644 (file)
@@ -289,6 +289,10 @@ Send serial break (triggers SysRq on Linux, etc.)
 Show configuration (baudrate, databits, etc.)
 .IP "\fBctrl-t e"
 Toggle local echo mode
+.IP "\fBctrl-t f"
+Toggle log to file
+.IP "\fBctrl-t F"
+Flush data I/O buffers (discard data written but not transmitted and data received but not read)
 .IP "\fBctrl-t g"
 Toggle serial port line
 .IP "\fBctrl-t h"
@@ -340,7 +344,7 @@ activated from the command-line when starting tio.
 
 .PP
 \fBtio\fR will try to match the user input to a sub-configuration by name or by
-pattern to get the tty and other options.
+pattern to get the TTY device and other options.
 
 .PP
 Options without any label change the default options.
@@ -354,8 +358,8 @@ The following configuration file options are available:
 .TP 25n
 .IP "\fBpattern"
 Pattern matching user input. This pattern can be an extended regular expression with a single group.
-.IP "\fBtty"
-tty device to open. If it contains a "%s" it is substituted with the first group match.
+.IP "\fBdevice"
+TTY device to open. If it contains a "%s" it is substituted with the first group match.
 .IP "\fBbaudrate"
 Set baud rate
 .IP "\fBdatabits"
@@ -433,7 +437,7 @@ Named sub-configurations can be added via labels:
 .nf
 .eo
 [rpi3]
-tty = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
+device = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 baudrate = 115200
 color = 11
 .ec
@@ -458,7 +462,7 @@ A sub-configuration can also be activated by its pattern which supports regular
 .eo
 [usb device]
 pattern = usb([0-9]*)
-tty = /dev/ttyUSB%s
+device = /dev/ttyUSB%s
 baudrate = 115200
 .ec
 .fi
@@ -489,7 +493,7 @@ Which corresponds to the commonly used default options:
 
 $ tio \-b 115200 \-d 8 \-f none \-s 1 \-p none /dev/ttyUSB0
 .TP
-It is recommended to connect serial tty devices by ID:
+It is recommended to connect serial TTY devices by ID:
 
 $ tio /dev/serial/by\-id/usb\-FTDI_TTL232R-3V3_FTGQVXBL\-if00\-port0
 .PP
@@ -528,13 +532,13 @@ expect -i $uart "prompt> "
 .RE
 
 .TP
-Redirect device I/O to network file socket for remote tty sharing:
+Redirect device I/O to network file socket for remote TTY sharing:
 
 $ tio --socket inet:4444 /dev/ttyUSB0
 
 .TP
 
-Then, use netcat to connect to the shared tty session over network (assuming tio is hosted on IP 10.0.0.42):
+Then, use netcat to connect to the shared TTY session over network (assuming tio is hosted on IP 10.0.0.42):
 
 $ nc -N 10.0.0.42 4444
 
index 1874c65dcd871cfb877b3d79ff9bcbd29a6e21d2..aa26dcc28bd4871e9885af0546b4b714fcbf1ec6 100644 (file)
@@ -224,6 +224,10 @@ KEYS
 
        ctrl-t e        Toggle local echo mode
 
+       ctrl-t f        Toggle log to file
+
+       ctrl-t F        Flush data I/O buffers (discard data written but not transmitted and data received but not read)
+
        ctrl-t g        Toggle serial port line
 
        ctrl-t h        Toggle hexadecimal mode
@@ -262,7 +266,7 @@ CONFIGURATION FILE
 
        Labels can be used to group settings into named sub-configurations which can be activated from the command-line when starting tio.
 
-       tio will try to match the user input to a sub-configuration by name or by pattern to get the tty and other options.
+       tio will try to match the user input to a sub-configuration by name or by pattern to get the TTY device and other options.
 
        Options without any label change the default options.
 
@@ -272,7 +276,7 @@ CONFIGURATION FILE
 
        pattern                  Pattern matching user input. This pattern can be an extended regular expression with a single group.
 
-       tty                      tty device to open. If it contains a "%s" it is substituted with the first group match.
+       device                   TTY device to open. If it contains a "%s" it is substituted with the first group match.
 
        baudrate                 Set baud rate
 
@@ -338,7 +342,7 @@ CONFIGURATION FILE EXAMPLES
        Named sub-configurations can be added via labels:
 
               [rpi3]
-              tty = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
+              device = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
               baudrate = 115200
               color = 11
 
@@ -354,7 +358,7 @@ CONFIGURATION FILE EXAMPLES
 
               [usb device]
               pattern = usb([0-9]*)
-              tty = /dev/ttyUSB%s
+              device = /dev/ttyUSB%s
               baudrate = 115200
 
        Activate the sub-configuration by pattern match:
@@ -378,7 +382,7 @@ EXAMPLES
 
               $ tio -b 115200 -d 8 -f none -s 1 -p none /dev/ttyUSB0
 
-       It is recommended to connect serial tty devices by ID:
+       It is recommended to connect serial TTY devices by ID:
 
               $ tio /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 
@@ -407,11 +411,11 @@ EXAMPLES
               send -i $uart "ls -la\n"
               expect -i $uart "prompt> "
 
-       Redirect device I/O to network file socket for remote tty sharing:
+       Redirect device I/O to network file socket for remote TTY sharing:
 
               $ tio --socket inet:4444 /dev/ttyUSB0
 
-       Then, use netcat to connect to the shared tty session over network (assuming tio is hosted on IP 10.0.0.42):
+       Then, use netcat to connect to the shared TTY session over network (assuming tio is hosted on IP 10.0.0.42):
 
               $ nc -N 10.0.0.42 4444
 
@@ -439,4 +443,4 @@ WEBSITE
 AUTHOR
        Created by Martin Lund <martin.lund@keep-it-simple.com>.
 
-tio 2.2                                                                                                                              2022-10-18                                                                                                                               tio(1)
+tio 2.4                                                                                                                              2022-11-02                                                                                                                               tio(1)
index 9a91e851a53f24fd1cb1d9b9b7df1f8b4323750b..c394f8cb0f9188895034997e26bd41fd33630b7b 100644 (file)
@@ -1,12 +1,12 @@
 project('tio', 'c',
-    version : '2.2',
+    version : '2.4',
     license : [ 'GPL-2'],
     meson_version : '>= 0.53.2',
     default_options : [ 'warning_level=2', 'buildtype=release', 'c_std=gnu99' ]
 )
 
 # The tag date of the project_version(), update when the version bumps.
-version_date = '2022-10-18'
+version_date = '2022-11-02'
 
 # Test for dynamic baudrate configuration interface
 compiler = meson.get_compiler('c')
index 82cb649964f54863791cfca21593ca0eaad797ed..9602c4fb93a54a599cc286c4beca8aba6128c950 100644 (file)
@@ -35,6 +35,7 @@ _tio()
              --rs-485 \
              --rs-485-config \
              --alert \
+             --mute \
           -v --version \
           -h --help"
 
@@ -141,6 +142,10 @@ _tio()
             COMPREPLY=( $(compgen -W "none bell blink"  -- ${cur}) )
             return 0
             ;;
+        --mute)
+            COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+            return 0
+            ;;
         -v | --version)
             COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
             return 0
index e749e4b49f9453a362d2f50ea790f5bc0545e662..8e29a26d2bfcb2b0c3b20df1be9954d7e361b4c1 100644 (file)
@@ -112,7 +112,7 @@ static int data_handler(void *user, const char *section, const char *name,
     if (!strcmp(section, c.section_name))
     {
         // Set configuration parameter if found
-        if (!strcmp(name, "tty"))
+        if (!strcmp(name, "device") || !strcmp(name, "tty"))
         {
             asprintf(&c.tty, value, c.match);
             option.tty_device = c.tty;
@@ -302,6 +302,17 @@ static int data_handler(void *user, const char *section, const char *name,
         {
             option.alert = alert_option_parse(value);
         }
+        else if (!strcmp(name, "mute"))
+        {
+            if (!strcmp(value, "enable"))
+            {
+                option.mute = true;
+            }
+            else if (!strcmp(value, "disable"))
+            {
+                option.mute = false;
+            }
+        }
     }
 
     return 0;
@@ -493,7 +504,7 @@ void config_file_print(void)
 {
     if (c.path != NULL)
     {
-        tio_printf(" Path: %s", c.path);
+        tio_printf(" Active configuration file: %s", c.path);
         if (c.section_name != NULL)
         {
             tio_printf(" Active sub-configuration: %s", c.section_name);
index aa868470e2e2bef1dd78cc1a379705189dcba84d..d0cf54396033fd38f75fa4406e4c5a2f58a50957 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -38,9 +38,9 @@
 #define IS_ESC_END_CHAR(c)              ((c >= 0x30) && (c <= 0x7E))
 #define IS_CTRL_CHAR(c)                 ((c >= 0x00) && (c <= 0x1F))
 
-static FILE *fp;
-static bool log_error = false;
+static FILE *fp = NULL;
 static char file_buffer[BUFSIZ];
+static const char *log_filename = NULL;
 
 static char *date_time(void)
 {
@@ -56,7 +56,7 @@ static char *date_time(void)
     return date_time_string;
 }
 
-void log_open(const char *filename)
+int log_open(const char *filename)
 {
     static char automatic_filename[400];
 
@@ -65,19 +65,22 @@ void log_open(const char *filename)
         // Generate filename if none provided ("tio_DEVICE_YYYY-MM-DDTHH:MM:SS.log")
         sprintf(automatic_filename, "tio_%s_%s.log", basename((char *)option.tty_device), date_time());
         filename = automatic_filename;
-        option.log_filename = automatic_filename;
     }
 
+    log_filename = filename;
+
     // Open log file in append write mode
     fp = fopen(filename, "a+");
     if (fp == NULL)
     {
-        log_error = true;
-        exit(EXIT_FAILURE);
+        tio_warning_printf("Could not open log file %s (%s)", filename, strerror(errno));
+        return -1;
     }
 
     // Enable line buffering
     setvbuf(fp, file_buffer, _IOLBF, BUFSIZ);
+
+    return 0;
 }
 
 bool log_strip(char c)
@@ -141,6 +144,11 @@ bool log_strip(char c)
 
 void log_printf(const char *format, ...)
 {
+    if (fp == NULL)
+    {
+        return;
+    }
+
     char *line;
 
     va_list(args);
@@ -155,20 +163,22 @@ void log_printf(const char *format, ...)
 
 void log_putc(char c)
 {
-    if (fp != NULL)
+    if (fp == NULL)
     {
-        if (option.log_strip)
-        {
-            if (!log_strip(c))
-            {
-                fputc(c, fp);
-            }
-        }
-        else
+        return;
+    }
+
+    if (option.log_strip)
+    {
+        if (!log_strip(c))
         {
             fputc(c, fp);
         }
     }
+    else
+    {
+        fputc(c, fp);
+    }
 }
 
 void log_close(void)
@@ -176,6 +186,8 @@ void log_close(void)
     if (fp != NULL)
     {
         fclose(fp);
+        fp = NULL;
+        log_filename = NULL;
     }
 }
 
@@ -183,15 +195,12 @@ void log_exit(void)
 {
     if (option.log)
     {
+        tio_printf("Saved log to file %s", log_filename);
         log_close();
     }
+}
 
-    if (log_error)
-    {
-        tio_error_printf("Could not open log file %s (%s)", option.log_filename, strerror(errno));
-    }
-    else if (option.log)
-    {
-        tio_printf("Saved log to file %s", option.log_filename);
-    }
+const char *log_get_filename(void)
+{
+    return log_filename;
 }
index d2a21881109be04120c0ad8d02bcf8bec1b9cc38..b24114e537f2dfe1758c91cb7eb4e0e218c9963b 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -21,8 +21,9 @@
 
 #pragma once
 
-void log_open(const char *filename);
+int log_open(const char *filename);
 void log_printf(const char *format, ...);
 void log_putc(char c);
 void log_close(void);
 void log_exit(void);
+const char * log_get_filename(void);
index d2b1c0d063dfc9fabe0ecba402719a5356d72a0c..ddf88485d79f95ba59ae987d738b210e8ed6891b 100644 (file)
@@ -120,6 +120,12 @@ int main(int argc, char *argv[])
         socket_configure();
     }
 
+    /* Spawn input handling into separate thread */
+    tty_input_thread_create();
+
+    /* Wait for input to be ready */
+    tty_input_thread_wait_ready();
+
     /* Connect to tty device */
     if (option.no_autoconnect)
     {
index 00777330ce96020ea80bcdfa099bc8e583c5601f..cec9429218e67b8958dc903822e8847e303307df 100644 (file)
@@ -20,9 +20,12 @@ tio_sources = [
   'alert.c'
 ]
 
-tio_dep = dependency('inih', required: true,
+tio_dep = [
+  dependency('threads', required: true),
+  dependency('inih', required: true,
                      fallback : ['libinih', 'inih_dep'],
                      default_options: ['default_library=static', 'distro_install=false'])
+]
 
 tio_c_args = ['-Wno-unused-result']
 
index 7b61fd810adabc8bf98ca0c6ac111421d38b4105..eb75144edf7ae99445fa1b67dd7697659b311edb 100644 (file)
@@ -38,6 +38,7 @@
 #include "rs485.h"
 #include "timestamp.h"
 #include "alert.h"
+#include "log.h"
 
 enum opt_t
 {
@@ -51,6 +52,7 @@ enum opt_t
     OPT_RS485_CONFIG,
     OPT_ALERT,
     OPT_COMPLETE_SUB_CONFIGS,
+    OPT_MUTE,
 };
 
 /* Default options */
@@ -99,7 +101,7 @@ void print_help(char *argv[])
 
     printf("Usage: tio [<options>] <tty-device|sub-config>\n");
     printf("\n");
-    printf("Connect to tty device directly or via sub-configuration.\n");
+    printf("Connect to TTY device directly or via sub-configuration.\n");
     printf("\n");
     printf("Options:\n");
     printf("  -b, --baudrate <bps>                   Baud rate (default: 115200)\n");
@@ -127,6 +129,7 @@ void print_help(char *argv[])
     printf("      --rs-485                           Enable RS-485 mode\n");
     printf("      --rs-485-config <config>           Set RS-485 configuration\n");
     printf("      --alert bell|blink|none            Alert on connect/disconnect (default: none)\n");
+    printf("      --mute                             Mute tio\n");
     printf("  -v, --version                          Display version\n");
     printf("  -h, --help                             Display help\n");
     printf("\n");
@@ -193,7 +196,7 @@ void line_pulse_duration_option_parse(const char *arg)
 
 void options_print()
 {
-    tio_printf(" TTY device: %s", option.tty_device);
+    tio_printf(" Device: %s", option.tty_device);
     tio_printf(" Baudrate: %u", option.baudrate);
     tio_printf(" Databits: %d", option.databits);
     tio_printf(" Flow: %s", option.flow);
@@ -214,7 +217,7 @@ void options_print()
     if (option.map[0] != 0)
         tio_printf(" Map flags: %s", option.map);
     if (option.log)
-        tio_printf(" Log file: %s", option.log_filename);
+        tio_printf(" Log file: %s", log_get_filename());
     if (option.socket)
         tio_printf(" Socket: %s", option.socket);
 }
@@ -258,6 +261,7 @@ void options_parse(int argc, char *argv[])
             {"rs-485",               no_argument,       0, OPT_RS485               },
             {"rs-485-config",        required_argument, 0, OPT_RS485_CONFIG        },
             {"alert",                required_argument, 0, OPT_ALERT               },
+            {"mute",                 no_argument,       0, OPT_MUTE                },
             {"version",              no_argument,       0, 'v'                     },
             {"help",                 no_argument,       0, 'h'                     },
             {"complete-sub-configs", no_argument,       0, OPT_COMPLETE_SUB_CONFIGS},
@@ -413,6 +417,10 @@ void options_parse(int argc, char *argv[])
                 option.alert = alert_option_parse(optarg);
                 break;
 
+            case OPT_MUTE:
+                option.mute = true;
+                break;
+
             case 'v':
                 printf("tio v%s\n", VERSION);
                 exit(EXIT_SUCCESS);
index 75c724230b34de2f0fad913bfbb2354892292af7..faad20c3a25324266d8acd7c3d3c073eab94ac91 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
@@ -40,6 +40,7 @@
 #include <errno.h>
 #include <time.h>
 #include <dirent.h>
+#include <pthread.h>
 #include "config.h"
 #include "configfile.h"
 #include "tty.h"
@@ -80,6 +81,8 @@
 #define KEY_B 0x62
 #define KEY_C 0x63
 #define KEY_E 0x65
+#define KEY_F 0x66
+#define KEY_SHIFT_F 0x46
 #define KEY_G 0x67
 #define KEY_H 0x68
 #define KEY_L 0x6C
@@ -133,6 +136,9 @@ static unsigned char hex_char_index = 0;
 static char tty_buffer[BUFSIZ*2];
 static size_t tty_buffer_count = 0;
 static char *tty_buffer_write_ptr = tty_buffer;
+static pthread_t thread;
+static int pipefd[2];
+static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER;
 
 static void optional_local_echo(char c)
 {
@@ -255,6 +261,99 @@ ssize_t tty_write(int fd, const void *buffer, size_t count)
     return bytes_written;
 }
 
+void *tty_stdin_input_thread(void *arg)
+{
+    UNUSED(arg);
+    char input_buffer[BUFSIZ];
+    ssize_t byte_count;
+    ssize_t bytes_written;
+
+    // Create FIFO pipe
+    if (pipe(pipefd) == -1)
+    {
+        tio_error_printf("Failed to create pipe");
+        exit(EXIT_FAILURE);
+    }
+
+    // Signal that input pipe is ready
+    pthread_mutex_unlock(&mutex_input_ready);
+
+    // Input loop for stdin
+    while (1)
+    {
+        /* Input from stdin ready */
+        byte_count = read(STDIN_FILENO, input_buffer, BUFSIZ);
+        if (byte_count < 0)
+        {
+            tio_warning_printf("Could not read from stdin (%s)", strerror(errno));
+        }
+        else if (byte_count == 0)
+        {
+            // Close write end to signal EOF in read end
+            close(pipefd[1]);
+            pthread_exit(0);
+        }
+
+        if (interactive_mode)
+        {
+            static char previous_char = 0;
+            char input_char;
+
+            // Process quit and flush key command
+            for (int i = 0; i<byte_count; i++)
+            {
+                input_char = input_buffer[i];
+
+                if (previous_char == option.prefix_code)
+                {
+                    switch (input_char)
+                    {
+                        case KEY_Q:
+                            exit(EXIT_FAILURE);
+                            break;
+                        case KEY_SHIFT_F:
+                            tio_printf("Flushed data I/O channels")
+                            tcflush(fd, TCIOFLUSH);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                previous_char = input_char;
+            }
+        }
+
+        // Write all bytes read to pipe
+        while (byte_count)
+        {
+            bytes_written = write(pipefd[1], input_buffer, byte_count);
+            if (bytes_written < 0)
+            {
+                tio_warning_printf("Could not write to pipe (%s)", strerror(errno));
+                break;
+            }
+            byte_count -= bytes_written;
+        }
+    }
+
+    pthread_exit(0);
+}
+
+void tty_input_thread_create(void)
+{
+    pthread_mutex_lock(&mutex_input_ready);
+
+    if (pthread_create(&thread, NULL, tty_stdin_input_thread, NULL) != 0) {
+        tio_error_printf("pthread_create() error");
+        exit(1);
+    }
+}
+
+void tty_input_thread_wait_ready(void)
+{
+    pthread_mutex_lock(&mutex_input_ready);
+}
+
 static void output_hex(char c)
 {
     hex_chars[hex_char_index++] = c;
@@ -348,12 +447,13 @@ static void toggle_line(const char *line_name, int mask, enum line_mode_t line_m
     }
 }
 
-void handle_command_sequence(char input_char, char previous_char, char *output_char, bool *forward)
+void handle_command_sequence(char input_char, char *output_char, bool *forward)
 {
     char unused_char;
     bool unused_bool;
     int state;
     static enum line_mode_t line_mode = LINE_OFF;
+    static char previous_char = 0;
 
     /* Ignore unused arguments */
     if (output_char == NULL)
@@ -406,6 +506,16 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
         /* Do not forward input char to output by default */
         *forward = false;
 
+        /* Handle special double prefix key input case */
+        if (input_char == option.prefix_code)
+        {
+            /* Forward prefix character to tty */
+            *output_char = option.prefix_code;
+            *forward = true;
+            previous_char = 0;
+            return;
+        }
+
         switch (input_char)
         {
             case KEY_QUESTION:
@@ -414,6 +524,8 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf(" ctrl-%c b       Send break", option.prefix_key);
                 tio_printf(" ctrl-%c c       Show configuration", option.prefix_key);
                 tio_printf(" ctrl-%c e       Toggle local echo mode", option.prefix_key);
+                tio_printf(" ctrl-%c f       Toggle log to file", option.prefix_key);
+                tio_printf(" ctrl-%c F       Flush data I/O buffers", option.prefix_key);
                 tio_printf(" ctrl-%c g       Toggle serial port line", option.prefix_key);
                 tio_printf(" ctrl-%c h       Toggle hexadecimal mode", option.prefix_key);
                 tio_printf(" ctrl-%c l       Clear screen", option.prefix_key);
@@ -443,6 +555,25 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf(" RI : %s", (state & TIOCM_RI) ? "HIGH" : "LOW");
                 break;
 
+            case KEY_F:
+                if (option.log)
+                {
+                    log_close();
+                    option.log = false;
+                }
+                else
+                {
+                    if (log_open(option.log_filename) == 0)
+                    {
+                        option.log = true;
+                    }
+                }
+                tio_printf("Switched log to file %s", option.log ? "on" : "off");
+                break;
+
+            case KEY_SHIFT_F:
+                break;
+
             case KEY_G:
                 tio_printf("Please enter which serial line number to toggle:");
                 tio_printf(" DTR (0)");
@@ -473,8 +604,8 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
 
             case KEY_C:
                 tio_printf("Configuration:");
-                config_file_print();
                 options_print();
+                config_file_print();
                 if (option.rs485)
                 {
                     rs485_print_config();
@@ -570,27 +701,12 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 break;
 
             default:
-                /* Handle double prefix key input case */
-                if (input_char == option.prefix_code)
-                {
-                    static int count = 0;
-                    if (count++ == 1)
-                    {
-                        // Do not forward prefix characters excessively
-                        count = 0;
-                        break;
-                    }
-
-                    /* Forward prefix character to tty */
-                    *output_char = option.prefix_code;
-                    *forward = true;
-                    break;
-                }
-
                 /* Ignore unknown ctrl-t escaped keys */
                 break;
         }
     }
+
+    previous_char = input_char;
 }
 
 void stdin_restore(void)
@@ -907,7 +1023,7 @@ void tty_wait_for_device(void)
     int    status;
     int    maxfd;
     struct timeval tv;
-    static char input_char, previous_char = 0;
+    static char input_char;
     static bool first = true;
     static int last_errno = 0;
 
@@ -933,19 +1049,19 @@ void tty_wait_for_device(void)
             }
 
             FD_ZERO(&rdfs);
-            FD_SET(STDIN_FILENO, &rdfs);
-            maxfd = MAX(STDIN_FILENO, socket_add_fds(&rdfs, false));
+            FD_SET(pipefd[0], &rdfs);
+            maxfd = MAX(pipefd[0], socket_add_fds(&rdfs, false));
 
             /* Block until input becomes available or timeout */
             status = select(maxfd + 1, &rdfs, NULL, NULL, &tv);
             if (status > 0)
             {
-                if (FD_ISSET(STDIN_FILENO, &rdfs))
+                if (FD_ISSET(pipefd[0], &rdfs))
                 {
                     /* Input from stdin ready */
 
                     /* Read one character */
-                    status = read(STDIN_FILENO, &input_char, 1);
+                    status = read(pipefd[0], &input_char, 1);
                     if (status <= 0)
                     {
                         tio_error_printf("Could not read from stdin");
@@ -953,9 +1069,7 @@ void tty_wait_for_device(void)
                     }
 
                     /* Handle commands */
-                    handle_command_sequence(input_char, previous_char, NULL, NULL);
-
-                    previous_char = input_char;
+                    handle_command_sequence(input_char, NULL, NULL);
                 }
                 socket_handle_input(&rdfs, NULL);
             }
@@ -1077,7 +1191,6 @@ int tty_connect(void)
     int    maxfd;          /* Maximum file descriptor used */
     char   input_char, output_char;
     char   input_buffer[BUFSIZ];
-    static char previous_char = 0;
     static bool first = true;
     int    status;
     bool   next_timestamp = false;
@@ -1189,9 +1302,9 @@ int tty_connect(void)
         FD_SET(fd, &rdfs);
         if (!ignore_stdin)
         {
-            FD_SET(STDIN_FILENO, &rdfs);
+            FD_SET(pipefd[0], &rdfs);
         }
-        maxfd = MAX(fd, STDIN_FILENO);
+        maxfd = MAX(fd, pipefd[0]);
         maxfd = MAX(maxfd, socket_add_fds(&rdfs, true));
 
         /* Manage timeout */
@@ -1298,10 +1411,10 @@ int tty_connect(void)
                     }
                 }
             }
-            else if (FD_ISSET(STDIN_FILENO, &rdfs))
+            else if (FD_ISSET(pipefd[0], &rdfs))
             {
                 /* Input from stdin ready */
-                ssize_t bytes_read = read(STDIN_FILENO, input_buffer, BUFSIZ);
+                ssize_t bytes_read = read(pipefd[0], input_buffer, BUFSIZ);
                 if (bytes_read < 0)
                 {
                     tio_error_printf_silent("Could not read from stdin (%s)", strerror(errno));
@@ -1345,10 +1458,7 @@ int tty_connect(void)
                         }
 
                         /* Handle commands */
-                        handle_command_sequence(input_char, previous_char, &output_char, &forward);
-
-                        /* Save previous key */
-                        previous_char = input_char;
+                        handle_command_sequence(input_char, &output_char, &forward);
 
                         if ((option.hex_mode) && (forward))
                         {
@@ -1370,6 +1480,7 @@ int tty_connect(void)
             }
             else
             {
+                /* Input from socket ready */
                 forward = socket_handle_input(&rdfs, &output_char);
 
                 if (forward)
index 14d1779dcb5cff66d825c6f78af23fe34acb4dc6..c4b67974971cb7e3e8f028c898fce214d8b1aa07 100644 (file)
--- a/src/tty.h
+++ b/src/tty.h
@@ -31,3 +31,5 @@ void tty_configure(void);
 int tty_connect(void);
 void tty_wait_for_device(void);
 void list_serial_devices(void);
+void tty_input_thread_create(void);
+void tty_input_thread_wait_ready(void);