From bbda0b8851ebb791f6ad997fa39b121650ad6528 Mon Sep 17 00:00:00 2001 From: Martin Lund Date: Sun, 1 May 2016 21:18:51 +0200 Subject: [PATCH] Added log feature Added "--log " option which writes all activity to specified file. --- README | 1 + man/gotty.1 | 4 +++ src/bash-completion/gotty | 5 +++ src/include/gotty/log.h | 30 ++++++++++++++++++ src/include/gotty/options.h | 4 ++- src/log.c | 62 +++++++++++++++++++++++++++++++++++++ src/main.c | 11 +++++++ src/options.c | 17 ++++++++-- src/tty.c | 10 ++++++ 9 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/include/gotty/log.h create mode 100644 src/log.c diff --git a/README b/README index 2f1ab62..a90dabb 100644 --- a/README +++ b/README @@ -29,6 +29,7 @@ -p, --parity even|odd|none Parity (default: none) -o, --output-delay Output delay (default: 0) -n, --no-autoconnect Disable automatic connect + -l, --log Log to file -v, --version Display version -h, --help Display help diff --git a/man/gotty.1 b/man/gotty.1 index 93d7076..a09129e 100644 --- a/man/gotty.1 +++ b/man/gotty.1 @@ -47,6 +47,10 @@ Set output delay [ms] - delay inserted between each transmitted character (defau Disable automatic connect. .TP +.B \-l, \--log + +Log to file. +.TP .B \-v, \--version Display program version. diff --git a/src/bash-completion/gotty b/src/bash-completion/gotty index 14ed2c1..b03642a 100644 --- a/src/bash-completion/gotty +++ b/src/bash-completion/gotty @@ -17,6 +17,7 @@ _gotty() -p --parity \ -o --output-delay \ -n --no-autoconnect \ + -l --log \ -v --version \ -h --help" @@ -79,6 +80,10 @@ _gotty() COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; + -l | --log) + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; -v | --version) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 diff --git a/src/include/gotty/log.h b/src/include/gotty/log.h new file mode 100644 index 0000000..f50284b --- /dev/null +++ b/src/include/gotty/log.h @@ -0,0 +1,30 @@ +/* + * Go TTY - The Really Simple Terminal 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 LOG_H +#define LOG_H + +void log_open(char *filename); +void log_write(char c); +void log_close(void); +void log_exit(void); + +#endif diff --git a/src/include/gotty/options.h b/src/include/gotty/options.h index 6efe292..1470964 100644 --- a/src/include/gotty/options.h +++ b/src/include/gotty/options.h @@ -31,9 +31,11 @@ struct option_t { char tty_device[MAXPATHLEN]; + bool log; + char log_filename[_POSIX_ARG_MAX]; bool no_autoconnect; - struct termios tio; int output_delay; + struct termios tio; }; extern struct option_t option; diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..39e2ffd --- /dev/null +++ b/src/log.c @@ -0,0 +1,62 @@ +/* + * Go TTY - The Really Simple Terminal 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 "gotty/options.h" +#include "gotty/print.h" + +static FILE *fp; +static bool error = false; + +void log_open(char *filename) +{ + fp = fopen(filename, "w+"); + + if (fp == NULL) + { + error = true; + exit(EXIT_FAILURE); + } +} + +void log_write(char c) +{ + if (fp != NULL) + fputc(c, fp); +} + +void log_close(void) +{ + if (fp != NULL) + fclose(fp); +} + +void log_exit(void) +{ + if (option.log) + log_close(); + + if (error) + printf("Error: Could not open log file %s (%s)\n", option.log_filename, strerror(errno)); +} diff --git a/src/main.c b/src/main.c index 7b8315a..50a2ee1 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ #include #include "gotty/options.h" #include "gotty/tty.h" +#include "gotty/log.h" int main(int argc, char *argv[]) { @@ -34,9 +35,16 @@ int main(int argc, char *argv[]) /* Configure output terminal */ configure_stdout(); + /* Install log exit handler */ + atexit(&log_exit); + /* Restore output terminal on exit */ atexit(&restore_stdout); + /* Create log file */ + if (option.log) + log_open(option.log_filename); + /* Connect to tty device */ if (option.no_autoconnect) status = connect_tty(); @@ -50,5 +58,8 @@ int main(int argc, char *argv[]) } } + /* Close log */ + log_close(); + return status; } diff --git a/src/options.c b/src/options.c index 554a2cc..ae80f00 100644 --- a/src/options.c +++ b/src/options.c @@ -27,14 +27,18 @@ #include #include #include +#include #include "config.h" #include "gotty/options.h" #include "gotty/print.h" struct option_t option = { - "", /* Device name */ - false, /* No autoconnect */ + "", // Device name + false, // No log + "", // Log filename + false, // No autoconnect + 0, // No output delay }; void print_options_help(char *argv[]) @@ -49,6 +53,7 @@ void print_options_help(char *argv[]) printf(" -p, --parity odd|even|none Parity (default: none)\n"); printf(" -o, --output-delay Output delay (default: 0)\n"); printf(" -n, --no-autoconnect Disable automatic connect\n"); + printf(" -l, --log Log to file\n"); printf(" -v, --version Display version\n"); printf(" -h, --help Display help\n"); printf("\n"); @@ -88,6 +93,7 @@ void parse_options(int argc, char *argv[]) {"parity", required_argument, 0, 'p'}, {"output-delay", required_argument, 0, 'o'}, {"no-autoconnect", no_argument, 0, 'n'}, + {"log", required_argument, 0, 'l'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0 } @@ -97,7 +103,7 @@ void parse_options(int argc, char *argv[]) int option_index = 0; /* Parse argument using getopt_long */ - c = getopt_long(argc, argv, "b:d:f:s:p:o:nvh", long_options, &option_index); + c = getopt_long(argc, argv, "b:d:f:s:p:o:nl:vh", long_options, &option_index); /* Detect the end of the options */ if (c == -1) @@ -306,6 +312,11 @@ void parse_options(int argc, char *argv[]) option.no_autoconnect = true; break; + case 'l': + option.log = true; + strncpy(option.log_filename, optarg, _POSIX_ARG_MAX); + break; + case 'v': printf("Go TTY v%s\n", VERSION); printf("Copyright (c) 2014-2016 Martin Lund\n"); diff --git a/src/tty.c b/src/tty.c index 007e3d7..1cd1471 100644 --- a/src/tty.c +++ b/src/tty.c @@ -35,6 +35,7 @@ #include "gotty/print.h" #include "gotty/options.h" #include "gotty/time.h" +#include "gotty/log.h" static int connected = false; struct termios new_stdout, old_stdout, old_tio; @@ -204,6 +205,11 @@ int connect_tty(void) /* Print received tty character to stdout */ putchar(c_tty); fflush(stdout); + + /* Write to log */ + if (option.log) + log_write(c_tty); + if (c_tty != 0x7) // Small trick to avoid ctrl-g echo tainted = true; } else @@ -229,6 +235,10 @@ int connect_tty(void) /* Forward input to tty device */ status = write(fd, &c_stdin[0], 1); + /* Write to log */ + if (option.log) + log_write(c_stdin[0]); + /* Insert output delay */ if (option.output_delay) usleep(option.output_delay * 1000);