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-07-06 15:42:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/tio (Old) and /work/SRC/openSUSE:Factory/.tio.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tio" Wed Jul 6 15:42:22 2022 rev:7 rq:987137 version:1.42 Changes: -------- --- /work/SRC/openSUSE:Factory/tio/tio.changes 2022-06-21 16:32:35.155826476 +0200 +++ /work/SRC/openSUSE:Factory/.tio.new.1548/tio.changes 2022-07-06 15:42:37.454572245 +0200 @@ -1,0 +2,15 @@ +Tue Jul 5 05:35:29 UTC 2022 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.42 + * Update man page + * Handle malloc failure + * Add missing 'string.h' include. + +------------------------------------------------------------------- +Mon Jul 4 15:55:37 UTC 2022 - Martin Hauke <mar...@gmx.de> + +- Update to version 1.41 + * Rename --hex-mode to --hexadecimal + * Enable buffered writing / reading + +------------------------------------------------------------------- Old: ---- tio-1.40.tar.xz New: ---- tio-1.42.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tio.spec ++++++ --- /var/tmp/diff_new_pack.I2gPFF/_old 2022-07-06 15:42:37.846572807 +0200 +++ /var/tmp/diff_new_pack.I2gPFF/_new 2022-07-06 15:42:37.846572807 +0200 @@ -17,7 +17,7 @@ Name: tio -Version: 1.40 +Version: 1.42 Release: 0 Summary: Simple TTY terminal I/O application License: GPL-2.0-or-later ++++++ tio-1.40.tar.xz -> tio-1.42.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/AUTHORS new/tio-1.42/AUTHORS --- old/tio-1.40/AUTHORS 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/AUTHORS 2022-07-04 22:42:15.000000000 +0200 @@ -34,5 +34,6 @@ Liam Beguin <liambeg...@gmail.com> Peter Collingbourne <p...@google.com> g0mb4 <gomba...@gmail.com> +ZeroMemoryEx on GitHub Thanks to everyone who has contributed to this project. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/ChangeLog new/tio-1.42/ChangeLog --- old/tio-1.40/ChangeLog 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/ChangeLog 2022-07-04 22:42:15.000000000 +0200 @@ -1,4 +1,48 @@ -=== tio v1.40 === +=== tio v1.42 === + + + +Changes since tio v1.41: + + * Update man page + +ZeroMemoryEx: + + * Handle malloc failure + +Sylvain LAFRASSE: + + * Add missing 'string.h' include. + + + +Changes since tio v1.40: + + * Rename --hex-mode to --hexadecimal + + * Enable buffered writing + + Read block of bytes from input and process same block for output. This + will speed things up by reducing I/O overhead. + + * Enable buffered reading + + Read block of bytes from input and process byte by byte for output. This + will speed things up by reducing I/O overhead. + + * Refactoring + + * Cleanup stdout flushing + + Flushing is not needed since we disabled buffering of stdout. + + * Simplify stdout_configure() code + + * Simplify stdin_configure() code + + * Update man page + + * Update README diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/README.md new/tio-1.42/README.md --- old/tio-1.40/README.md 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/README.md 2022-07-04 22:42:15.000000000 +0200 @@ -16,22 +16,47 @@ ### 1.1 Motivation -To make a simpler serial device tool for talking with TTY devices with less -focus on classic terminal/modem features and more focus on the needs of +To make a simpler serial device tool for talking with serial TTY devices with +less focus on classic terminal/modem features and more focus on the needs of embedded developers and hackers. tio was originally created to replace [screen](https://www.gnu.org/software/screen) for connecting to serial devices when used in combination with [tmux](https://tmux.github.io). -## 2. Usage +## 2. Features -### 2.1 Command-line + * Easily connect to serial TTY devices + * Automatic connect + * Support for arbitrary baud rates + * List available serial devices + * Show RX/TX statistics + * Toggle serial lines + * Local echo support + * Remap special characters (nl, cr-nl, bs, etc.) + * Line timestamps + * Support for delayed output + * Hexadecimal mode + * Log to file + * Autogeneration of log filename + * Configuration file support + * Activate sub-configurations by name or pattern + * Redirect I/O to socket for scripting or TTY sharing + * Pipe input and/or output + * Bash completion + * Color support + * Man page documentation + +## 3. Usage + +### 3.1 Command-line The command-line interface is straightforward as reflected in the output from 'tio --help': ``` - Usage: tio [<options>] <tty-device|config> + Usage: tio [<options>] <tty-device|sub-config> + + Connect to tty-device directly or via sub-configuration. Options: -b, --baudrate <bps> Baud rate (default: 115200) @@ -45,17 +70,17 @@ -t, --timestamp Enable line timestamp --timestamp-format <format> Set timestamp format (default: 24hour) -L, --list-devices List available serial devices - -l, --log Enable logging to file + -l, --log Enable log to file --log-file <filename> Set log filename --log-strip Strip control characters and escape sequences -m, --map <flags> Map special characters -c, --color 0..255|none|list Colorize tio text (default: 15) -S, --socket <socket> Redirect I/O to socket - -x, --hex Enable hexadecimal mode + -x, --hexadecimal Enable hexadecimal mode -v, --version Display version -h, --help Display help - Options may be set via configuration file. + Options and sub-configurations may be set via configuration file. In session, press ctrl-t q to quit. @@ -71,7 +96,7 @@ tio features full bash autocompletion. -### 2.2 Key commands +### 3.2 Key commands Various in session key commands are supported. When tio is started, press ctrl-t ? to list the available key commands. @@ -94,7 +119,7 @@ [20:19:12.041] ctrl-t v Show version ``` -### 2.3 Configuration file +### 3.3 Configuration file Options can be set via the configuration file first found in any of the following locations in the order listed: @@ -139,13 +164,17 @@ ``` -## 3. Installation +## 4. Installation + +### 4.1 Installation using package manager -### 3.1 Installation using package manager Packages for various GNU/Linux distributions are available. Please consult your package manager tool to find and install tio. -### 3.2 Installation using snap +If you would like to see tio included in your favorite distribution, please +reach out to their package maintainers team. + +### 4.2 Installation using snap Install latest stable version: ``` @@ -156,7 +185,7 @@ $ snap install tio --edge ``` -### 3.3 Installation from source +### 4.3 Installation from source The latest source releases can be found [here](https://github.com/tio/tio/releases). @@ -173,7 +202,7 @@ how to build stuff using meson. -## 4. Contributing +## 5. Contributing tio is open source. If you want to help out with the project please feel free to join in. @@ -188,22 +217,22 @@ [![Donate](images/paypal.png)](https://www.paypal.me/lundmar) -## 5. Support +## 6. Support Submit bug reports via GitHub: https://github.com/tio/tio/issues -## 6. Website +## 7. Website Visit [tio.github.io](https://tio.github.io) -## 7. License +## 8. License tio is GPLv2+. See LICENSE file for more details. -## 8. Authors +## 9. Authors Created by Martin Lund \<martin.l...@keep-it-simple.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/TODO new/tio-1.42/TODO --- old/tio-1.40/TODO 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/TODO 2022-07-04 22:42:15.000000000 +0200 @@ -1,4 +1,3 @@ * Improve error/warning messaging when parsing configuration file - * Add support for piping to tio diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/man/tio.1.in new/tio-1.42/man/tio.1.in --- old/tio-1.40/man/tio.1.in 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/man/tio.1.in 2022-07-04 22:42:15.000000000 +0200 @@ -6,7 +6,7 @@ .SH "SYNOPSIS" .PP .B tio -.RI "[" <options> "] " "<tty-device|config>" +.RI "[" <options> "] " "<tty-device|sub-config>" .SH "DESCRIPTION" .PP @@ -87,7 +87,7 @@ .TP .BR \-l ", " \-\-log -Enable logging to file. If no filename is provided the filename will be automatically generated. +Enable log to file. If no filename is provided the filename will be automatically generated. .TP .BR " \-\-log-file \fI<filename> @@ -124,7 +124,7 @@ .RE .TP -.BR \-x ", " \-\-hex\-mode +.BR \-x ", " \-\-hexadecimal Enable hexadecimal mode. @@ -207,20 +207,29 @@ .TP Bytes can be sent in this mode by typing the \fBtwo-character hexadecimal\fR representation of the value, e.g.: to send \fI0xA\fR you must type \fI0a\fR or \fI0A\fR. -.SH "CONFIGURATION" +.SH "CONFIGURATION FILE" .PP .TP 16n -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 +Options can be set via configuration file using the INI format. tio uses the configuration file first found in the following locations in the order listed: +.PP +.I $XDG_CONFIG_HOME/tio/tiorc +.PP +.I $HOME/.config/tio/tiorc +.PP +.I $HOME/.tiorc .TP -Config sections can be used to group settings. +Labels can be used to group settings into named sub-configurations which can be activated from the command-line when starting tio. .TP .TP -tio will try to match the user input to a config section 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 and other options. .TP -Options without any config section name sets the default options. +Options without any label change the default options. + +.TP +Any options set via command-line will override options set in the configuraqtion file. .TP The following configuration file options are available: @@ -229,7 +238,7 @@ .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 tty contains a "%s" it will be substituted with the first group match. +tty device to open. If it contains a "%s" it is substituted with the first group match. .IP "\fBbaudrate" Set baud rate .IP "\fBdatabits" @@ -245,7 +254,7 @@ .IP "\fBno-autoconnect" Disable automatic connect .IP "\fBlog" -Enable logging to file +Enable log to file .IP "\fBlog-file" Set log filename .IP "\fBlog-strip" @@ -260,58 +269,85 @@ Map special characters on input or output .IP "\fBcolor" Colorize tio text using ANSI color code ranging from 0 to 255 -.IP "\fBhex-mode" +.IP "\fBhexadecimal" Enable hexadecimal mode .IP "\fBsocket" Set socket to redirect I/O to -.SH "CONFIGURATION EXAMPLES" +.SH "CONFIGURATION FILE EXAMPLES" .TP -A typical config section used as a short-hand would be defined as such: +To change the default configuration simply set options like so: + +.RS +.nf +.eo +# Defaults +baudrate = 115200 +databits = 8 +parity = none +stopbits = 1 +color = 10 +.ec +.fi +.RE + +.TP +Named sub-configurations can be added via labels: .RS .nf .eo [ftdi] -baudrate=115200 -tty=/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0 -color=11 +baudrate = 115200 +tty = /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0 +color = 11 .ec .fi .RE .TP -With this config section defined in the configuration file the following commands would be equivalent: +Activate the sub-configuration by name: $ tio ftdi +.TP +Which is equivalent to: + $ tio -b 115200 -c 11 /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTGQVXBL-if00-port0 .TP -A config section can also be matched by its pattern which supports regular expressions: +A sub-configuration can also be activated by its pattern which supports regular expressions: .RS .nf .eo [usb device] -pattern=usb([0-9]*) -baudrate=115200 -tty=/dev/ttyUSB%s +pattern = usb([0-9]*) +baudrate = 115200 +tty = /dev/ttyUSB%s .ec .fi .RE .TP -Making the following commands equivalent: +Activate the sub-configuration by pattern match: $ tio usb12 +.TP +Which is equivalent to: + $ tio -b 115200 /dev/ttyUSB12 +.TP +It is also possible to combine use of sub-configuration and command-line options. For example: + +$ tio -l -t usb12 + .SH "EXAMPLES" .TP -Typical use is without options. For example: +Typical use is without options: $ tio /dev/ttyUSB0 .TP @@ -319,16 +355,59 @@ $ tio \-b 115200 \-d 8 \-f none \-s 1 \-p none /dev/ttyUSB0 .TP -It is recommended to connect serial tty devices by ID. For example: +It is recommended to connect serial tty devices by ID: $ tio /dev/serial/by\-id/usb\-FTDI_TTL232R-3V3_FTGQVXBL\-if00\-port0 .PP Using serial devices by ID ensures that tio automatically reconnects to the correct serial device if the device is disconnected and then reconnected. .TP -To listen and redirect serial device I/O to network socket on port 4444 do: +Redirect serial device I/O to Unix file socket for scripting: + +$ tio -S unix:/tmp/tmux-socket0 /dev/ttyUSB0 + +.TP +Then, to issue a command via the file socket simply do: + +$ echo "ls -la" | nc -UN /tmp/tmux-socket0 > /dev/null + +.TP +Or use the expect command to script an interaction: + +.RS +.nf +.eo +#!/usr/bin/expect -f + +set timeout -1 +log_user 0 + +spawn nc -UN /tmp/tio-socket0 +set uart $spawn_id + +send -i $uart "date\n" +expect -i $uart "prompt> " +send -i $uart "ls -la\n" +expect -i $uart "prompt> " +.ec +.fi +.RE + +.TP +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): + +$ nc -N 10.0.0.42 4444 + +.TP +Pipe data from file to the serial device: -$ tio -S inet:4444 /dev/ttyUSB0 +$ cat data.bin | tio /dev/serial/by\-id/usb\-FTDI_TTL232R-3V3_FTGQVXBL\-if00\-port0 .SH "WEBSITE" .PP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/meson.build new/tio-1.42/meson.build --- old/tio-1.40/meson.build 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/meson.build 2022-07-04 22:42:15.000000000 +0200 @@ -1,12 +1,12 @@ project('tio', 'c', - version : '1.40', + version : '1.42', 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-06-17' +version_date = '2022-07-04' # Test for dynamic baudrate configuration interface compiler = meson.get_compiler('c') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/bash-completion/tio.in new/tio-1.42/src/bash-completion/tio.in --- old/tio-1.40/src/bash-completion/tio.in 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/bash-completion/tio.in 2022-07-04 22:42:15.000000000 +0200 @@ -27,7 +27,7 @@ -L --list-devices \ -c --color \ -S --socket \ - -x --hex-mode \ + -x --hexadecimal \ -v --version \ -h --help" @@ -102,7 +102,7 @@ COMPREPLY=( $(compgen -W "unix: inet: inet6:" -- ${cur}) ) return 0 ;; - -x | --hex-mode) + -x | --hexadecimal) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/configfile.c new/tio-1.42/src/configfile.c --- old/tio-1.40/src/configfile.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/configfile.c 2022-07-04 22:42:15.000000000 +0200 @@ -19,7 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ + #define _GNU_SOURCE + #include "config.h" #include <sys/types.h> #include <sys/stat.h> @@ -171,7 +173,7 @@ option.local_echo = false; } } - else if (!strcmp(name, "hex-mode")) + else if (!strcmp(name, "hexadecimal")) { if (!strcmp(value, "enable")) { @@ -318,6 +320,11 @@ int ret; c = malloc(sizeof(struct config_t)); + if (!c) + { + fprintf(stderr, "Error: Insufficient memory allocation"); + exit(EXIT_FAILURE); + } memset(c, 0, sizeof(struct config_t)); // Find config file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/log.c new/tio-1.42/src/log.c --- old/tio-1.40/src/log.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/log.c 2022-07-04 22:42:15.000000000 +0200 @@ -19,9 +19,12 @@ * 02110-1301, USA. */ +#define __STDC_WANT_LIB_EXT2__ 1 // To access vasprintf + #include "config.h" #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> #include <string.h> #include <errno.h> #include <time.h> @@ -37,6 +40,7 @@ static FILE *fp; static bool log_error = false; +static char file_buffer[BUFSIZ]; static char *date_time(void) { @@ -64,14 +68,16 @@ option.log_filename = automatic_filename; } + // Open log file in append write mode fp = fopen(filename, "a+"); - if (fp == NULL) { log_error = true; exit(EXIT_FAILURE); } - setvbuf(fp, NULL, _IONBF, 0); + + // Enable full buffering + setvbuf(fp, file_buffer, _IOFBF, BUFSIZ); } bool log_strip(char c) @@ -133,7 +139,21 @@ return strip; } -void log_write(char c) +void log_printf(const char *format, ...) +{ + char *line; + + va_list(args); + va_start(args, format); + vasprintf(&line, format, args); + va_end(args); + + fwrite(line, strlen(line), 1, fp); + + free(line); +} + +void log_putc(char c) { if (fp != NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/log.h new/tio-1.42/src/log.h --- old/tio-1.40/src/log.h 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/log.h 2022-07-04 22:42:15.000000000 +0200 @@ -22,6 +22,7 @@ #pragma once void log_open(const char *filename); -void log_write(char c); +void log_printf(const char *format, ...); +void log_putc(char c); void log_close(void); void log_exit(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/misc.h new/tio-1.42/src/misc.h --- old/tio-1.40/src/misc.h 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/misc.h 2022-07-04 22:42:15.000000000 +0200 @@ -20,6 +20,7 @@ */ #pragma once + #define UNUSED(expr) do { (void)(expr); } while (0) char * current_time(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/options.c new/tio-1.42/src/options.c --- old/tio-1.40/src/options.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/options.c 2022-07-04 22:42:15.000000000 +0200 @@ -68,7 +68,9 @@ void print_help(char *argv[]) { - printf("Usage: %s [<options>] <tty-device|config>\n", argv[0]); + printf("Usage: %s [<options>] <tty-device|sub-config>\n", argv[0]); + printf("\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"); @@ -88,11 +90,11 @@ printf(" -m, --map <flags> Map special characters\n"); printf(" -c, --color 0..255|none|list Colorize tio text (default: 15)\n"); printf(" -S, --socket <socket> Redirect I/O to socket\n"); - printf(" -x, --hex-mode Enable hexadecimal mode\n"); + printf(" -x, --hexadecimal Enable hexadecimal mode\n"); printf(" -v, --version Display version\n"); printf(" -h, --help Display help\n"); printf("\n"); - printf("Options may be set via configuration file.\n"); + printf("Options and sub-configurations may be set via configuration file.\n"); printf("\n"); printf("In session, press ctrl-t q to quit.\n"); printf("\n"); @@ -199,7 +201,7 @@ {"socket", required_argument, 0, 'S' }, {"map", required_argument, 0, 'm' }, {"color", required_argument, 0, 'c' }, - {"hex-mode", no_argument, 0, 'x' }, + {"hexadecimal", no_argument, 0, 'x' }, {"version", no_argument, 0, 'v' }, {"help", no_argument, 0, 'h' }, {0, 0, 0, 0 } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/print.c new/tio-1.42/src/print.c --- old/tio-1.40/src/print.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/print.c 2022-07-04 22:42:15.000000000 +0200 @@ -30,14 +30,11 @@ void print_hex(char c) { printf("%02x ", (unsigned char) c); - - fflush(stdout); } void print_normal(char c) { putchar(c); - fflush(stdout); } void print_init_ansi_formatting() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/print.h new/tio-1.42/src/print.h --- old/tio-1.40/src/print.h 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/print.h 2022-07-04 22:42:15.000000000 +0200 @@ -37,7 +37,6 @@ fprintf (stdout, "\r" format "\r\n", ## args); \ else \ fprintf (stdout, "\r%s" format ANSI_RESET "\r\n", ansi_format, ## args); \ - fflush(stdout); \ } #define ansi_error_printf(format, args...) \ @@ -55,7 +54,6 @@ fprintf (stdout, format, ## args); \ else \ fprintf (stdout, "%s" format ANSI_RESET, ansi_format, ## args); \ - fflush(stdout); \ } #define warning_printf(format, args...) \ @@ -66,7 +64,6 @@ fprintf (stdout, "\r[%s] Warning: " format "\r\n", current_time(), ## args); \ else \ ansi_printf("[%s] Warning: " format, current_time(), ## args); \ - fflush(stdout); \ } #define tio_printf(format, args...) \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/socket.c new/tio-1.42/src/socket.c --- old/tio-1.40/src/socket.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/socket.c 2022-07-04 22:42:15.000000000 +0200 @@ -20,10 +20,6 @@ * 02110-1301, USA. */ -#include "socket.h" -#include "options.h" -#include "print.h" - #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -32,6 +28,11 @@ #include <sys/un.h> #include <netinet/in.h> #include <unistd.h> +#include <string.h> + +#include "socket.h" +#include "options.h" +#include "print.h" #define MAX_SOCKET_CLIENTS 16 #define SOCKET_PORT_DEFAULT 3333 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/tty.c new/tio-1.42/src/tty.c --- old/tio-1.40/src/tty.c 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/tty.c 2022-07-04 22:42:15.000000000 +0200 @@ -78,15 +78,21 @@ static bool map_o_del_bs = false; static char hex_chars[2]; 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 void optional_local_echo(char c) { if (!option.local_echo) + { return; + } print(c); - fflush(stdout); if (option.log) - log_write(c); + { + log_putc(c); + } } inline static bool is_valid_hex(char c) @@ -96,17 +102,85 @@ inline static unsigned char char_to_nibble(char c) { - if(c >= '0' && c <= '9'){ + if(c >= '0' && c <= '9') + { return c - '0'; - } else if(c >= 'a' && c <= 'f'){ + } + else if (c >= 'a' && c <= 'f') + { return c - 'a' + 10; - } else if(c >= 'A' && c <= 'F'){ + } + else if (c >= 'A' && c <= 'F') + { return c - 'A' + 10; - } else { + } + else + { return 0; } } +void tty_flush(int fd) +{ + ssize_t count; + + do + { + count = write(fd, tty_buffer, tty_buffer_count); + if (count < 0) + { + // Error + debug_printf("Write error while flushing tty buffer (%s)", strerror(errno)); + break; + } + tty_buffer_count -= count; + } + while (tty_buffer_count > 0); + + // Reset + tty_buffer_write_ptr = tty_buffer; + tty_buffer_count = 0; +} + +ssize_t tty_write(int fd, const void *buffer, size_t count) +{ + ssize_t bytes_written = 0; + + if (option.output_delay) + { + // Write byte by byte with output delay + for (size_t i=0; i<count; i++) + { + ssize_t retval = write(fd, buffer, 1); + if (retval < 0) + { + // Error + debug_printf("Write error (%s)", strerror(errno)); + break; + } + bytes_written += retval; + fsync(fd); + delay(option.output_delay); + } + } + else + { + // Flush tty buffer if too full + if ((tty_buffer_count + count) > BUFSIZ) + { + tty_flush(fd); + } + + // Copy bytes to tty write buffer + memcpy(tty_buffer_write_ptr, buffer, count); + tty_buffer_write_ptr += count; + tty_buffer_count += count; + bytes_written = count; + } + + return bytes_written; +} + static void output_hex(char c) { hex_chars[hex_char_index++] = c; @@ -118,16 +192,15 @@ optional_local_echo(hex_value); - ssize_t status = write(fd, &hex_value, 1); + ssize_t status = tty_write(fd, &hex_value, 1); if (status < 0) { warning_printf("Could not write to tty device"); - } else + } + else { tx_total++; } - - fsync(fd); } } @@ -251,7 +324,6 @@ case KEY_L: /* Clear screen using ANSI/VT100 escape code */ printf("\033c"); - fflush(stdout); break; case KEY_Q: @@ -304,6 +376,11 @@ } } +void stdin_restore(void) +{ + tcsetattr(STDIN_FILENO, TCSANOW, &stdin_old); +} + void stdin_configure(void) { int status; @@ -319,9 +396,7 @@ memcpy(&stdin_new, &stdin_old, sizeof(stdin_old)); /* Reconfigure stdin (RAW configuration) */ - stdin_new.c_iflag &= ~(ICRNL); // Do not translate CR -> NL on input - stdin_new.c_oflag &= ~(OPOST); - stdin_new.c_lflag &= ~(ECHO|ICANON|ISIG|ECHOE|ECHOK|ECHONL); + cfmakeraw(&stdin_new); /* Control characters */ stdin_new.c_cc[VTIME] = 0; /* Inter-character timer unused */ @@ -339,9 +414,9 @@ atexit(&stdin_restore); } -void stdin_restore(void) +void stdout_restore(void) { - tcsetattr(STDIN_FILENO, TCSANOW, &stdin_old); + tcsetattr(STDOUT_FILENO, TCSANOW, &stdout_old); } void stdout_configure(void) @@ -350,7 +425,7 @@ /* Disable line buffering in stdout. This is necessary if we * want things like local echo to work correctly. */ - setbuf(stdout, NULL); + setvbuf(stdout, NULL, _IONBF, 0); /* Save current stdout settings */ if (tcgetattr(STDOUT_FILENO, &stdout_old) < 0) @@ -363,8 +438,7 @@ memcpy(&stdout_new, &stdout_old, sizeof(stdout_old)); /* Reconfigure stdout (RAW configuration) */ - stdout_new.c_oflag &= ~(OPOST); - stdout_new.c_lflag &= ~(ECHO|ICANON|ISIG|ECHOE|ECHOK|ECHONL); + cfmakeraw(&stdout_new); /* Control characters */ stdout_new.c_cc[VTIME] = 0; /* Inter-character timer unused */ @@ -385,11 +459,6 @@ atexit(&stdout_restore); } -void stdout_restore(void) -{ - tcsetattr(STDOUT_FILENO, TCSANOW, &stdout_old); -} - void tty_configure(void) { bool token_found = true; @@ -514,7 +583,9 @@ tio.c_cflag &= ~PARODD; } else if (strcmp("none", option.parity) == 0) + { tio.c_cflag &= ~PARENB; + } else { error_printf("Invalid parity"); @@ -535,26 +606,44 @@ 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,"OCRNL") == 0) + { map_o_cr_nl = true; + } else if (strcmp(token,"ODELBS") == 0) + { map_o_del_bs = true; + } else if (strcmp(token,"INLCRNL") == 0) + { map_i_nl_crnl = true; + } else if (strcmp(token, "ONLCRNL") == 0) + { map_o_nl_crnl = true; + } else { printf("Error: Unknown mapping flag %s\n", token); @@ -562,7 +651,9 @@ } } else + { token_found = false; + } } free(buffer); } @@ -586,7 +677,8 @@ tv.tv_sec = 0; tv.tv_usec = 1; first = false; - } else + } + else { /* Wait up to 1 second */ tv.tv_sec = 1; @@ -619,7 +711,8 @@ previous_char = input_char; } socket_handle_input(&rdfs, NULL); - } else if (status == -1) + } + else if (status == -1) { error_printf("select() failed (%s)", strerror(errno)); exit(EXIT_FAILURE); @@ -627,7 +720,8 @@ /* Test for accessible device file */ status = access(option.tty_device, R_OK); - if (status == 0) { + if (status == 0) + { last_errno = 0; return; } @@ -656,7 +750,60 @@ tcsetattr(fd, TCSANOW, &tio_old); if (connected) + { tty_disconnect(); + } +} + +void forward_to_tty(int fd, char output_char) +{ + int status; + + /* 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 = tty_write(fd, crlf, 2); + if (status < 0) + { + warning_printf("Could not write to tty device"); + } + + tx_total += 2; + } + else + { + if (print_mode == HEX) + { + output_hex(output_char); + } + else + { + /* Send output to tty device */ + optional_local_echo(output_char); + status = tty_write(fd, &output_char, 1); + if (status < 0) + { + warning_printf("Could not write to tty device"); + } + + /* Update transmit statistics */ + tx_total++; + } + } } int tty_connect(void) @@ -664,18 +811,15 @@ fd_set rdfs; /* Read file descriptor set */ 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; + bool next_timestamp = false; char* now = NULL; /* Open tty device */ -#ifdef __APPLE__ - fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK ); -#else - fd = open(option.tty_device, O_RDWR | O_NOCTTY); -#endif + fd = open(option.tty_device, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { error_printf_silent("Could not open tty device (%s)", strerror(errno)); @@ -706,7 +850,9 @@ print_tainted = false; if (option.timestamp) + { next_timestamp = true; + } /* Manage print output mode */ if (option.hex_mode) @@ -722,7 +868,9 @@ /* Save current port settings */ if (tcgetattr(fd, &tio_old) < 0) + { goto error_tcgetattr; + } #ifdef HAVE_IOSSIOSPEED if (!standard_baudrate) @@ -787,12 +935,23 @@ if (FD_ISSET(fd, &rdfs)) { /* Input from tty device ready */ - if (read(fd, &input_char, 1) > 0) + ssize_t bytes_read = read(fd, input_buffer, BUFSIZ); + if (bytes_read <= 0) { - /* Update receive statistics */ - rx_total++; + /* Error reading - device is likely unplugged */ + error_printf_silent("Could not read from tty device"); + goto error_read; + } + + /* Update receive statistics */ + rx_total += bytes_read; - /* Print timestamp on new line, if desired. */ + /* Process input byte by byte */ + for (int i=0; i<bytes_read; i++) + { + input_char = input_buffer[i]; + + /* Print timestamp on new line if enabled */ if (next_timestamp && input_char != '\n' && input_char != '\r') { now = current_time(); @@ -801,14 +960,7 @@ ansi_printf_raw("[%s] ", now); if (option.log) { - log_write('['); - while (*now != '\0') - { - log_write(*now); - ++now; - } - log_write(']'); - log_write(' '); + log_printf("[%s] ", now); } next_timestamp = false; } @@ -820,117 +972,96 @@ print('\r'); print('\n'); if (option.timestamp) + { next_timestamp = true; - } else + } + } + else { /* Print received tty character to stdout */ print(input_char); } - fflush(stdout); /* Write to log */ if (option.log) - log_write(input_char); + { + log_putc(input_char); + } socket_write(input_char); print_tainted = true; if (input_char == '\n' && option.timestamp) + { next_timestamp = true; - } else - { - /* Error reading - device is likely unplugged */ - error_printf_silent("Could not read from tty device"); - goto error_read; + } } } - if (FD_ISSET(STDIN_FILENO, &rdfs)) + else if (FD_ISSET(STDIN_FILENO, &rdfs)) { - forward = true; - /* Input from stdin ready */ - status = read(STDIN_FILENO, &input_char, 1); - if (status <= 0) + ssize_t bytes_read = read(STDIN_FILENO, input_buffer, BUFSIZ); + if (bytes_read <= 0) { error_printf_silent("Could not read from stdin"); goto error_read; } - /* Forward input to output */ - output_char = input_char; - - if (interactive_mode) + /* Process input byte by byte */ + for (int i=0; i<bytes_read; i++) { - /* Do not forward ctrl-t key */ - if (input_char == KEY_CTRL_T) - forward = false; + input_char = input_buffer[i]; - /* Handle commands */ - handle_command_sequence(input_char, previous_char, &output_char, &forward); + /* Forward input to output */ + output_char = input_char; + forward = true; - /* Save previous key */ - previous_char = input_char; + if (interactive_mode) + { + /* Do not forward ctrl-t key */ + if (input_char == KEY_CTRL_T) + { + forward = false; + } + + /* Handle commands */ + handle_command_sequence(input_char, previous_char, &output_char, &forward); + + /* Save previous key */ + previous_char = input_char; + + if (print_mode == HEX) + { + if (!is_valid_hex(input_char)) + { + warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char); + forward = false; + } + } + } + + if (forward) + { + forward_to_tty(fd, output_char); + } } + + tty_flush(fd); } else { forward = socket_handle_input(&rdfs, &output_char); - } - if (forward) - { - if (print_mode == HEX) + if (forward) { - if (!is_valid_hex(input_char)) - { - warning_printf("Invalid hex character: '%d' (0x%02x)", input_char, input_char); - continue; - } + forward_to_tty(fd, output_char); } - /* 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"); - - tx_total += 2; - delay(option.output_delay); - } else - { - if (print_mode == HEX) - { - output_hex(output_char); - } - 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); - - /* Update transmit statistics */ - tx_total++; - } - - /* Insert output delay */ - delay(option.output_delay); - } + tty_flush(fd); } - } else if (status == -1) + } + else if (status == -1) { error_printf("Error: select() failed (%s)", strerror(errno)); exit(EXIT_FAILURE); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-1.40/src/tty.h new/tio-1.42/src/tty.h --- old/tio-1.40/src/tty.h 2022-06-17 11:54:01.000000000 +0200 +++ new/tio-1.42/src/tty.h 2022-07-04 22:42:15.000000000 +0200 @@ -42,13 +42,11 @@ #define NORMAL 0 #define HEX 1 +extern bool interactive_mode; + void stdout_configure(void); -void stdout_restore(void); void stdin_configure(void); -void stdin_restore(void); void tty_configure(void); int tty_connect(void); void tty_wait_for_device(void); void list_serial_devices(void); - -extern bool interactive_mode;