Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package tio for openSUSE:Factory checked in 
at 2022-06-09 14:11:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/tio (Old)
 and      /work/SRC/openSUSE:Factory/.tio.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "tio"

Thu Jun  9 14:11:57 2022 rev:5 rq:981391 version:1.38

Changes:
--------
--- /work/SRC/openSUSE:Factory/tio/tio.changes  2022-04-22 21:55:36.390898448 
+0200
+++ /work/SRC/openSUSE:Factory/.tio.new.1548/tio.changes        2022-06-09 
14:12:08.400555966 +0200
@@ -1,0 +2,25 @@
+Thu Jun  2 09:05:15 UTC 2022 - Martin Hauke <mar...@gmx.de>
+
+- Update to version 1.38
+  * Redirect error messages to stderr
+  * Improve help and man page
+  * Mention config file in --help
+  * Fix running without config file
+  * Fix config file error messages
+  * Redirect error messages to stderr
+  * Add repology packaging status
+  * Fix parsing of default settings
+  * Default configuration file settings were not parsed in case a
+    section was matched. Now we make sure that the default
+    (unnamed) settings are always parsed.
+  * Append to existing log file (no truncation)
+  * Add socket info to show configuration
+  * Print socket info at startup
+  * Fix socket option parsing
+  * Match user input against config section names if pattern
+    matching was unsuccessful.
+  * Add support for external control via a Unix domain socket.
+  * fix for using option 'log' without 'log-filename' in config
+    file.
+
+-------------------------------------------------------------------

Old:
----
  tio-1.37.tar.xz

New:
----
  tio-1.38.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ tio.spec ++++++
--- /var/tmp/diff_new_pack.glWpnB/_old  2022-06-09 14:12:09.048556834 +0200
+++ /var/tmp/diff_new_pack.glWpnB/_new  2022-06-09 14:12:09.052556840 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           tio
-Version:        1.37
+Version:        1.38
 Release:        0
 Summary:        Simple TTY terminal I/O application
 License:        GPL-2.0-or-later

++++++ tio-1.37.tar.xz -> tio-1.38.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/AUTHORS new/tio-1.38/AUTHORS
--- old/tio-1.37/AUTHORS        2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/AUTHORS        2022-06-02 09:36:36.000000000 +0200
@@ -32,5 +32,6 @@
 attila-v <attil...@index.hu>
 Yin Fengwei <fengwei....@intel.com>
 Liam Beguin <liambeg...@gmail.com>
+Peter Collingbourne <p...@google.com>
 
 Thanks to everyone who has contributed to this project.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/ChangeLog new/tio-1.38/ChangeLog
--- old/tio-1.37/ChangeLog      2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/ChangeLog      2022-06-02 09:36:36.000000000 +0200
@@ -1,4 +1,88 @@
-=== tio v1.37 ===
+=== tio v1.38 ===
+
+
+
+Changes since tio v1.37:
+
+ * Redirect error messages to stderr
+
+ * Improve help and man page
+
+ * Mention config file in --help
+
+ * Fix running without config file
+
+ * Fix config file error messages
+
+ * Redirect error messages to stderr
+
+ * Add repology packaging status
+
+ * Fix parsing of default settings
+
+   Default configuration file settings were not parsed in case a section
+   was matched. Now we make sure that the default (unnamed) settings are
+   always parsed.
+
+ * Append to existing log file (no truncation)
+
+ * Add socket info to show configuration
+
+ * Print socket info at startup
+
+ * Fix socket option parsing
+
+Peter Collingbourne:
+
+ * Match user input against config section names if pattern matching was 
unsuccessful.
+
+   This allows for better config file ergonomics if the user has a diverse
+   set of serial devices as the name does not need to be specified in
+   the config file twice.
+
+ * Add support for external control via a Unix domain socket.
+
+   This feature allows an external program to inject output into and
+   listen to input from a serial port via a Unix domain socket (path
+   specified via the -S/--socket command line flag, or the socket
+   config file option) while tio is running. This is useful for ad-hoc
+   scripting of serial port interactions while still permitting manual
+   control. Since many serial devices (at least on Linux) get confused
+   when opened by multiple processes, and most commands do not know
+   how to correctly open a serial device, this allows a more convenient
+   usage model than directly writing to the device node from an external
+   program.
+
+   Any input from clients connected to the socket is sent on the serial
+   port as if entered at the terminal where tio is running (except that
+   ctrl-t sequences are not recognized), and any input from the serial
+   port is multiplexed to the terminal and all connected clients.
+
+   Sockets remain open while the serial port is disconnected, and writes
+   will block.
+
+   Example usage 1 (issue a command):
+
+     echo command | nc -UN /path/to/socket > /dev/null
+
+   Example usage 2 (use the expect command to script an interaction):
+
+     #!/usr/bin/expect -f
+
+     set timeout -1
+     log_user 0
+
+     spawn nc -UN /path/to/socket
+     set uart $spawn_id
+
+     send -i $uart "command1\n"
+     expect -i $uart "prompt> "
+     send -i $uart "command2\n"
+     expect -i $uart "prompt> "
+
+lexaone:
+
+ * fix for using option 'log' without 'log-filename' in config file
 
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/README.md new/tio-1.38/README.md
--- old/tio-1.37/README.md      2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/README.md      2022-06-02 09:36:36.000000000 +0200
@@ -2,6 +2,7 @@
 
 
[![CircleCI](https://circleci.com/gh/tio/tio/tree/master.svg?style=shield)](https://circleci.com/gh/tio/tio/tree/master)
 [![tio](https://snapcraft.io/tio/badge.svg)](https://snapcraft.io/tio)
+[![Packaging 
status](https://repology.org/badge/tiny-repos/tio.svg)](https://repology.org/project/tio/versions)
 
 ## 1. Introduction
 
@@ -24,7 +25,7 @@
 The command-line interface is straightforward as reflected in the output from
 'tio --help':
 ```
-    Usage: tio [<options>] <tty-device>
+    Usage: tio [<options>] <tty-device|config>
 
     Options:
       -b, --baudrate <bps>        Baud rate (default: 115200)
@@ -40,12 +41,15 @@
       -l, --log <filename>        Log to file
       -m, --map <flags>           Map special characters
       -c, --color <0..255>        Colorize tio text
+      -S, --socket <socket>       Listen on socket
       -v, --version               Display version
       -h, --help                  Display help
 
-    See the man page for more details.
+    Options may be set via configuration file.
 
     In session, press ctrl-t q to quit.
+
+    See the man page for more details.
 ```
 
 The only option which requires a bit of elaboration is perhaps the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/man/tio.1.in new/tio-1.38/man/tio.1.in
--- old/tio-1.37/man/tio.1.in   2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/man/tio.1.in   2022-06-02 09:36:36.000000000 +0200
@@ -6,13 +6,13 @@
 .SH "SYNOPSIS"
 .PP
 .B tio
-.RI "[" <options> "] " "<tty-device>"
+.RI "[" <options> "] " "<tty-device|config>"
 
 .SH "DESCRIPTION"
 .PP
 .B tio
 is a simple serial terminal tool which features a straightforward command-line
-interface to easily connect to serial/TTY devices for basic I/O operations.
+interface to easily connect to serial TTY devices for basic I/O operations.
 
 .SH "OPTIONS"
 
@@ -115,6 +115,23 @@
 If color code is negative a list of available ANSI colors will be printed.
 
 .TP
+.BR \-S ", " "\-\-socket \fI<socket>\fR\fB
+
+Listen on socket. Any input from clients connected to the socket is sent on 
the serial port as if entered at the terminal where tio is running (except that
+.B ctrl-t
+sequences are not recognized), and any input from the serial port is 
multiplexed to the terminal and all connected clients.
+
+Sockets remain open while the serial port is disconnected, and writes will 
block.
+
+Two socket types are supported using different prefixes in the socket field:
+
+unix:<filename> - Unix Domain Socket (file)
+
+inet:<IP>:<port> - Internet Socket (network) (NOT YET SUPPORTED)
+
+At present there is a hardcoded limit of 16 clients connected at one time.
+
+.TP
 .BR \-v ", " \-\-version
 
 Display program version.
@@ -159,14 +176,14 @@
 Options can be set via a configuration file using the INI format. tio uses the 
configuration file first found in the following locations in the order listed: 
$XDG_CONFIG_HOME/tio/tiorc, $HOME/.config/tio/tiorc, $HOME/.tiorc
 
 .TP
-Sections can be used to group settings and their names are only used for 
readability.
+Config sections can be used to group settings.
 
 .TP
 .TP
-tio will try to match the user input to a section pattern to get the tty and 
other options.
+tio will try to match the user input to a config section by name or by pattern 
to get the tty and other options.
 
 .TP
-Options without any section name sets the default options.
+Options without any config section name sets the default options.
 
 .TP
 The following configuration file options are available:
@@ -201,17 +218,19 @@
 Map special characters on input or output
 .IP "\fBcolor"
 Colorize tio text using ANSI color code ranging from 0 to 255.
+.IP "\fBsocket"
+Set socket path (must include
+.BR unix: ).
 
 .SH "CONFIGURATION EXAMPLES"
 
 .TP
-A Typical section used as a short-hand would be defined as such:
+A typical config section used as a short-hand would be defined as such:
 
 .RS
 .nf
 .eo
-[ftdi device]
-pattern=ftdi
+[ftdi]
 baudrate=115200
 tty=/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 color=11
@@ -220,14 +239,14 @@
 .RE
 
 .TP
-With this section defined in the configuration file the following commands 
would be equivalent:
+With this config section defined in the configuration file the following 
commands would be equivalent:
 
 tio ftdi
 
 tio -b 115200 /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0
 
 .TP
-A pattern can also be a regular expression:
+A config section can also be matched by its pattern which supports regular 
expressions:
 
 .RS
 .nf
@@ -270,4 +289,4 @@
 
 .SH "AUTHOR"
 .PP
-Written by Martin Lund <martin.lund@keep\-it\-simple.com>.
+Created by Martin Lund <martin.lund@keep\-it\-simple.com>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/meson.build new/tio-1.38/meson.build
--- old/tio-1.37/meson.build    2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/meson.build    2022-06-02 09:36:36.000000000 +0200
@@ -1,12 +1,12 @@
 project('tio', 'c',
-    version : '1.37',
+    version : '1.38',
     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-04-13'
+version_date = '2022-06-02'
 
 # Test for dynamic baudrate configuration interface
 compiler = meson.get_compiler('c')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/bash-completion/tio.in 
new/tio-1.38/src/bash-completion/tio.in
--- old/tio-1.37/src/bash-completion/tio.in     2022-04-13 18:00:34.000000000 
+0200
+++ new/tio-1.38/src/bash-completion/tio.in     2022-06-02 09:36:36.000000000 
+0200
@@ -80,6 +80,10 @@
             COMPREPLY=( $(compgen -W "$(seq 0 255)" -- ${cur}) )
             return 0
             ;;
+        -S | --socket)
+            COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+            return 0
+            ;;
         -v | --version)
             COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
             return 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/configfile.c 
new/tio-1.38/src/configfile.c
--- old/tio-1.37/src/configfile.c       2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/configfile.c       2022-06-02 09:36:36.000000000 +0200
@@ -56,7 +56,7 @@
     if (ret)
     {
         regerror(ret, &re, err, sizeof(err));
-        printf("reg error: %s\n", err);
+        fprintf(stderr, "regex error: %s", err);
         return ret;
     }
 
@@ -152,19 +152,24 @@
         {
             option.color = atoi(value);
         }
+        else if (!strcmp(name, "socket"))
+        {
+            asprintf(&c->socket, "%s", value);
+            option.socket = c->socket;
+        }
     }
     return 0;
 }
 
 /**
- * section_search_handler() - walk config file to find section matching user 
input
+ * section_pattern_search_handler() - walk config file to find section 
matching user input
  *
  * INIH handler used to resolve the section matching the user's input.
  * This will look for the pattern element of each section and try to match it
  * with the user input.
  */
-static int section_search_handler(void *user, const char *section, const char
-                                  *varname, const char *varval)
+static int section_pattern_search_handler(void *user, const char *section, 
const char *varname,
+                                          const char *varval)
 {
     UNUSED(user);
 
@@ -185,6 +190,28 @@
     return 0;
 }
 
+/**
+ * section_pattern_search_handler() - walk config file to find section 
matching user input
+ *
+ * INIH handler used to resolve the section matching the user's input.
+ * This will try to match the user input against a section with the name of 
the user input.
+ */
+static int section_name_search_handler(void *user, const char *section, const 
char *varname,
+                                       const char *varval)
+{
+    UNUSED(user);
+    UNUSED(varname);
+    UNUSED(varval);
+
+    if (!strcmp(section, c->user))
+    {
+        /* section name matches as plain text */
+        asprintf(&c->section_name, "%s", section);
+    }
+
+    return 0;
+}
+
 static int resolve_config_file(void)
 {
     asprintf(&c->path, "%s/tio/tiorc", getenv("XDG_CONFIG_HOME"));
@@ -216,7 +243,12 @@
     c = malloc(sizeof(struct config_t));
     memset(c, 0, sizeof(struct config_t));
 
-    resolve_config_file();
+    // Find config file
+    if (resolve_config_file() != 0)
+    {
+        // None found - stop parsing
+        return;
+    }
 
     for (i = 1; i < argc; i++)
     {
@@ -232,17 +264,33 @@
         return;
     }
 
-    ret = ini_parse(c->path, section_search_handler, NULL);
+    // Parse default (unnamed) settings
+    asprintf(&c->section_name, "%s", "");
+    ret = ini_parse(c->path, data_handler, NULL);
+    if (ret < 0)
+    {
+        fprintf(stderr, "Error: Unable to parse configuration file (%d)", ret);
+        exit(EXIT_FAILURE);
+    }
+    c->section_name = NULL;
+
+    // Find matching section
+    ret = ini_parse(c->path, section_pattern_search_handler, NULL);
     if (!c->section_name)
     {
-        debug_printf("unable to match user input to configuration section 
(%d)\n", ret);
-        return;
+        ret = ini_parse(c->path, section_name_search_handler, NULL);
+        if (!c->section_name)
+        {
+            debug_printf("Unable to match user input to configuration section 
(%d)", ret);
+            return;
+        }
     }
 
+    // Parse settings of found section
     ret = ini_parse(c->path, data_handler, NULL);
     if (ret < 0)
     {
-        fprintf(stderr, "Error: unable to parse configuration file (%d)\n", 
ret);
+        fprintf(stderr, "Error: Unable to parse configuration file (%d)", ret);
         exit(EXIT_FAILURE);
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/configfile.h 
new/tio-1.38/src/configfile.h
--- old/tio-1.37/src/configfile.h       2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/configfile.h       2022-06-02 09:36:36.000000000 +0200
@@ -34,6 +34,7 @@
        char *flow;
        char *parity;
        char *log_filename;
+       char *socket;
        char *map;
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/error.c new/tio-1.38/src/error.c
--- old/tio-1.37/src/error.c    2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/error.c    2022-06-02 09:36:36.000000000 +0200
@@ -35,11 +35,11 @@
   if (error[0][0] != 0)
   {
     /* Print error */
-    tio_printf("Error: %s", error[0]);
+    tio_error_printf("Error: %s", error[0]);
   }
   else if ((error[1][0] != 0) && (option.no_autoconnect))
   {
     /* Print silent error */
-    tio_printf("Error: %s", error[1]);
+    tio_error_printf("Error: %s", error[1]);
   }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/log.c new/tio-1.38/src/log.c
--- old/tio-1.37/src/log.c      2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/log.c      2022-06-02 09:36:36.000000000 +0200
@@ -60,7 +60,7 @@
         option.log_filename = automatic_filename;
     }
 
-    fp = fopen(filename, "w+");
+    fp = fopen(filename, "a+");
 
     if (fp == NULL)
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/main.c new/tio-1.38/src/main.c
--- old/tio-1.37/src/main.c     2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/main.c     2022-06-02 09:36:36.000000000 +0200
@@ -30,6 +30,7 @@
 #include "error.h"
 #include "print.h"
 #include "signals.h"
+#include "socket.h"
 
 int main(int argc, char *argv[])
 {
@@ -78,6 +79,9 @@
     tio_printf("tio v%s", VERSION);
     tio_printf("Press ctrl-t q to quit");
 
+    /* Open socket */
+    socket_configure();
+
     /* Connect to tty device */
     if (option.no_autoconnect)
         status = tty_connect();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/meson.build new/tio-1.38/src/meson.build
--- old/tio-1.37/src/meson.build        2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/meson.build        2022-06-02 09:36:36.000000000 +0200
@@ -12,7 +12,8 @@
   'tty.c',
   'print.c',
   'configfile.c',
-  'signals.c'
+  'signals.c',
+  'socket.c'
 ]
 
 tio_dep = dependency('inih', required: true,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/options.c new/tio-1.38/src/options.c
--- old/tio-1.37/src/options.c  2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/options.c  2022-06-02 09:36:36.000000000 +0200
@@ -50,14 +50,15 @@
     .local_echo = false,
     .timestamp = TIMESTAMP_NONE,
     .list_devices = false,
-    .log_filename = "",
+    .log_filename = NULL,
+    .socket = NULL,
     .map = "",
     .color = -1,
 };
 
 void print_help(char *argv[])
 {
-    printf("Usage: %s [<options>] <tty-device>\n", argv[0]);
+    printf("Usage: %s [<options>] <tty-device|config>\n", argv[0]);
     printf("\n");
     printf("Options:\n");
     printf("  -b, --baudrate <bps>        Baud rate (default: 115200)\n");
@@ -73,13 +74,17 @@
     printf("  -l, --log[=<filename>]      Log to file\n");
     printf("  -m, --map <flags>           Map special characters\n");
     printf("  -c, --color <code>          Colorize tio text\n");
+    printf("  -S, --socket <socket>       Listen on socket\n");
     printf("  -v, --version               Display version\n");
     printf("  -h, --help                  Display help\n");
     printf("\n");
-    printf("See the man page for more details.\n");
+    printf("Options may be set via configuration file.\n");
     printf("\n");
     printf("In session, press ctrl-t q to quit.\n");
     printf("\n");
+    printf("See the man page for more details.\n");
+    printf("\n");
+
 }
 
 const char* timestamp_token(enum timestamp_t timestamp)
@@ -147,6 +152,8 @@
         tio_printf(" Map flags: %s", option.map);
     if (option.log)
         tio_printf(" Log file: %s", option.log_filename);
+    if (option.socket)
+        tio_printf(" Socket: %s", option.socket);
 }
 
 void options_parse(int argc, char *argv[])
@@ -174,6 +181,7 @@
             {"timestamp",      optional_argument, 0, 't'},
             {"list-devices",   no_argument,       0, 'L'},
             {"log",            optional_argument, 0, 'l'},
+            {"socket",         required_argument, 0, 'S'},
             {"map",            required_argument, 0, 'm'},
             {"color",          required_argument, 0, 'c'},
             {"version",        no_argument,       0, 'v'},
@@ -185,7 +193,7 @@
         int option_index = 0;
 
         /* Parse argument using getopt_long */
-        c = getopt_long(argc, argv, "b:d:f:s:p:o:net::Ll::m:c:vh", 
long_options, &option_index);
+        c = getopt_long(argc, argv, "b:d:f:s:p:o:net::Ll::S:m:c:vh", 
long_options, &option_index);
 
         /* Detect the end of the options */
         if (c == -1)
@@ -248,6 +256,10 @@
                 option.log_filename = optarg;
                 break;
 
+            case 'S':
+                option.socket = optarg;
+                break;
+
             case 'm':
                 option.map = optarg;
                 break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/options.h new/tio-1.38/src/options.h
--- old/tio-1.37/src/options.h  2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/options.h  2022-06-02 09:36:36.000000000 +0200
@@ -53,6 +53,7 @@
     bool list_devices;
     const char *log_filename;
     const char *map;
+    const char *socket;
     int color;
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/print.h new/tio-1.38/src/print.h
--- old/tio-1.37/src/print.h    2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/print.h    2022-06-02 09:36:36.000000000 +0200
@@ -36,6 +36,12 @@
   fflush(stdout); \
 }
 
+#define ansi_error_printf(format, args...) \
+{ \
+  fprintf (stderr, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \
+  fflush(stderr); \
+}
+
 #define ansi_printf_raw(format, args...) \
 { \
   fprintf (stdout, "%s" format ANSI_RESET, ansi_format, ## args); \
@@ -56,6 +62,14 @@
   print_tainted = false; \
 }
 
+#define tio_error_printf(format, args...) \
+{ \
+  if (print_tainted) \
+    putchar('\n'); \
+  ansi_error_printf("[%s] " format, current_time(), ## args); \
+  print_tainted = false; \
+}
+
 #define error_printf(format, args...) \
   snprintf(error[0], 1000, format, ## args);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/socket.c new/tio-1.38/src/socket.c
--- old/tio-1.37/src/socket.c   1970-01-01 01:00:00.000000000 +0100
+++ new/tio-1.38/src/socket.c   2022-06-02 09:36:36.000000000 +0200
@@ -0,0 +1,197 @@
+/*
+ * tio - a simple serial terminal I/O tool
+ *
+ * Copyright (c) 2014-2022  Martin Lund
+ * Copyright (c) 2022  Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "socket.h"
+#include "options.h"
+#include "print.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define MAX_SOCKET_CLIENTS 16
+
+static int sockfd;
+static int clientfds[MAX_SOCKET_CLIENTS];
+
+static const char *socket_filename(void)
+{
+    /* skip 'unix:' */
+    return option.socket + 5;
+}
+
+static void socket_exit(void)
+{
+    unlink(socket_filename());
+}
+
+void socket_configure(void)
+{
+    if (!option.socket)
+    {
+        return;
+    }
+
+    if (strncmp(option.socket, "unix:", 5) != 0)
+    {
+        error_printf("%s: Invalid socket scheme, must be 'unix:'", 
option.socket);
+        exit(EXIT_FAILURE);
+    }
+
+    struct sockaddr_un sockaddr = {};
+    if (strlen(socket_filename()) > sizeof(sockaddr.sun_path) - 1)
+    {
+        error_printf("Socket file path %s too long", option.socket);
+        exit(EXIT_FAILURE);
+    }
+ 
+    sockaddr.sun_family = AF_UNIX;
+    strncpy(sockaddr.sun_path, socket_filename(), sizeof(sockaddr.sun_path) - 
1);
+
+    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sockfd < 0)
+    {
+        error_printf("Failed to create socket: %s", strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    unlink(socket_filename());
+    if (bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0)
+    {
+        error_printf("Failed to bind to socket %s: %s", socket_filename(), 
strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    if (listen(sockfd, MAX_SOCKET_CLIENTS) < 0)
+    {
+        error_printf("Failed to listen on socket %s: %s", socket_filename(), 
strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    memset(clientfds, -1, sizeof(clientfds));
+    atexit(socket_exit);
+
+    tio_printf("Listening on socket %s", socket_filename());
+}
+
+void socket_write(char input_char)
+{
+    if (!option.socket)
+    {
+        return;
+    }
+
+    for (int i = 0; i != MAX_SOCKET_CLIENTS; ++i)
+    {
+        if (clientfds[i] != -1)
+        {
+            if (write(clientfds[i], &input_char, 1) <= 0)
+            {
+                error_printf_silent("Failed to write to socket: %s", 
strerror(errno));
+                close(clientfds[i]);
+                clientfds[i] = -1;
+            }
+        }
+    }
+}
+
+int socket_add_fds(fd_set *rdfs, bool connected)
+{
+    if (!option.socket)
+    {
+        return 0;
+    }
+
+    int numclients = 0, maxfd = 0;
+    for (int i = 0; i != MAX_SOCKET_CLIENTS; ++i)
+    {
+        if (clientfds[i] != -1)
+        {
+            /* let clients block if they try to send while we're disconnected 
*/
+            if (connected)
+            {
+                FD_SET(clientfds[i], rdfs);
+                maxfd = MAX(maxfd, clientfds[i]);
+            }
+            numclients++;
+        }
+    }
+    /* don't bother to accept clients if we're already full */
+    if (numclients != MAX_SOCKET_CLIENTS)
+    {
+        FD_SET(sockfd, rdfs);
+        maxfd = MAX(maxfd, sockfd);
+    }
+    return maxfd;
+}
+
+bool socket_handle_input(fd_set *rdfs, char *output_char)
+{
+    if (!option.socket)
+    {
+        return false;
+    }
+
+    if (FD_ISSET(sockfd, rdfs))
+    {
+        int clientfd = accept(sockfd, NULL, NULL);
+        /* this loop should always succeed because we don't select on sockfd 
when full */
+        for (int i = 0; i != MAX_SOCKET_CLIENTS; ++i)
+        {
+            if (clientfds[i] == -1)
+            {
+                clientfds[i] = clientfd;
+                break;
+            }
+        }
+    }
+    for (int i = 0; i != MAX_SOCKET_CLIENTS; ++i)
+    {
+        if (clientfds[i] != -1 && FD_ISSET(clientfds[i], rdfs))
+        {
+            int status = read(clientfds[i], output_char, 1);
+            if (status == 0)
+            {
+                close(clientfds[i]);
+                clientfds[i] = -1;
+                continue;
+            }
+            if (status < 0)
+            {
+                error_printf_silent("Failed to read from socket: %s", 
strerror(errno));
+                close(clientfds[i]);
+                clientfds[i] = -1;
+                continue;
+            }
+            /* match the behavior of a terminal in raw mode */
+            if (*output_char == '\n')
+            {
+                *output_char = '\r';
+            }
+            return true;
+        }
+    }
+    return false;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/socket.h new/tio-1.38/src/socket.h
--- old/tio-1.37/src/socket.h   1970-01-01 01:00:00.000000000 +0100
+++ new/tio-1.38/src/socket.h   2022-06-02 09:36:36.000000000 +0200
@@ -0,0 +1,31 @@
+/*
+ * tio - a simple serial terminal I/O tool
+ *
+ * Copyright (c) 2014-2022  Martin Lund
+ * Copyright (c) 2022  Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <sys/select.h>
+
+void socket_configure(void);
+void socket_write(char input_char);
+int socket_add_fds(fd_set *fds, bool connected);
+bool socket_handle_input(fd_set *fds, char *output_char);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tio-1.37/src/tty.c new/tio-1.38/src/tty.c
--- old/tio-1.37/src/tty.c      2022-04-13 18:00:34.000000000 +0200
+++ new/tio-1.38/src/tty.c      2022-06-02 09:36:36.000000000 +0200
@@ -31,6 +31,8 @@
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <fcntl.h>
 #include <termios.h>
 #include <stdbool.h>
@@ -45,6 +47,7 @@
 #include "misc.h"
 #include "log.h"
 #include "error.h"
+#include "socket.h"
 
 #ifdef HAVE_TERMIOS2
 extern int setspeed2(int fd, int baudrate);
@@ -164,7 +167,7 @@
                 break;
 
             case KEY_C:
-                tio_printf("Configuraiton:");
+                tio_printf("Configuration:");
                 config_file_print();
                 options_print();
                 break;
@@ -494,6 +497,7 @@
 {
     fd_set rdfs;
     int    status;
+    int    maxfd;
     struct timeval tv;
     static char input_char, previous_char = 0;
     static bool first = true;
@@ -517,26 +521,30 @@
 
         FD_ZERO(&rdfs);
         FD_SET(STDIN_FILENO, &rdfs);
+        maxfd = MAX(STDIN_FILENO, socket_add_fds(&rdfs, false));
 
         /* Block until input becomes available or timeout */
-        status = select(STDIN_FILENO + 1, &rdfs, NULL, NULL, &tv);
+        status = select(maxfd + 1, &rdfs, NULL, NULL, &tv);
         if (status > 0)
         {
-            /* Input from stdin ready */
-
-            /* Read one character */
-            status = read(STDIN_FILENO, &input_char, 1);
-            if (status <= 0)
+            if (FD_ISSET(STDIN_FILENO, &rdfs))
             {
-                error_printf("Could not read from stdin");
-                exit(EXIT_FAILURE);
-            }
+                /* Input from stdin ready */
 
-            /* Handle commands */
-            handle_command_sequence(input_char, previous_char, NULL, NULL);
+                /* Read one character */
+                status = read(STDIN_FILENO, &input_char, 1);
+                if (status <= 0)
+                {
+                    error_printf("Could not read from stdin");
+                    exit(EXIT_FAILURE);
+                }
 
-            previous_char = input_char;
+                /* Handle commands */
+                handle_command_sequence(input_char, previous_char, NULL, NULL);
 
+                previous_char = input_char;
+            }
+            socket_handle_input(&rdfs, NULL);
         } else if (status == -1)
         {
             error_printf("select() failed (%s)", strerror(errno));
@@ -686,19 +694,20 @@
     }
 #endif
 
-    maxfd = MAX(fd, STDIN_FILENO) + 1;  /* Maximum bit entry (fd) to test */
-
     /* Input loop */
     while (true)
     {
         FD_ZERO(&rdfs);
         FD_SET(fd, &rdfs);
         FD_SET(STDIN_FILENO, &rdfs);
+        maxfd = MAX(fd, STDIN_FILENO);
+        maxfd = MAX(maxfd, socket_add_fds(&rdfs, true));
 
         /* Block until input becomes available */
-        status = select(maxfd, &rdfs, NULL, NULL, NULL);
+        status = select(maxfd + 1, &rdfs, NULL, NULL, NULL);
         if (status > 0)
         {
+            bool forward = false;
             if (FD_ISSET(fd, &rdfs))
             {
                 /* Input from tty device ready */
@@ -747,6 +756,8 @@
                     if (option.log)
                         log_write(input_char);
 
+                    socket_write(input_char);
+
                     print_tainted = true;
 
                     if (input_char == '\n' && option.timestamp)
@@ -760,7 +771,7 @@
             }
             if (FD_ISSET(STDIN_FILENO, &rdfs))
             {
-                bool forward = true;
+                forward = true;
 
                 /* Input from stdin ready */
                 status = read(STDIN_FILENO, &input_char, 1);
@@ -778,46 +789,50 @@
                 /* Handle commands */
                 handle_command_sequence(input_char, previous_char, 
&output_char, &forward);
 
-                if (forward)
-                {
-                    /* Map output character */
-                    if ((output_char == 127) && (map_o_del_bs))
-                        output_char = '\b';
-                    if ((output_char == '\r') && (map_o_cr_nl))
-                        output_char = '\n';
-
-                    /* Map newline character */
-                    if ((output_char == '\n' || output_char == '\r') && 
(map_o_nl_crnl)) {
-                        const char *crlf = "\r\n";
-
-                        optional_local_echo(crlf[0]);
-                        optional_local_echo(crlf[1]);
-                        status = write(fd, crlf, 2);
-                        if (status < 0)
-                            warning_printf("Could not write to tty device");
+                /* Save previous key */
+                previous_char = input_char;
 
-                        tx_total += 2;
-                        delay(option.output_delay);
-                    } else
-                    {
-                        /* Send output to tty device */
-                        optional_local_echo(output_char);
-                        status = write(fd, &output_char, 1);
-                        if (status < 0)
-                            warning_printf("Could not write to tty device");
-                        fsync(fd);
+            }
+            else
+            {
+                forward = socket_handle_input(&rdfs, &output_char);
+            }
 
-                        /* Update transmit statistics */
-                        tx_total++;
+            if (forward)
+            {
+                /* Map output character */
+                if ((output_char == 127) && (map_o_del_bs))
+                    output_char = '\b';
+                if ((output_char == '\r') && (map_o_cr_nl))
+                    output_char = '\n';
+
+                /* Map newline character */
+                if ((output_char == '\n' || output_char == '\r') && 
(map_o_nl_crnl)) {
+                    const char *crlf = "\r\n";
+
+                    optional_local_echo(crlf[0]);
+                    optional_local_echo(crlf[1]);
+                    status = write(fd, crlf, 2);
+                    if (status < 0)
+                        warning_printf("Could not write to tty device");
 
-                        /* Insert output delay */
-                        delay(option.output_delay);
-                    }
-                }
+                    tx_total += 2;
+                    delay(option.output_delay);
+                } else
+                {
+                    /* Send output to tty device */
+                    optional_local_echo(output_char);
+                    status = write(fd, &output_char, 1);
+                    if (status < 0)
+                        warning_printf("Could not write to tty device");
+                    fsync(fd);
 
-                /* Save previous key */
-                previous_char = input_char;
+                    /* Update transmit statistics */
+                    tx_total++;
 
+                    /* Insert output delay */
+                    delay(option.output_delay);
+                }
             }
         } else if (status == -1)
         {

Reply via email to