Martin Hundeboll <martin@hundeboll.net>
Nick Østergaard <oe.nick@gmail.com>
Adam Borowski <kilobyte@angband.pl>
+Robert Scheck <robert@fedoraproject.org>
+Dmitri Goutnik <dg@syrec.org>
Thanks to everyone who has contributed to this project.
-=== tio v1.25 ===
+=== tio v1.26 ===
+
+
+Changes since tio v1.25:
+
+ * Reconfigure stdin
+
+ Make stdin behave more raw'ish. In particular, don't
+ translate CR -> NL on input.
+
+ * Add special character map feature
+
+ Add a --map option which allows to map special characters, in particular CR and
+ NL characters which are used in various combinations on varios platforms.
+
+ * Cleanup
+
+ * Update AUTHORS
+
+ * Update README
+
+ * Mention website
+
+ * Update man page
+
Changes since tio v1.24:
-o, --output-delay <ms> Output delay (default: 0)
-n, --no-autoconnect Disable automatic connect
-l, --log <filename> Log to file
+ -m, --map <flags> Map special characters
-v, --version Display version
-h, --help Display help
4. Installation
- Installation steps (from source):
+4.1 Installation from source:
$ ./configure
$ make
See INSTALL file for more installation details.
- Installation steps (binary package):
+4.2 Installation using package:
Tio comes prepackaged for various GNU/Linux distributions. Visit
- https://tio.github.io to see package installation details.
+ https://tio.github.io for package installation details.
5. Contributing
Submit bug reports via GitHub: https://github.com/tio/tio/issues
-7. License
+7. Website
+
+ Visit https://tio.github.io
+
+
+8. License
Tio is GPLv2+. See COPYING file for license details.
-8. Authors
+9. Authors
Created by Martin Lund <martin.lund@keep-it-simple.com>
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tio 1.25.
+# Generated by GNU Autoconf 2.69 for tio 1.26.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Identity of this package.
PACKAGE_NAME='tio'
PACKAGE_TARNAME='tio'
-PACKAGE_VERSION='1.25'
-PACKAGE_STRING='tio 1.25'
+PACKAGE_VERSION='1.26'
+PACKAGE_STRING='tio 1.26'
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.25 to adapt to many kinds of systems.
+\`configure' configures tio 1.26 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.25:";;
+ short | recursive ) echo "Configuration of tio 1.26:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-tio configure 1.25
+tio configure 1.26
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.25, which was
+It was created by tio $as_me 1.26, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='tio'
- VERSION='1.25'
+ VERSION='1.26'
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.25, which was
+This file was extended by tio $as_me 1.26, 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.25
+tio config.status 1.26
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
AC_PREREQ([2.68])
-AC_INIT([tio], [1.25], [], [tio], [https://tio.github.io])
+AC_INIT([tio], [1.26], [], [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" "September 2017"
+.TH "tio" "1" "October 2017"
.SH "NAME"
tio \- a simple TTY terminal I/O application
.SH "SYNOPSIS"
.PP
.B tio
-.RI "[" <options> "] " "<tty device>"
+.RI "[" <options> "] " "<tty-device>"
.SH "DESCRIPTION"
.PP
.BR \-l ", " "\-\-log " \fI<filename>
Log to file.
+
+.TP
+.BR \-m ", " "\-\-map " \fI<flags>
+
+Map (replace, translate) special characters on input or output. The following mapping flags are supported:
+
+.RS
+.TP 8n
+.IP "\fBINLCR"
+Translate NL to CR on input.
+.IP "\fBIGNCR"
+Ignore carriage return on input.
+.IP "\fBICRNL"
+Translate carriage return to newline on input (unless IGNCR is set).
+.IP "\fBONLCR"
+Map NL to CR-NL on output.
+.IP "\fBOCRNL"
+Map CR to NL on output.
+.P
+If defining more than one flag, the flags must be comma separated.
+.RE
+
.TP
.BR \-v ", " \-\-version
Using serial devices by id ensures that tio automatically reconnects to the
correct serial device if the device is disconnected and then reconnected.
+.SH "WEBSITE"
+.PP
+Visit https://tio.github.io
+
.SH "AUTHOR"
.PP
Written by Martin Lund <martin.lund@keep\-it\-simple.com>.
-o --output-delay \
-n --no-autoconnect \
-l --log \
+ -m --map \
-v --version \
-h --help"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
;;
+ -m | --map)
+ COMPREPLY=( $(compgen -W "INLCR IGNCR ICRNL ONLCR OCRNL" -- ${cur}) )
+ return 0
+ ;;
-v | --version)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
bool no_autoconnect;
bool log;
const char *log_filename;
+ const char *map;
};
extern struct option_t option;
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);
/* Configure tty device */
tty_configure();
+ /* Configure input terminal */
+ stdin_configure();
+
/* Configure output terminal */
stdout_configure();
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <errno.h>
#include <getopt.h>
#include <termios.h>
0, // No output delay
false, // No autoconnect
false, // No log
- "" // Log filename
+ "", // Log filename
+ "" // Map string
};
void print_help(char *argv[])
printf(" -o, --output-delay <ms> Output delay (default: 0)\n");
printf(" -n, --no-autoconnect Disable automatic connect\n");
printf(" -l, --log <filename> Log to file\n");
+ printf(" -m, --map <flags> Map special characters\n");
printf(" -v, --version Display version\n");
printf(" -h, --help Display help\n");
printf("\n");
{"output-delay", required_argument, 0, 'o'},
{"no-autoconnect", no_argument, 0, 'n'},
{"log", required_argument, 0, 'l'},
+ {"map", required_argument, 0, 'm'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0 }
int option_index = 0;
/* Parse argument using getopt_long */
- c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:vh", long_options, &option_index);
+ c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:m:vh", long_options, &option_index);
/* Detect the end of the options */
if (c == -1)
option.log_filename = optarg;
break;
+ case 'm':
+ option.map = optarg;
+ break;
+
case 'v':
printf("tio v%s\n", VERSION);
printf("Copyright (c) 2014-2017 Martin Lund\n");
#include "tio/log.h"
#include "tio/error.h"
-static struct termios tio, new_stdout, old_stdout, old_tio;
+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;
static bool tainted = false;
tio_printf(" Stopbits: %d", option.stopbits);
tio_printf(" Parity: %s", option.parity);
tio_printf(" Output delay: %d", option.output_delay);
+ if (option.map[0] != 0)
+ tio_printf(" Map flags: %s", option.map);
if (option.log)
tio_printf(" Log file: %s", option.log_filename);
break;
}
}
+void stdin_configure(void)
+{
+ int status;
+
+ /* Save current stdin settings */
+ if (tcgetattr(STDIN_FILENO, &stdin_old) < 0)
+ {
+ error_printf("Saving current stdin settings failed");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Prepare new stdin settings */
+ 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);
+
+ /* Control characters */
+ stdin_new.c_cc[VTIME] = 0; /* Inter-character timer unused */
+ stdin_new.c_cc[VMIN] = 1; /* Blocking read until 1 character received */
+
+ /* Activate new stdin settings */
+ status = tcsetattr(STDIN_FILENO, TCSANOW, &stdin_new);
+ if (status == -1)
+ {
+ error_printf("Could not apply new stdin settings (%s)", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Make sure we restore old stdin settings on exit */
+ atexit(&stdin_restore);
+}
+
+void stdin_restore(void)
+{
+ tcsetattr(STDIN_FILENO, TCSANOW, &stdin_old);
+}
+
void stdout_configure(void)
{
int status;
/* Save current stdout settings */
- if (tcgetattr(STDOUT_FILENO, &old_stdout) < 0)
+ if (tcgetattr(STDOUT_FILENO, &stdout_old) < 0)
{
error_printf("Saving current stdio settings failed");
exit(EXIT_FAILURE);
}
/* Prepare new stdout settings */
- memcpy(&new_stdout, &old_stdout, sizeof(old_stdout));
+ memcpy(&stdout_new, &stdout_old, sizeof(stdout_old));
/* Reconfigure stdout (RAW configuration) */
- new_stdout.c_oflag &= ~(OPOST);
- new_stdout.c_lflag &= ~(ECHO|ICANON|ISIG|ECHOE|ECHOK|ECHONL);
+ stdout_new.c_oflag &= ~(OPOST);
+ stdout_new.c_lflag &= ~(ECHO|ICANON|ISIG|ECHOE|ECHOK|ECHONL);
/* Control characters */
- new_stdout.c_cc[VTIME] = 0; /* Inter-character timer unused */
- new_stdout.c_cc[VMIN] = 1; /* Blocking read until 1 character received */
+ stdout_new.c_cc[VTIME] = 0; /* Inter-character timer unused */
+ stdout_new.c_cc[VMIN] = 1; /* Blocking read until 1 character received */
/* Activate new stdout settings */
- status = tcsetattr(STDOUT_FILENO, TCSANOW, &new_stdout);
+ status = tcsetattr(STDOUT_FILENO, TCSANOW, &stdout_new);
if (status == -1)
{
error_printf("Could not apply new stdout settings (%s)", strerror(errno));
void stdout_restore(void)
{
- tcsetattr(STDOUT_FILENO, TCSANOW, &old_stdout);
+ tcsetattr(STDOUT_FILENO, TCSANOW, &stdout_old);
}
void tty_configure(void)
{
+ bool token_found = true;
+ char *token = NULL;
+ char *buffer;
int status;
speed_t baudrate;
error_printf("Invalid parity");
exit(EXIT_FAILURE);
}
+
+ /* Control, input, output, local modes for tty device */
+ tio.c_cflag |= CLOCAL | CREAD;
+ tio.c_oflag = 0;
+ tio.c_lflag = 0;
+
+ /* Control characters */
+ tio.c_cc[VTIME] = 0; // Inter-character timer unused
+ tio.c_cc[VMIN] = 1; // Blocking read until 1 character received
+
+ /* Configure any specified input or output mappings */
+
+ buffer = strdup(option.map);
+ 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,"ONLCR") == 0)
+ tio.c_oflag |= ONLCR;
+ else if (strcmp(token,"OCRNL") == 0)
+ tio.c_oflag |= OCRNL;
+ else
+ {
+ printf("Error: Unknown mapping flag %s\n", token);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ token_found = false;
+ }
+ free(buffer);
}
void tty_wait_for_device(void)
void tty_restore(void)
{
- tcsetattr(fd, TCSANOW, &old_tio);
+ tcsetattr(fd, TCSANOW, &tio_old);
if (connected)
tty_disconnect();
tainted = false;
/* Save current port settings */
- if (tcgetattr(fd, &old_tio) < 0)
+ if (tcgetattr(fd, &tio_old) < 0)
goto error_tcgetattr;
/* Make sure we restore tty settings on exit */
first = false;
}
- /* Control, input, output, local modes for tty device */
- tio.c_cflag |= CLOCAL | CREAD;
- tio.c_oflag = 0;
- tio.c_lflag = 0;
-
- /* Control characters */
- tio.c_cc[VTIME] = 0; /* Inter-character timer unused */
- tio.c_cc[VMIN] = 1; /* Blocking read until 1 character received */
-
/* Activate new port settings */
status = tcsetattr(fd, TCSANOW, &tio);
if (status == -1)