Quit from non-interactive mode using ctrl-c

When piping to tio it will automatically enter "non-interactive" mode
which means it will not react to any input key sequences but simple read
the input stream and write it to the tty device.

This also means that ctrl-t q can not be used to quit and so tio would
hang forever when used in non-interactive mode.

This change allows to send the standard termination signal by pressing
ctrl-c on tio in non-interactive mode to make it quit.
This commit is contained in:
Martin Lund 2022-07-20 17:59:13 +02:00
parent eadcc7e384
commit 5f46136b28
3 changed files with 77 additions and 45 deletions

View file

@ -96,6 +96,10 @@ int main(int argc, char *argv[])
if (interactive_mode) if (interactive_mode)
{ {
tio_printf("Press ctrl-%c q to quit", option.prefix_key); tio_printf("Press ctrl-%c q to quit", option.prefix_key);
} else
{
tio_printf("Non-interactive mode enabled");
tio_printf("Press ctrl-c to quit");
} }
/* Open socket */ /* Open socket */
@ -105,7 +109,7 @@ int main(int argc, char *argv[])
} }
/* Connect to tty device */ /* Connect to tty device */
if ((option.no_autoconnect) || (!interactive_mode)) if (option.no_autoconnect)
{ {
status = tty_connect(); status = tty_connect();
} }

View file

@ -27,15 +27,24 @@
#include "error.h" #include "error.h"
#include "print.h" #include "print.h"
#include "misc.h" #include "misc.h"
#include "tty.h"
static void signal_handler(int signum) static void signal_handler(int signum)
{ {
UNUSED(signum); switch (signum)
tio_printf("Received hangup signal!"); {
case SIGHUP:
tio_printf("Received SIGHUP signal!");
break;
case SIGINT:
tio_printf("Received SIGINT signal!");
break;
}
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void signal_handlers_install(void) void signal_handlers_install(void)
{ {
signal(SIGHUP, signal_handler); signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
} }

103
src/tty.c
View file

@ -586,6 +586,12 @@ void stdout_configure(void)
/* Reconfigure stdout (RAW configuration) */ /* Reconfigure stdout (RAW configuration) */
cfmakeraw(&stdout_new); cfmakeraw(&stdout_new);
/* Allow ^C / SIGINT (to allow termination when piping to tio) */
if (!interactive_mode)
{
stdout_new.c_lflag |= ISIG;
}
/* Control characters */ /* Control characters */
stdout_new.c_cc[VTIME] = 0; /* Inter-character timer unused */ stdout_new.c_cc[VTIME] = 0; /* Inter-character timer unused */
stdout_new.c_cc[VMIN] = 1; /* Blocking read until 1 character received */ stdout_new.c_cc[VMIN] = 1; /* Blocking read until 1 character received */
@ -833,51 +839,56 @@ void tty_wait_for_device(void)
/* Loop until device pops up */ /* Loop until device pops up */
while (true) while (true)
{ {
if (first) if (interactive_mode)
{ {
/* Don't wait first time */ /* In interactive mode, while waiting for tty device, we need to
tv.tv_sec = 0; * read from stdin to react on input key commands. */
tv.tv_usec = 1; if (first)
first = false;
}
else
{
/* Wait up to 1 second */
tv.tv_sec = 1;
tv.tv_usec = 0;
}
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(maxfd + 1, &rdfs, NULL, NULL, &tv);
if (status > 0)
{
if (FD_ISSET(STDIN_FILENO, &rdfs))
{ {
/* Input from stdin ready */ /* Don't wait first time */
tv.tv_sec = 0;
/* Read one character */ tv.tv_usec = 1;
status = read(STDIN_FILENO, &input_char, 1); first = false;
if (status <= 0) }
{ else
tio_error_printf("Could not read from stdin"); {
exit(EXIT_FAILURE); /* Wait up to 1 second for input */
} tv.tv_sec = 1;
tv.tv_usec = 0;
/* Handle commands */ }
handle_command_sequence(input_char, previous_char, NULL, NULL);
FD_ZERO(&rdfs);
previous_char = input_char; FD_SET(STDIN_FILENO, &rdfs);
maxfd = MAX(STDIN_FILENO, socket_add_fds(&rdfs, false));
/* Block until input becomes available or timeout */
status = select(maxfd + 1, &rdfs, NULL, NULL, &tv);
if (status > 0)
{
if (FD_ISSET(STDIN_FILENO, &rdfs))
{
/* Input from stdin ready */
/* Read one character */
status = read(STDIN_FILENO, &input_char, 1);
if (status <= 0)
{
tio_error_printf("Could not read from stdin");
exit(EXIT_FAILURE);
}
/* Handle commands */
handle_command_sequence(input_char, previous_char, NULL, NULL);
previous_char = input_char;
}
socket_handle_input(&rdfs, NULL);
}
else if (status == -1)
{
tio_error_printf("select() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
} }
socket_handle_input(&rdfs, NULL);
}
else if (status == -1)
{
tio_error_printf("select() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
} }
/* Test for accessible device file */ /* Test for accessible device file */
@ -893,6 +904,14 @@ void tty_wait_for_device(void)
tio_printf("Waiting for tty device.."); tio_printf("Waiting for tty device..");
last_errno = errno; last_errno = errno;
} }
if (!interactive_mode)
{
/* In non-interactive mode we do not need to handle input key
* commands so we simply sleep 1 second between checking for
* presence of tty device */
sleep(1);
}
} }
} }