Daniel Engberg <daniel.engberg.lists@pyret.net>
Petr Vaněk <pv@excello.cz>
qianfan Zhao <qianfanguijin@163.com>
+Henner Zeller <h.zeller@acm.org>
Thanks to everyone who has contributed to this project.
-=== tio v1.30 ===
+=== tio v1.31 ===
+
+
+
+Changes since tio v1.30:
+
+ * Update date
+
+ * Update AUTHORS
+
+Henner Zeller:
+
+ * Clarify the input/output variable names (No-op change)
+
+ * Organize options the same sequence they are mentiond in cmdline help.
+
+ * Update README.
+
+ * Map CR->NL locally on output instead of using tio.c_oflag |= OCRNL.
+
+ This mostly is intended to have local echo output exactly what is sent
+ to the remote endpoint.
+ A nice side-effect is, that it also fixes tty-implementations, that can't
+ deal with the OCRNL flag on tio.c_oflag.
+
+ * Provide local-echo option.
+
+ Can be switched on with -e on the command line.
+ Can be toggled with Ctrl t e while program is running.
+
+ * Write to logfile as soon as we have the data, don't buffer.
+
+ Logfiles are important to see what happend, in particular if something
+ unexpected happened; so we want to make sure that the logfile is flushed
+ to disk.
+
+ Before this change, the logfile was typically written at the end in
+ a large chunk as the default (large) buffering applied. Now, characters are
+ written out ASAP, so it is possible to get a live-view with a
+ tail -f <logfile>
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tio 1.30.
+# Generated by GNU Autoconf 2.69 for tio 1.31.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Identity of this package.
PACKAGE_NAME='tio'
PACKAGE_TARNAME='tio'
-PACKAGE_VERSION='1.30'
-PACKAGE_STRING='tio 1.30'
+PACKAGE_VERSION='1.31'
+PACKAGE_STRING='tio 1.31'
PACKAGE_BUGREPORT=''
PACKAGE_URL='https://tio.github.io'
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures tio 1.30 to adapt to many kinds of systems.
+\`configure' configures tio 1.31 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of tio 1.30:";;
+ short | recursive ) echo "Configuration of tio 1.31:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-tio configure 1.30
+tio configure 1.31
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by tio $as_me 1.30, which was
+It was created by tio $as_me 1.31, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='tio'
- VERSION='1.30'
+ VERSION='1.31'
cat >>confdefs.h <<_ACEOF
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by tio $as_me 1.30, which was
+This file was extended by tio $as_me 1.31, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-tio config.status 1.30
+tio config.status 1.31
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
AC_PREREQ([2.68])
-AC_INIT([tio], [1.30], [], [tio], [https://tio.github.io])
+AC_INIT([tio], [1.31], [], [tio], [https://tio.github.io])
AC_CONFIG_HEADERS([src/include/config.h])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz no-dist-gzip -Wall -Werror])
AM_SILENT_RULES([yes])
-.TH "tio" "1" "April 2018"
+.TH "tio" "1" "June 2018"
.SH "NAME"
tio \- a simple TTY terminal I/O application
.B \-\-no\-autoconnect
option is provided, tio will exit if the device is not present or an established connection is lost.
+.TP
+.BR \-e ", " "\-\-local\-echo
+
+Enable local echo.
+
.TP
.BR \-l ", " "\-\-log " \fI<filename>
Send serial break (triggers SysRq on Linux, etc.)
.IP "\fBctrl-t c"
Show configuration (baudrate, databits, etc.)
+.IP "\fBctrl-t e"
+Toggle local echo mode
.IP "\fBctrl-t h"
Toggle hexadecimal mode
.IP "\fBctrl-t l"
COMPREPLY=( $(compgen -W "5 6 7 8" -- ${cur}) )
return 0
;;
+ -h | --local-echo)
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+ ;;
-f | --flow)
COMPREPLY=( $(compgen -W "hard soft none" -- ${cur}) )
return 0
int output_delay;
bool no_autoconnect;
bool log;
+ bool local_echo;
const char *log_filename;
const char *map;
};
#define KEY_QUESTION 0x3f
#define KEY_B 0x62
#define KEY_C 0x63
+#define KEY_E 0x65
#define KEY_H 0x68
#define KEY_L 0x6C
#define KEY_Q 0x71
log_error = true;
exit(EXIT_FAILURE);
}
+ setvbuf(fp, NULL, _IONBF, 0);
}
void log_write(char c)
/*
* tio - a simple TTY terminal I/O application
*
- * Copyright (c) 2014-2017 Martin Lund
+ * Copyright (c) 2014-2018 Martin Lund
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
0, // No output delay
false, // No autoconnect
false, // No log
+ false, // No local echo
"", // Log filename
"" // Map string
};
printf(" -p, --parity odd|even|none Parity (default: none)\n");
printf(" -o, --output-delay <ms> Output delay (default: 0)\n");
printf(" -n, --no-autoconnect Disable automatic connect\n");
+ printf(" -e, --local-echo Do local echo\n");
printf(" -l, --log <filename> Log to file\n");
printf(" -m, --map <flags> Map special characters\n");
printf(" -v, --version Display version\n");
{"parity", required_argument, 0, 'p'},
{"output-delay", required_argument, 0, 'o'},
{"no-autoconnect", no_argument, 0, 'n'},
+ {"local-echo", no_argument, 0, 'e'},
{"log", required_argument, 0, 'l'},
{"map", required_argument, 0, 'm'},
{"version", no_argument, 0, 'v'},
int option_index = 0;
/* Parse argument using getopt_long */
- c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:m:vh", long_options, &option_index);
+ c = getopt_long(argc, argv, "b:d:f:s:p:o:nel:m:vh", long_options, &option_index);
/* Detect the end of the options */
if (c == -1)
option.no_autoconnect = true;
break;
+ case 'e':
+ option.local_echo = true;
+ break;
+
case 'l':
option.log = true;
option.log_filename = optarg;
case 'v':
printf("tio v%s\n", VERSION);
- printf("Copyright (c) 2014-2017 Martin Lund\n");
+ printf("Copyright (c) 2014-2018 Martin Lund\n");
printf("\n");
printf("License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>.\n");
printf("This is free software: you are free to change and redistribute it.\n");
static bool standard_baudrate = true;
static void (*print)(char c);
static int fd;
-static bool map_inlcrnl = false;
-static bool map_onlcrnl = false;
-static bool map_odelbs = false;
+static bool map_i_nl_crnl = false;
+static bool map_o_cr_nl = false;
+static bool map_o_nl_crnl = false;
+static bool map_o_del_bs = false;
#define tio_printf(format, args...) \
{ \
tio_printf(" ctrl-t ? List available key commands");
tio_printf(" ctrl-t b Send break");
tio_printf(" ctrl-t c Show configuration");
+ tio_printf(" ctrl-t e Toggle local echo mode");
tio_printf(" ctrl-t h Toggle hexadecimal mode");
tio_printf(" ctrl-t l Clear screen");
tio_printf(" ctrl-t q Quit");
tio_printf(" Flow: %s", option.flow);
tio_printf(" Stopbits: %d", option.stopbits);
tio_printf(" Parity: %s", option.parity);
+ tio_printf(" Local Echo: %s", option.local_echo ? "yes":"no");
tio_printf(" Output delay: %d", option.output_delay);
if (option.map[0] != 0)
tio_printf(" Map flags: %s", option.map);
tio_printf(" Log file: %s", option.log_filename);
break;
+ case KEY_E:
+ option.local_echo = !option.local_echo;
+ break;
+
case KEY_H:
/* Toggle hexadecimal printing mode */
if (print_mode == NORMAL)
else if (strcmp(token,"ICRNL") == 0)
tio.c_iflag |= ICRNL;
else if (strcmp(token,"OCRNL") == 0)
- tio.c_oflag |= OCRNL;
+ map_o_cr_nl = true;
else if (strcmp(token,"ODELBS") == 0)
- map_odelbs = true;
+ map_o_del_bs = true;
else if (strcmp(token,"INLCRNL") == 0)
- map_inlcrnl = true;
+ map_i_nl_crnl = true;
else if (strcmp(token, "ONLCRNL") == 0)
- map_onlcrnl = true;
+ map_o_nl_crnl = true;
else
{
printf("Error: Unknown mapping flag %s\n", token);
tty_disconnect();
}
+static void optional_local_echo(char c)
+{
+ if (!option.local_echo)
+ return;
+ print(c);
+ if (option.log)
+ log_write(c);
+}
+
int tty_connect(void)
{
fd_set rdfs; /* Read file descriptor set */
rx_total++;
/* Map input character */
- if ((input_char == '\n') && (map_inlcrnl))
+ if ((input_char == '\n') && (map_i_nl_crnl))
{
print('\r');
print('\n');
if (forward)
{
/* Map output character */
- if ((output_char == 127) && (map_odelbs))
+ 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') && (map_onlcrnl)) {
+ if ((output_char == '\n') && (map_o_nl_crnl)) {
char r = '\r';
+ optional_local_echo(r);
status = write(fd, &r, 1);
if (status < 0)
warning_printf("Could not write to tty device");
}
/* 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");