]> git.sur5r.net Git - tio/blobdiff - src/tty.c
New upstream version 2.4
[tio] / src / tty.c
index 75c724230b34de2f0fad913bfbb2354892292af7..faad20c3a25324266d8acd7c3d3c073eab94ac91 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
@@ -40,6 +40,7 @@
 #include <errno.h>
 #include <time.h>
 #include <dirent.h>
+#include <pthread.h>
 #include "config.h"
 #include "configfile.h"
 #include "tty.h"
@@ -80,6 +81,8 @@
 #define KEY_B 0x62
 #define KEY_C 0x63
 #define KEY_E 0x65
+#define KEY_F 0x66
+#define KEY_SHIFT_F 0x46
 #define KEY_G 0x67
 #define KEY_H 0x68
 #define KEY_L 0x6C
@@ -133,6 +136,9 @@ static unsigned char hex_char_index = 0;
 static char tty_buffer[BUFSIZ*2];
 static size_t tty_buffer_count = 0;
 static char *tty_buffer_write_ptr = tty_buffer;
+static pthread_t thread;
+static int pipefd[2];
+static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER;
 
 static void optional_local_echo(char c)
 {
@@ -255,6 +261,99 @@ ssize_t tty_write(int fd, const void *buffer, size_t count)
     return bytes_written;
 }
 
+void *tty_stdin_input_thread(void *arg)
+{
+    UNUSED(arg);
+    char input_buffer[BUFSIZ];
+    ssize_t byte_count;
+    ssize_t bytes_written;
+
+    // Create FIFO pipe
+    if (pipe(pipefd) == -1)
+    {
+        tio_error_printf("Failed to create pipe");
+        exit(EXIT_FAILURE);
+    }
+
+    // Signal that input pipe is ready
+    pthread_mutex_unlock(&mutex_input_ready);
+
+    // Input loop for stdin
+    while (1)
+    {
+        /* Input from stdin ready */
+        byte_count = read(STDIN_FILENO, input_buffer, BUFSIZ);
+        if (byte_count < 0)
+        {
+            tio_warning_printf("Could not read from stdin (%s)", strerror(errno));
+        }
+        else if (byte_count == 0)
+        {
+            // Close write end to signal EOF in read end
+            close(pipefd[1]);
+            pthread_exit(0);
+        }
+
+        if (interactive_mode)
+        {
+            static char previous_char = 0;
+            char input_char;
+
+            // Process quit and flush key command
+            for (int i = 0; i<byte_count; i++)
+            {
+                input_char = input_buffer[i];
+
+                if (previous_char == option.prefix_code)
+                {
+                    switch (input_char)
+                    {
+                        case KEY_Q:
+                            exit(EXIT_FAILURE);
+                            break;
+                        case KEY_SHIFT_F:
+                            tio_printf("Flushed data I/O channels")
+                            tcflush(fd, TCIOFLUSH);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                previous_char = input_char;
+            }
+        }
+
+        // Write all bytes read to pipe
+        while (byte_count)
+        {
+            bytes_written = write(pipefd[1], input_buffer, byte_count);
+            if (bytes_written < 0)
+            {
+                tio_warning_printf("Could not write to pipe (%s)", strerror(errno));
+                break;
+            }
+            byte_count -= bytes_written;
+        }
+    }
+
+    pthread_exit(0);
+}
+
+void tty_input_thread_create(void)
+{
+    pthread_mutex_lock(&mutex_input_ready);
+
+    if (pthread_create(&thread, NULL, tty_stdin_input_thread, NULL) != 0) {
+        tio_error_printf("pthread_create() error");
+        exit(1);
+    }
+}
+
+void tty_input_thread_wait_ready(void)
+{
+    pthread_mutex_lock(&mutex_input_ready);
+}
+
 static void output_hex(char c)
 {
     hex_chars[hex_char_index++] = c;
@@ -348,12 +447,13 @@ static void toggle_line(const char *line_name, int mask, enum line_mode_t line_m
     }
 }
 
-void handle_command_sequence(char input_char, char previous_char, char *output_char, bool *forward)
+void handle_command_sequence(char input_char, char *output_char, bool *forward)
 {
     char unused_char;
     bool unused_bool;
     int state;
     static enum line_mode_t line_mode = LINE_OFF;
+    static char previous_char = 0;
 
     /* Ignore unused arguments */
     if (output_char == NULL)
@@ -406,6 +506,16 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
         /* Do not forward input char to output by default */
         *forward = false;
 
+        /* Handle special double prefix key input case */
+        if (input_char == option.prefix_code)
+        {
+            /* Forward prefix character to tty */
+            *output_char = option.prefix_code;
+            *forward = true;
+            previous_char = 0;
+            return;
+        }
+
         switch (input_char)
         {
             case KEY_QUESTION:
@@ -414,6 +524,8 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf(" ctrl-%c b       Send break", option.prefix_key);
                 tio_printf(" ctrl-%c c       Show configuration", option.prefix_key);
                 tio_printf(" ctrl-%c e       Toggle local echo mode", option.prefix_key);
+                tio_printf(" ctrl-%c f       Toggle log to file", option.prefix_key);
+                tio_printf(" ctrl-%c F       Flush data I/O buffers", option.prefix_key);
                 tio_printf(" ctrl-%c g       Toggle serial port line", option.prefix_key);
                 tio_printf(" ctrl-%c h       Toggle hexadecimal mode", option.prefix_key);
                 tio_printf(" ctrl-%c l       Clear screen", option.prefix_key);
@@ -443,6 +555,25 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 tio_printf(" RI : %s", (state & TIOCM_RI) ? "HIGH" : "LOW");
                 break;
 
+            case KEY_F:
+                if (option.log)
+                {
+                    log_close();
+                    option.log = false;
+                }
+                else
+                {
+                    if (log_open(option.log_filename) == 0)
+                    {
+                        option.log = true;
+                    }
+                }
+                tio_printf("Switched log to file %s", option.log ? "on" : "off");
+                break;
+
+            case KEY_SHIFT_F:
+                break;
+
             case KEY_G:
                 tio_printf("Please enter which serial line number to toggle:");
                 tio_printf(" DTR (0)");
@@ -473,8 +604,8 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
 
             case KEY_C:
                 tio_printf("Configuration:");
-                config_file_print();
                 options_print();
+                config_file_print();
                 if (option.rs485)
                 {
                     rs485_print_config();
@@ -570,27 +701,12 @@ void handle_command_sequence(char input_char, char previous_char, char *output_c
                 break;
 
             default:
-                /* Handle double prefix key input case */
-                if (input_char == option.prefix_code)
-                {
-                    static int count = 0;
-                    if (count++ == 1)
-                    {
-                        // Do not forward prefix characters excessively
-                        count = 0;
-                        break;
-                    }
-
-                    /* Forward prefix character to tty */
-                    *output_char = option.prefix_code;
-                    *forward = true;
-                    break;
-                }
-
                 /* Ignore unknown ctrl-t escaped keys */
                 break;
         }
     }
+
+    previous_char = input_char;
 }
 
 void stdin_restore(void)
@@ -907,7 +1023,7 @@ void tty_wait_for_device(void)
     int    status;
     int    maxfd;
     struct timeval tv;
-    static char input_char, previous_char = 0;
+    static char input_char;
     static bool first = true;
     static int last_errno = 0;
 
@@ -933,19 +1049,19 @@ void tty_wait_for_device(void)
             }
 
             FD_ZERO(&rdfs);
-            FD_SET(STDIN_FILENO, &rdfs);
-            maxfd = MAX(STDIN_FILENO, socket_add_fds(&rdfs, false));
+            FD_SET(pipefd[0], &rdfs);
+            maxfd = MAX(pipefd[0], 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))
+                if (FD_ISSET(pipefd[0], &rdfs))
                 {
                     /* Input from stdin ready */
 
                     /* Read one character */
-                    status = read(STDIN_FILENO, &input_char, 1);
+                    status = read(pipefd[0], &input_char, 1);
                     if (status <= 0)
                     {
                         tio_error_printf("Could not read from stdin");
@@ -953,9 +1069,7 @@ void tty_wait_for_device(void)
                     }
 
                     /* Handle commands */
-                    handle_command_sequence(input_char, previous_char, NULL, NULL);
-
-                    previous_char = input_char;
+                    handle_command_sequence(input_char, NULL, NULL);
                 }
                 socket_handle_input(&rdfs, NULL);
             }
@@ -1077,7 +1191,6 @@ int tty_connect(void)
     int    maxfd;          /* Maximum file descriptor used */
     char   input_char, output_char;
     char   input_buffer[BUFSIZ];
-    static char previous_char = 0;
     static bool first = true;
     int    status;
     bool   next_timestamp = false;
@@ -1189,9 +1302,9 @@ int tty_connect(void)
         FD_SET(fd, &rdfs);
         if (!ignore_stdin)
         {
-            FD_SET(STDIN_FILENO, &rdfs);
+            FD_SET(pipefd[0], &rdfs);
         }
-        maxfd = MAX(fd, STDIN_FILENO);
+        maxfd = MAX(fd, pipefd[0]);
         maxfd = MAX(maxfd, socket_add_fds(&rdfs, true));
 
         /* Manage timeout */
@@ -1298,10 +1411,10 @@ int tty_connect(void)
                     }
                 }
             }
-            else if (FD_ISSET(STDIN_FILENO, &rdfs))
+            else if (FD_ISSET(pipefd[0], &rdfs))
             {
                 /* Input from stdin ready */
-                ssize_t bytes_read = read(STDIN_FILENO, input_buffer, BUFSIZ);
+                ssize_t bytes_read = read(pipefd[0], input_buffer, BUFSIZ);
                 if (bytes_read < 0)
                 {
                     tio_error_printf_silent("Could not read from stdin (%s)", strerror(errno));
@@ -1345,10 +1458,7 @@ int tty_connect(void)
                         }
 
                         /* Handle commands */
-                        handle_command_sequence(input_char, previous_char, &output_char, &forward);
-
-                        /* Save previous key */
-                        previous_char = input_char;
+                        handle_command_sequence(input_char, &output_char, &forward);
 
                         if ((option.hex_mode) && (forward))
                         {
@@ -1370,6 +1480,7 @@ int tty_connect(void)
             }
             else
             {
+                /* Input from socket ready */
                 forward = socket_handle_input(&rdfs, &output_char);
 
                 if (forward)