Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package tio for openSUSE:Factory checked in at 2023-09-26 22:01:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/tio (Old) and /work/SRC/openSUSE:Factory/.tio.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tio" Tue Sep 26 22:01:39 2023 rev:14 rq:1113517 version:2.7 Changes: -------- --- /work/SRC/openSUSE:Factory/tio/tio.changes 2023-06-13 16:09:41.702950898 +0200 +++ /work/SRC/openSUSE:Factory/.tio.new.1770/tio.changes 2023-09-26 22:14:53.813081198 +0200 @@ -1,0 +2,7 @@ +Thu Sep 21 14:22:40 UTC 2023 - Martin Hauke <mar...@gmx.de> + +- Update to 2.7: + * Add xmodem and ymodem file send support + * fix: support --log-append in cli options + +------------------------------------------------------------------- Old: ---- tio-2.6.tar.xz New: ---- tio-2.7.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tio.spec ++++++ --- /var/tmp/diff_new_pack.5eosRo/_old 2023-09-26 22:14:55.329136070 +0200 +++ /var/tmp/diff_new_pack.5eosRo/_new 2023-09-26 22:14:55.345136649 +0200 @@ -17,7 +17,7 @@ Name: tio -Version: 2.6 +Version: 2.7 Release: 0 Summary: Simple TTY terminal I/O application License: GPL-2.0-or-later ++++++ tio-2.6.tar.xz -> tio-2.7.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/AUTHORS new/tio-2.7/AUTHORS --- old/tio-2.6/AUTHORS 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/AUTHORS 2023-09-19 21:48:58.000000000 +0200 @@ -45,5 +45,8 @@ Bill Hass <billh...@umich.edu> Peter van Dijk <pe...@7bits.nl> Braden Young <bra...@somewearlabs.com> +Wes Koerber <wkoer...@acsd4u.com> +HiFiPhile <ad...@hifiphile.com> +Paul Ruizendaal <p...@planet.nl> Thanks to everyone who has contributed to this project. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/NEWS new/tio-2.7/NEWS --- old/tio-2.6/NEWS 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/NEWS 2023-09-19 21:48:58.000000000 +0200 @@ -1,5 +1,31 @@ -=== tio v2.6 === +=== tio v2.7 === + + + +Changes since tio v2.6: + +Paul Ruizendaal: + + * Add xmodem and ymodem file send support + +HiFiPhile: + + * tty_stdin_input_thread(): write to pipe only if byte_count > 0. + + * Ignore EINTR error. + + * CYGWIN: Add support for "COM*" naming. + +Wes Koerber: + + * chore: reorder log-strip and log-append + + reorder to maintain consistency with documentation + + * chore: update readme, bash completion, man page + + * fix: support --log-append in cli options diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/README.md new/tio-2.7/README.md --- old/tio-2.6/README.md 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/README.md 2023-09-19 21:48:58.000000000 +0200 @@ -6,7 +6,7 @@ [![](https://img.shields.io/circleci/build/github/tio/tio)](https://circleci.com/github/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/repology/repositories/tio)](https://repology.org/project/tio/versions) -[![](https://img.shields.io/tokei/lines/github/tio/tio)](https://github.com/tio/tio) +<!-- [![](https://img.shields.io/tokei/lines/github/tio/tio)](https://github.com/tio/tio) --> ## 1. Introduction @@ -35,6 +35,7 @@ * Sensible defaults (115200 8n1) * Support for non-standard baud rates * Support for RS-485 mode + * X-modem (1K) and Y-modem file upload * Support for mark and space parity * List available serial devices by ID * Show RX/TX statistics @@ -91,6 +92,7 @@ -L, --list-devices List available serial devices -l, --log Enable log to file --log-file <filename> Set log filename + --log-append Append to log file --log-strip Strip control characters and escape sequences -m, --map <flags> Map characters -c, --color 0..255|bold|none|list Colorize tio text (default: bold) @@ -193,6 +195,8 @@ [20:19:12.041] ctrl-t t Toggle line timestamp mode [20:19:12.041] ctrl-t U Toggle conversion to uppercase [20:19:12.041] ctrl-t v Show version +[20:19:12.041] ctrl-t x Send file using the XMODEM protocol +[20:19:12.041] ctrl-t y Send file using the YMODEM protocol [20:19:12.041] ctrl-t ctrl-t Send ctrl-t character ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/TODO new/tio-2.7/TODO --- old/tio-2.6/TODO 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/TODO 2023-09-19 21:48:58.000000000 +0200 @@ -1,4 +1,9 @@ - * Support for interaction using simple autoresponse strings +* Line mode feature + + Only send line when pressing enter. Maybe even add readline support so one + can use all the readline editing feature before sending the line. + +* Support for interaction using simple autoresponse strings Add support for simple autoresponse strings in the configuration file. For example: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/man/tio.1.in new/tio-2.7/man/tio.1.in --- old/tio-2.6/man/tio.1.in 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/man/tio.1.in 2023-09-19 21:48:58.000000000 +0200 @@ -309,6 +309,8 @@ Clear screen .IP "\fBctrl-t L" Show line states (DTR, RTS, CTS, DSR, DCD, RI) +.IP "\fBctrl-t m" +Toggle MSB to LSB bit order .IP "\fBctrl-t p" Pulse serial port line .IP "\fBctrl-t q" @@ -321,6 +323,10 @@ Toggle conversion to uppercase on output .IP "\fBctrl-t v" Show version +.IP "\fBctrl-t x" +Send a file using the XMODEM protocol (prompts for file name) +.IP "\fBctrl-t y" +Send a file using the YMODEM protocol (prompts for file name) .IP "\fBctrl-t ctrl-t" Send ctrl-t character @@ -390,6 +396,8 @@ Enable log to file .IP "\fBlog-file" Set log filename +.IP "\fBlog-append" +Append to log file .IP "\fBlog-strip" Enable strip of control and escape sequences from log .IP "\fBlocal-echo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/man/tio.1.txt new/tio-2.7/man/tio.1.txt --- old/tio-2.6/man/tio.1.txt 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/man/tio.1.txt 2023-09-19 21:48:58.000000000 +0200 @@ -305,6 +305,8 @@ log-file Set log filename + log-append Append to log file + log-strip Enable strip of control and escape sequences from log local-echo Enable local echo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/meson.build new/tio-2.7/meson.build --- old/tio-2.6/meson.build 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/meson.build 2023-09-19 21:48:58.000000000 +0200 @@ -1,12 +1,12 @@ project('tio', 'c', - version : '2.6', + version : '2.7', 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-12-17' +version_date = '2023-09-19' # Test for dynamic baudrate configuration interface compiler = meson.get_compiler('c') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/bash-completion/tio.in new/tio-2.7/src/bash-completion/tio.in --- old/tio-2.6/src/bash-completion/tio.in 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/src/bash-completion/tio.in 2023-09-19 21:48:58.000000000 +0200 @@ -22,6 +22,7 @@ -e --local-echo \ -l --log \ --log-file \ + --log-append \ --log-strip \ -m --map \ -t --timestamp \ @@ -90,6 +91,10 @@ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; + --log-append) + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; --log-strip) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/meson.build new/tio-2.7/src/meson.build --- old/tio-2.6/src/meson.build 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/src/meson.build 2023-09-19 21:48:58.000000000 +0200 @@ -17,7 +17,8 @@ 'setspeed.c', 'rs485.c', 'timestamp.c', - 'alert.c' + 'alert.c', + 'xymodem.c' ] tio_dep = [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/misc.h new/tio-2.7/src/misc.h --- old/tio-2.6/src/misc.h 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/src/misc.h 2023-09-19 21:48:58.000000000 +0200 @@ -29,3 +29,6 @@ int ctrl_key_code(unsigned char key); void alert_connect(void); void alert_disconnect(void); + +extern char key_hit; +int xymodem_send(int sio, const char *filename, char mode); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/options.c new/tio-2.7/src/options.c --- old/tio-2.6/src/options.c 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/src/options.c 2023-09-19 21:48:58.000000000 +0200 @@ -46,6 +46,7 @@ OPT_TIMESTAMP_FORMAT, OPT_LOG_FILE, OPT_LOG_STRIP, + OPT_LOG_APPEND, OPT_LINE_PULSE_DURATION, OPT_RESPONSE_TIMEOUT, OPT_RS485, @@ -253,6 +254,7 @@ {"list-devices", no_argument, 0, 'L' }, {"log", no_argument, 0, 'l' }, {"log-file", required_argument, 0, OPT_LOG_FILE }, + {"log-append", no_argument, 0, OPT_LOG_APPEND }, {"log-strip", no_argument, 0, OPT_LOG_STRIP }, {"socket", required_argument, 0, 'S' }, {"map", required_argument, 0, 'm' }, @@ -357,6 +359,10 @@ option.log_strip = true; break; + case OPT_LOG_APPEND: + option.log_append = true; + break; + case 'S': option.socket = optarg; break; @@ -486,6 +492,19 @@ optind = 1; // Reset option index to restart scanning of argv options_parse(argc, argv); +#ifdef __CYGWIN__ + unsigned char portnum; + char *tty_win; + if ( ((strncmp("COM", tty_device, 3) == 0) + || (strncmp("com", tty_device, 3) == 0) ) + && (sscanf(tty_device + 3, "%hhu", &portnum) == 1) + && (portnum > 0) ) + { + asprintf(&tty_win, "/dev/ttyS%hhu", portnum - 1); + tty_device = tty_win; + } +#endif + /* Restore tty device */ option.tty_device = tty_device; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/tty.c new/tio-2.7/src/tty.c --- old/tio-2.6/src/tty.c 2023-06-10 13:02:32.000000000 +0200 +++ new/tio-2.7/src/tty.c 2023-09-19 21:48:58.000000000 +0200 @@ -82,6 +82,8 @@ #define CMSPAR 010000000000 #endif +#define LINE_SIZE_MAX 1000 + #define KEY_0 0x30 #define KEY_1 0x31 #define KEY_2 0x32 @@ -105,6 +107,8 @@ #define KEY_T 0x74 #define KEY_U 0x55 #define KEY_V 0x76 +#define KEY_X 0x78 +#define KEY_Y 0x79 #define KEY_Z 0x7a enum line_mode_t @@ -133,6 +137,8 @@ bool map_i_cr_nl = false; bool map_ign_cr = false; +char key_hit = 0xff; + static struct termios tio, tio_old, stdout_new, stdout_old, stdin_new, stdin_old; static unsigned long rx_total = 0, tx_total = 0; static bool connected = false; @@ -153,6 +159,7 @@ static pthread_t thread; static int pipefd[2]; static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER; +static char line[LINE_SIZE_MAX]; static void optional_local_echo(char c) { @@ -299,6 +306,11 @@ byte_count = read(STDIN_FILENO, input_buffer, BUFSIZ); if (byte_count < 0) { + /* No error actually occurred */ + if (errno == EINTR) + { + continue; + } tio_warning_printf("Could not read from stdin (%s)", strerror(errno)); } else if (byte_count == 0) @@ -316,6 +328,14 @@ // Process quit and flush key command for (int i = 0; i<byte_count; i++) { + // first do key hit check for xmodem abort + if (!key_hit) { + key_hit = input_buffer[i]; + byte_count--; + memcpy(input_buffer+i, input_buffer+i+1, byte_count-i); + continue; + } + input_char = input_buffer[i]; if (previous_char == option.prefix_code) @@ -344,7 +364,7 @@ } // Write all bytes read to pipe - while (byte_count) + while (byte_count > 0) { bytes_written = write(pipefd[1], input_buffer, byte_count); if (bytes_written < 0) @@ -467,6 +487,33 @@ } } +static int tio_readln(void) +{ + char *p = line; + + /* Read line, accept BS and DEL as rubout characters */ + for (p = line ; p < &line[LINE_SIZE_MAX-1]; ) + { + if (read(pipefd[0], p, 1) > 0) + { + if (*p == 0x08 || *p == 0x7f) + { + if (p > line ) + { + write(STDOUT_FILENO, "\b \b", 3); + p--; + } + continue; + } + write(STDOUT_FILENO, p, 1); + if (*p == '\r') break; + p++; + } + } + *p = 0; + return (p - line); +} + void handle_command_sequence(char input_char, char *output_char, bool *forward) { char unused_char; @@ -557,7 +604,9 @@ tio_printf(" ctrl-%c t Toggle line timestamp mode", option.prefix_key); tio_printf(" ctrl-%c U Toggle conversion to uppercase on output", option.prefix_key); tio_printf(" ctrl-%c v Show version", option.prefix_key); - tio_printf(" ctrl-%c ctrl-%c Send ctrl-%c character", option.prefix_key, option.prefix_key, option.prefix_key); + tio_printf(" ctrl-%c x Send file via Xmodem-1K", option.prefix_key); + tio_printf(" ctrl-%c y Send file via Ymodem", option.prefix_key); + tio_printf(" ctrl-%c ctrl-%c Send ctrl-%c character", option.prefix_key, option.prefix_key, option.prefix_key); break; case KEY_SHIFT_L: @@ -716,6 +765,17 @@ tio_printf("tio v%s", VERSION); break; + case KEY_X: + case KEY_Y: + tio_printf("Send file with %cMODEM", toupper(input_char)); + tio_printf_raw("Enter file name: "); + if (tio_readln()) { + tio_printf("Sending file '%s' ", line); + tio_printf("Press any key to abort transfer"); + tio_printf("%s", xymodem_send(fd, line, input_char) < 0 ? "Aborted" : "Done"); + } + break; + case KEY_Z: tio_printf_array(random_array); break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tio-2.6/src/xymodem.c new/tio-2.7/src/xymodem.c --- old/tio-2.6/src/xymodem.c 1970-01-01 01:00:00.000000000 +0100 +++ new/tio-2.7/src/xymodem.c 2023-09-19 21:48:58.000000000 +0200 @@ -0,0 +1,225 @@ +/* + * Minimalistic implementation of the xmodem-1k and ymodem sender protocol. + * https://en.wikipedia.org/wiki/XMODEM + * https://en.wikipedia.org/wiki/YMODEM + * + * SPDX-License-Identifier: GPL-2.0-or-later OR MIT-0 + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <termios.h> +#include "misc.h" + +#define STX 0x02 +#define ACK 0x06 +#define NAK 0x15 +#define CAN 0x18 +#define EOT "\004" + +#define OK 0 +#define ERR (-1) + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +struct xpacket { + uint8_t type; + uint8_t seq; + uint8_t nseq; + uint8_t data[1024]; + uint8_t crc_hi; + uint8_t crc_lo; +} __attribute__((packed)); + +/* See https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks */ +static uint16_t crc16(const uint8_t *data, uint16_t size) +{ + uint16_t crc, s; + + for (crc = 0; size > 0; size--) { + s = *data++ ^ (crc >> 8); + s ^= (s >> 4); + crc = (crc << 8) ^ s ^ (s << 5) ^ (s << 12); + } + return crc; +} + +static int xmodem(int sio, const void *data, size_t len, int seq) +{ + struct xpacket packet; + const uint8_t *buf = data; + char resp = 0; + int rc, crc; + + /* Drain pending characters from serial line. Insist on the + * last drained character being 'C'. + */ + while(1) { + if (key_hit) + return -1; + if (read(sio, &resp, 1) < 0) { + if (errno == EWOULDBLOCK) { + if (resp == 'C') break; + if (resp == CAN) return ERR; + usleep(50000); + continue; + } + perror("Read sync from serial failed"); + return ERR; + } + } + + /* Always work with 1K packets */ + packet.seq = seq; + packet.type = STX; + + while (len) { + size_t sz, z = 0; + char *from, status; + + /* Build next packet, pad with 0 to full seq */ + z = min(len, sizeof(packet.data)); + memcpy(packet.data, buf, z); + memset(packet.data + z, 0, sizeof(packet.data) - z); + crc = crc16(packet.data, sizeof(packet.data)); + packet.crc_hi = crc >> 8; + packet.crc_lo = crc; + packet.nseq = 0xff - packet.seq; + + /* Send packet */ + from = (char *) &packet; + sz = sizeof(packet); + while (sz) { + if (key_hit) + return ERR; + if ((rc = write(sio, from, sz)) < 0 ) { + if (errno == EWOULDBLOCK) { + usleep(1000); + continue; + } + perror("Write packet to serial failed"); + return ERR; + } + from += rc; + sz -= rc; + } + + /* 'lrzsz' does not ACK ymodem's fin packet */ + if (seq == 0 && packet.data[0] == 0) resp = ACK; + + /* Read receiver response, timeout 1 s */ + for(int n=0; n < 20; n++) { + if (key_hit) + return ERR; + if (read(sio, &resp, 1) < 0) { + if (errno == EWOULDBLOCK) { + usleep(50000); + continue; + } + perror("Read ack/nak from serial failed"); + return ERR; + } + break; + } + + /* Update "progress bar" */ + switch (resp) { + case NAK: status = 'N'; break; + case ACK: status = '.'; break; + case 'C': status = 'C'; break; + case CAN: status = '!'; return ERR; + default: status = '?'; + } + write(STDOUT_FILENO, &status, 1); + + /* Move to next block after ACK */ + if (resp == ACK) { + packet.seq++; + len -= z; + buf += z; + } + } + + /* Send EOT at 1 Hz until ACK or CAN received */ + while (seq) { + if (key_hit) + return ERR; + if (write(sio, EOT, 1) < 0) { + perror("Write EOT to serial failed"); + return ERR; + } + write(STDOUT_FILENO, "|", 1); + usleep(1000000); /* 1 s timeout*/ + if (read(sio, &resp, 1) < 0) { + if (errno == EWOULDBLOCK) continue; + perror("Read from serial failed"); + return ERR; + } + if (resp == ACK || resp == CAN) { + write(STDOUT_FILENO, "\r\n", 2); + return (resp == ACK) ? OK : ERR; + } + } + return 0; /* not reached */ +} + +int xymodem_send(int sio, const char *filename, char mode) +{ + size_t len; + int rc, fd; + struct stat stat; + const uint8_t *buf; + + /* Open file, map into memory */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("Could not open file"); + return ERR; + } + fstat(fd, &stat); + len = stat.st_size; + buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (!buf) { + close(fd); + perror("Could not mmap file"); + return ERR; + } + + /* Do transfer */ + key_hit = 0; + if (mode == 'x') { + rc = xmodem(sio, buf, len, 1); + } + else { + /* Ymodem: hdr + file + fin */ + while(1) { + char hdr[1024], *p; + + rc = -1; + if (strlen(filename) > 977) break; /* hdr block overrun */ + p = stpcpy(hdr, filename) + 1; + p += sprintf(p, "%ld %lo %o", len, stat.st_mtime, stat.st_mode); + + if (xmodem(sio, hdr, p - hdr, 0) < 0) break; /* hdr with metadata */ + if (xmodem(sio, buf, len, 1) < 0) break; /* xmodem file */ + if (xmodem(sio, "", 1, 0) < 0) break; /* empty hdr = fin */ + rc = 0; break; + } + } + key_hit = 0xff; + + /* Flush serial and release resources */ + tcflush(sio, TCIOFLUSH); + munmap((void *)buf, len); + close(fd); + return rc; +}