Code

Added __attribute__((format(printf, ...))) where appropriate.
[sysdb.git] / src / tools / sysdb / input.c
index c42390f2d1fafd29801523449bbaa1a0c7192e7e..55a074cd3863f8a39fa947a7f96cba2d8822488f 100644 (file)
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * This module implements the core of the command line tool. It handles all
+ * input from the user and the remote server, interacting with the scanner and
+ * command handling as needed.
+ *
+ * The main loop is managed by the flex scanner which parses the user input.
+ * It will call into this module (using sdb_input_readline()) whenever it
+ * needs further input to continue parsing. Whenever it finds a full query
+ * (terminated by a semicolon), it will hand the query back to this module
+ * (using sdb_input_exec_query()) which will then execute it.
+ *
+ * Most of the process life-time will be spend waiting for input. User input
+ * and (asynchronous) server replies are handled at the same time.
+ */
+
 #if HAVE_CONFIG_H
 #      include "config.h"
 #endif /* HAVE_CONFIG_H */
 #include "tools/sysdb/input.h"
 #include "tools/sysdb/command.h"
 
+#include "utils/error.h"
 #include "utils/strbuf.h"
 
+#include <errno.h>
+
 #include <sys/select.h>
 
 #include <stdio.h>
@@ -61,6 +79,8 @@
 #      endif
 #endif /* READLINEs */
 
+extern int yylex(void);
+
 /*
  * public variables
  */
@@ -109,11 +129,11 @@ handle_input(char *line)
                return;
        }
 
-       sdb_strbuf_append(sysdb_input->input, line);
-       sdb_strbuf_append(sysdb_input->input, "\n");
+       sdb_strbuf_append(sysdb_input->input, "%s\n", line);
        free(line);
 
-       rl_callback_handler_remove();
+       if (sysdb_input->interactive)
+               rl_callback_handler_remove();
 } /* handle_input */
 
 /* wait for a new line of data to be available */
@@ -127,13 +147,19 @@ input_readline(void)
 
        const char *prompt = "sysdb=> ";
 
+       len = sdb_strbuf_len(sysdb_input->input);
+
+       if (! sysdb_input->interactive) {
+               char *line = readline("");
+               handle_input(line);
+               return (ssize_t)(sdb_strbuf_len(sysdb_input->input) - len);
+       }
+
        if (sysdb_input->query_len)
                prompt = "sysdb-> ";
 
        rl_callback_handler_install(prompt, handle_input);
        client_fd = sdb_client_sockfd(sysdb_input->client);
-
-       len = sdb_strbuf_len(sysdb_input->input);
        while ((sdb_strbuf_len(sysdb_input->input) == len)
                        && (! sysdb_input->eof)) {
                int n;
@@ -161,10 +187,18 @@ input_readline(void)
                if (! FD_ISSET(client_fd, &fds))
                        continue;
 
+               if (sdb_client_eof(sysdb_input->client)) {
+                       /* XXX: try to reconnect */
+                       printf("\n");
+                       sdb_log(SDB_LOG_ERR, "Remote side closed the connection.");
+                       /* return EOF */
+                       return 0;
+               }
+
                /* some response / error message from the server pending */
                /* XXX: clear current line */
                printf("\n");
-               sdb_command_print_reply(sysdb_input);
+               sdb_command_print_reply(sysdb_input->client);
                rl_forced_update_display();
        }
 
@@ -182,15 +216,22 @@ sdb_input_init(sdb_input_t *input)
        /* register input handler */
        sysdb_input = input;
 
-       if (! isatty(STDIN_FILENO))
-               return -1;
-
-       term_rawmode();
+       input->interactive = isatty(STDIN_FILENO) != 0;
+       errno = 0;
+       if (input->interactive)
+               term_rawmode();
        return 0;
 } /* sdb_input_init */
 
+int
+sdb_input_mainloop(void)
+{
+       yylex();
+       return 0;
+} /* sdb_input_mainloop */
+
 ssize_t
-sdb_input_readline(char *buf, int *n_chars, size_t max_chars)
+sdb_input_readline(char *buf, size_t *n_chars, size_t max_chars)
 {
        const char *data;
        size_t len;