From ece9e7f918b1f902d735e22c6bdd30bce60e6bc9 Mon Sep 17 00:00:00 2001 From: Martin Lund Date: Sun, 8 May 2016 00:37:27 +0200 Subject: [PATCH] Improved error handling Fixes a memory leak and avoids aggressive busy looping when problems accessing tty device. --- src/Makefile.am | 20 +++++++------ src/error.c | 35 ++++++++++++++++++++++ src/include/tio/error.h | 32 ++++++++++++++++++++ src/main.c | 6 ++++ src/tty.c | 65 ++++++++++++++++++++++++++++++----------- 5 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 src/error.c create mode 100644 src/include/tio/error.h diff --git a/src/Makefile.am b/src/Makefile.am index 545a08c..c43fba0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,14 +1,16 @@ bin_PROGRAMS = tio tio_SOURCES = tty.c \ - options.c \ - time.c \ - main.c \ - log.c \ - include/tio/tty.h \ - include/tio/options.h \ - include/tio/time.h \ - include/tio/print.h \ - include/tio/log.h + options.c \ + time.c \ + main.c \ + log.c \ + error.c \ + include/tio/tty.h \ + include/tio/options.h \ + include/tio/time.h \ + include/tio/print.h \ + include/tio/log.h \ + include/tio/error.h if ENABLE_BASH_COMPLETION bashcompletiondir=@BASH_COMPLETION_DIR@ diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..31cf870 --- /dev/null +++ b/src/error.c @@ -0,0 +1,35 @@ +/* + * tio - the simple TTY terminal I/O application + * + * Copyright (c) 2014-2016 Martin Lund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include "tio/options.h" +#include "tio/print.h" + +char *error = ""; + +void error_exit(void) +{ + if ((error[0] != 0) && (option.no_autoconnect)) + printf("Error: %s\n", error); +} diff --git a/src/include/tio/error.h b/src/include/tio/error.h new file mode 100644 index 0000000..e7609b1 --- /dev/null +++ b/src/include/tio/error.h @@ -0,0 +1,32 @@ +/* + * tio - the simple TTY terminal I/O application + * + * Copyright (c) 2014-2016 Martin Lund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef ERROR_H +#define ERROR_H + +#define TIO_SUCCESS 0 +#define TIO_ERROR 1 + +extern char *error; + +void error_exit(void); + +#endif diff --git a/src/main.c b/src/main.c index c7f9c27..cdb2d0b 100644 --- a/src/main.c +++ b/src/main.c @@ -21,9 +21,12 @@ #include #include +#include #include "tio/options.h" #include "tio/tty.h" #include "tio/log.h" +#include "tio/error.h" +#include "tio/print.h" int main(int argc, char *argv[]) { @@ -35,6 +38,9 @@ int main(int argc, char *argv[]) /* Configure output terminal */ configure_stdout(); + /* Install error exit handler */ + atexit(&error_exit); + /* Install log exit handler */ atexit(&log_exit); diff --git a/src/tty.c b/src/tty.c index 2e298c6..d8cacea 100644 --- a/src/tty.c +++ b/src/tty.c @@ -36,6 +36,7 @@ #include "tio/options.h" #include "tio/time.h" #include "tio/log.h" +#include "tio/error.h" static int connected = false; struct termios new_stdout, old_stdout, old_tio; @@ -44,22 +45,27 @@ static bool tainted = false; void wait_for_tty_device(void) { - int ready, n; - struct stat status; fd_set rdfs; + int ready, status; struct timeval tv; - char c_stdin[3]; + static char c_stdin[3]; + static bool first = true; /* Loop until device pops up */ while (true) { - /* Test for accessible device file */ - if (access(option.tty_device, R_OK) == 0) - return; - - /* Wait up to 1 second */ - tv.tv_sec = 1; - tv.tv_usec = 0; + if (first) + { + /* Don't wait first time */ + tv.tv_sec = 0; + tv.tv_usec = 1; + first = false; + } else + { + /* Wait up to 1 second */ + tv.tv_sec = 1; + tv.tv_usec = 0; + } FD_ZERO(&rdfs); FD_SET(STDIN_FILENO, &rdfs); @@ -71,7 +77,9 @@ void wait_for_tty_device(void) /* Input from stdin ready */ /* Read one character */ - n = read(STDIN_FILENO, &c_stdin[0], 1); + status = read(STDIN_FILENO, &c_stdin[0], 1); + if (status < 0) + printf("Warning: Could not read from stdin\n"); /* Exit upon ctrl-t + q sequence */ c_stdin[2] = c_stdin[1]; @@ -79,6 +87,10 @@ void wait_for_tty_device(void) if ((c_stdin[1] == KEY_Q) && (c_stdin[2] == KEY_CTRL_T)) exit(EXIT_SUCCESS); } + + /* Test for accessible device file */ + if (access(option.tty_device, R_OK) == 0) + return; } } @@ -139,18 +151,24 @@ int connect_tty(void) fd_set rdfs; /* Read file descriptor set */ int maxfd; /* Maximum file descriptor used */ static bool first = true; - int status; char c_tty; char c_stdin[3]; + int status; /* Open tty device */ fd = open(option.tty_device, O_RDWR | O_NOCTTY ); if (fd < 0) - return EXIT_FAILURE; + { + error = strerror(errno); + goto error_open; + } /* Make sure device is of tty type */ if (!isatty(fd)) - return EXIT_FAILURE; + { + error = "Not a tty device"; + goto error_isatty; + } /* Flush stale I/O data (if any) */ tcflush(fd, TCIOFLUSH); @@ -164,7 +182,7 @@ int connect_tty(void) /* Save current port settings */ if (tcgetattr(fd, &old_tio) < 0) - return EXIT_FAILURE; + goto error_tcgetattr; /* Make sure we restore tty settings on exit */ if (first) @@ -216,13 +234,16 @@ int connect_tty(void) { /* Error reading - device is likely unplugged */ disconnect_tty(); - return EXIT_FAILURE; + goto error_reading; } } if (FD_ISSET(STDIN_FILENO, &rdfs)) { /* Input from stdin ready */ status = read(STDIN_FILENO, &c_stdin[0], 1); + if (status < 0) + printf("Warning: Could not read from stdin"); + if ((c_stdin[0] != KEY_Q) && (c_stdin[0] != KEY_CTRL_T)) tainted = true; @@ -234,6 +255,8 @@ int connect_tty(void) /* Forward input to tty device */ status = write(fd, &c_stdin[0], 1); + if (status < 0) + printf("Warning: Could not write to tty device"); /* Write to log */ if (option.log) @@ -245,5 +268,13 @@ int connect_tty(void) } } - return EXIT_SUCCESS; + return TIO_SUCCESS; + +error_tcgetattr: +error_isatty: + close(fd); + connected = false; +error_reading: +error_open: + return TIO_ERROR; }