mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
Improved error handling
Fixes a memory leak and avoids aggressive busy looping when problems accessing tty device.
This commit is contained in:
parent
4c59995db8
commit
ece9e7f918
5 changed files with 132 additions and 26 deletions
|
|
@ -1,14 +1,16 @@
|
||||||
bin_PROGRAMS = tio
|
bin_PROGRAMS = tio
|
||||||
tio_SOURCES = tty.c \
|
tio_SOURCES = tty.c \
|
||||||
options.c \
|
options.c \
|
||||||
time.c \
|
time.c \
|
||||||
main.c \
|
main.c \
|
||||||
log.c \
|
log.c \
|
||||||
include/tio/tty.h \
|
error.c \
|
||||||
include/tio/options.h \
|
include/tio/tty.h \
|
||||||
include/tio/time.h \
|
include/tio/options.h \
|
||||||
include/tio/print.h \
|
include/tio/time.h \
|
||||||
include/tio/log.h
|
include/tio/print.h \
|
||||||
|
include/tio/log.h \
|
||||||
|
include/tio/error.h
|
||||||
|
|
||||||
if ENABLE_BASH_COMPLETION
|
if ENABLE_BASH_COMPLETION
|
||||||
bashcompletiondir=@BASH_COMPLETION_DIR@
|
bashcompletiondir=@BASH_COMPLETION_DIR@
|
||||||
|
|
|
||||||
35
src/error.c
Normal file
35
src/error.c
Normal file
|
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
32
src/include/tio/error.h
Normal file
32
src/include/tio/error.h
Normal file
|
|
@ -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
|
||||||
|
|
@ -21,9 +21,12 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "tio/options.h"
|
#include "tio/options.h"
|
||||||
#include "tio/tty.h"
|
#include "tio/tty.h"
|
||||||
#include "tio/log.h"
|
#include "tio/log.h"
|
||||||
|
#include "tio/error.h"
|
||||||
|
#include "tio/print.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +38,9 @@ int main(int argc, char *argv[])
|
||||||
/* Configure output terminal */
|
/* Configure output terminal */
|
||||||
configure_stdout();
|
configure_stdout();
|
||||||
|
|
||||||
|
/* Install error exit handler */
|
||||||
|
atexit(&error_exit);
|
||||||
|
|
||||||
/* Install log exit handler */
|
/* Install log exit handler */
|
||||||
atexit(&log_exit);
|
atexit(&log_exit);
|
||||||
|
|
||||||
|
|
|
||||||
65
src/tty.c
65
src/tty.c
|
|
@ -36,6 +36,7 @@
|
||||||
#include "tio/options.h"
|
#include "tio/options.h"
|
||||||
#include "tio/time.h"
|
#include "tio/time.h"
|
||||||
#include "tio/log.h"
|
#include "tio/log.h"
|
||||||
|
#include "tio/error.h"
|
||||||
|
|
||||||
static int connected = false;
|
static int connected = false;
|
||||||
struct termios new_stdout, old_stdout, old_tio;
|
struct termios new_stdout, old_stdout, old_tio;
|
||||||
|
|
@ -44,22 +45,27 @@ static bool tainted = false;
|
||||||
|
|
||||||
void wait_for_tty_device(void)
|
void wait_for_tty_device(void)
|
||||||
{
|
{
|
||||||
int ready, n;
|
|
||||||
struct stat status;
|
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
|
int ready, status;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char c_stdin[3];
|
static char c_stdin[3];
|
||||||
|
static bool first = true;
|
||||||
|
|
||||||
/* Loop until device pops up */
|
/* Loop until device pops up */
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
/* Test for accessible device file */
|
if (first)
|
||||||
if (access(option.tty_device, R_OK) == 0)
|
{
|
||||||
return;
|
/* Don't wait first time */
|
||||||
|
tv.tv_sec = 0;
|
||||||
/* Wait up to 1 second */
|
tv.tv_usec = 1;
|
||||||
tv.tv_sec = 1;
|
first = false;
|
||||||
tv.tv_usec = 0;
|
} else
|
||||||
|
{
|
||||||
|
/* Wait up to 1 second */
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO(&rdfs);
|
FD_ZERO(&rdfs);
|
||||||
FD_SET(STDIN_FILENO, &rdfs);
|
FD_SET(STDIN_FILENO, &rdfs);
|
||||||
|
|
@ -71,7 +77,9 @@ void wait_for_tty_device(void)
|
||||||
/* Input from stdin ready */
|
/* Input from stdin ready */
|
||||||
|
|
||||||
/* Read one character */
|
/* 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 */
|
/* Exit upon ctrl-t + q sequence */
|
||||||
c_stdin[2] = c_stdin[1];
|
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))
|
if ((c_stdin[1] == KEY_Q) && (c_stdin[2] == KEY_CTRL_T))
|
||||||
exit(EXIT_SUCCESS);
|
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 */
|
fd_set rdfs; /* Read file descriptor set */
|
||||||
int maxfd; /* Maximum file descriptor used */
|
int maxfd; /* Maximum file descriptor used */
|
||||||
static bool first = true;
|
static bool first = true;
|
||||||
int status;
|
|
||||||
char c_tty;
|
char c_tty;
|
||||||
char c_stdin[3];
|
char c_stdin[3];
|
||||||
|
int status;
|
||||||
|
|
||||||
/* Open tty device */
|
/* Open tty device */
|
||||||
fd = open(option.tty_device, O_RDWR | O_NOCTTY );
|
fd = open(option.tty_device, O_RDWR | O_NOCTTY );
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return EXIT_FAILURE;
|
{
|
||||||
|
error = strerror(errno);
|
||||||
|
goto error_open;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure device is of tty type */
|
/* Make sure device is of tty type */
|
||||||
if (!isatty(fd))
|
if (!isatty(fd))
|
||||||
return EXIT_FAILURE;
|
{
|
||||||
|
error = "Not a tty device";
|
||||||
|
goto error_isatty;
|
||||||
|
}
|
||||||
|
|
||||||
/* Flush stale I/O data (if any) */
|
/* Flush stale I/O data (if any) */
|
||||||
tcflush(fd, TCIOFLUSH);
|
tcflush(fd, TCIOFLUSH);
|
||||||
|
|
@ -164,7 +182,7 @@ int connect_tty(void)
|
||||||
|
|
||||||
/* Save current port settings */
|
/* Save current port settings */
|
||||||
if (tcgetattr(fd, &old_tio) < 0)
|
if (tcgetattr(fd, &old_tio) < 0)
|
||||||
return EXIT_FAILURE;
|
goto error_tcgetattr;
|
||||||
|
|
||||||
/* Make sure we restore tty settings on exit */
|
/* Make sure we restore tty settings on exit */
|
||||||
if (first)
|
if (first)
|
||||||
|
|
@ -216,13 +234,16 @@ int connect_tty(void)
|
||||||
{
|
{
|
||||||
/* Error reading - device is likely unplugged */
|
/* Error reading - device is likely unplugged */
|
||||||
disconnect_tty();
|
disconnect_tty();
|
||||||
return EXIT_FAILURE;
|
goto error_reading;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FD_ISSET(STDIN_FILENO, &rdfs))
|
if (FD_ISSET(STDIN_FILENO, &rdfs))
|
||||||
{
|
{
|
||||||
/* Input from stdin ready */
|
/* Input from stdin ready */
|
||||||
status = 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");
|
||||||
|
|
||||||
if ((c_stdin[0] != KEY_Q) && (c_stdin[0] != KEY_CTRL_T))
|
if ((c_stdin[0] != KEY_Q) && (c_stdin[0] != KEY_CTRL_T))
|
||||||
tainted = true;
|
tainted = true;
|
||||||
|
|
||||||
|
|
@ -234,6 +255,8 @@ int connect_tty(void)
|
||||||
|
|
||||||
/* Forward input to tty device */
|
/* Forward input to tty device */
|
||||||
status = write(fd, &c_stdin[0], 1);
|
status = write(fd, &c_stdin[0], 1);
|
||||||
|
if (status < 0)
|
||||||
|
printf("Warning: Could not write to tty device");
|
||||||
|
|
||||||
/* Write to log */
|
/* Write to log */
|
||||||
if (option.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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue